DEV Community

Cover image for How to Use Magento 2 API: Complete E-commerce Integration Guide (2026)
Wanda
Wanda

Posted on • Originally published at apidog.com

How to Use Magento 2 API: Complete E-commerce Integration Guide (2026)

TL;DR

The Magento 2 (Adobe Commerce) API lets you programmatically integrate with e-commerce stores using REST, SOAP, and GraphQL. Authentication is via OAuth 1.0a and token-based methods. You get access to products, orders, customers, inventory, and more—with configurable rate limits. This guide covers authentication, CRUD, webhooks, custom endpoints, and deployment strategies.

Try Apidog today


Introduction

Adobe Commerce (Magento) powers over 250,000 e-commerce stores and $155B+ in annual GMV. API integration is essential for developers building integrations, ERP connectors, or mobile apps.

Manual Magento data entry across sales channels can cost merchants 20–30 hours per week. A robust Magento API integration automates product sync, order processing, inventory updates, and customer management.

This guide is a practical walk-through of Magento 2 API integration: authentication (OAuth/token), REST/SOAP/GraphQL endpoints, product/order management, webhooks, custom APIs, and deployment. Follow these steps for a production-ready integration.

💡 Tip: Apidog simplifies API integration testing—test endpoints, validate auth flows, inspect responses, mock APIs, and share scenarios with your team.


What Is the Magento 2 API?

Magento 2 gives you three API types:

  • REST API: JSON-based for web/mobile
  • SOAP API: XML-based for enterprise systems
  • GraphQL: Flexible queries for frontend/PWA

API coverage includes:

  • Products, categories, inventory
  • Orders, invoices, shipments
  • Customers, groups
  • Cart, checkout
  • Promotions, pricing rules
  • CMS content
  • Store config

Key Features

Feature Description
Multiple Protocols REST, SOAP, GraphQL
OAuth 1.0a Secure third-party access
Token Auth Admin and integration tokens
Webhooks Async operations via queues
Rate Limiting Configurable per installation
Custom Endpoints Extend with custom APIs
Multi-Store Single API, multiple storeviews

API Comparison

API Type Protocol Use Case
REST JSON Mobile apps, integrations
SOAP XML Enterprise (SAP, Oracle, etc.)
GraphQL GraphQL Storefront, PWA

Magento Versions

Version Status End of Support
Magento 2.4.x Current Active
Adobe Commerce 2.4.x Current Active
Magento 1.x EOL June 2020 (Do not use)

Getting Started: Authentication Setup

Step 1: Create Admin Account or Integration

  1. Log in to Magento Admin Panel
  2. Go to System > Permissions > All Users — create admin user (for admin token)
  3. Or, go to System > Extensions > Integrations — create integration (for OAuth)

Step 2: Choose Authentication Method

Method Best For Token Lifetime
Admin Token Internal integrations Configurable (default 4h)
Integration Token Third-party apps Until revoked
OAuth 1.0a Public marketplace Until revoked
Customer Token Customer-facing apps Configurable

Step 3: Get Admin Token (Simplest Method)

Generate admin token for internal use:

const MAGENTO_BASE_URL = process.env.MAGENTO_BASE_URL;
const MAGENTO_ADMIN_USERNAME = process.env.MAGENTO_ADMIN_USERNAME;
const MAGENTO_ADMIN_PASSWORD = process.env.MAGENTO_ADMIN_PASSWORD;

const getAdminToken = async () => {
  const response = await fetch(`${MAGENTO_BASE_URL}/rest/V1/integration/admin/token`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      username: MAGENTO_ADMIN_USERNAME,
      password: MAGENTO_ADMIN_PASSWORD
    })
  });

  if (!response.ok) throw new Error('Invalid admin credentials');
  const token = await response.text();
  return token;
};

// Usage
const token = await getAdminToken();
console.log(`Admin token: ${token}`);
// Store securely for API calls
Enter fullscreen mode Exit fullscreen mode

Security best practice: Store credentials in environment variables:

# .env
MAGENTO_BASE_URL="https://store.example.com"
MAGENTO_ADMIN_USERNAME="api_user"
MAGENTO_ADMIN_PASSWORD="secure_password_here"
MAGENTO_ACCESS_TOKEN="obtained_via_auth"
Enter fullscreen mode Exit fullscreen mode

Step 4: Create Integration (Recommended for Third-Party)

  1. Go to System > Extensions > Integrations
  2. Click Add New Integration
  3. Fill details (name, email, callback/identity URLs for OAuth)
  4. Set API Permissions (Products, Orders, Customers, Inventory recommended)
  5. Click Save and Activate
  6. Copy Access Token and Token Secret

Step 5: Get Customer Token

For customer-facing apps:

const getCustomerToken = async (email, password) => {
  const response = await fetch(`${MAGENTO_BASE_URL}/rest/V1/integration/customer/token`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: email, password: password })
  });

  if (!response.ok) throw new Error('Invalid customer credentials');
  const token = await response.text();
  return token;
};

// Usage
const customerToken = await getCustomerToken('customer@example.com', 'password123');
Enter fullscreen mode Exit fullscreen mode

Step 6: Make Authenticated API Calls

Reusable API client example:

const magentoRequest = async (endpoint, options = {}) => {
  const token = await getAdminToken(); // Or retrieve stored token

  const response = await fetch(`${MAGENTO_BASE_URL}/rest${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Magento API Error: ${error.message}`);
  }
  return response.json();
};

// Usage
const products = await magentoRequest('/V1/products');
console.log(`Found ${products.items.length} products`);
Enter fullscreen mode Exit fullscreen mode

Product Management

Getting Products

Fetch products with filters:

const getProducts = async (filters = {}) => {
  const params = new URLSearchParams();

  if (filters.search) {
    params.append('searchCriteria[filterGroups][0][filters][0][field]', 'sku');
    params.append('searchCriteria[filterGroups][0][filters][0][value]', `%${filters.search}%`);
    params.append('searchCriteria[filterGroups][0][filters][0][conditionType]', 'like');
  }

  if (filters.priceFrom) {
    params.append('searchCriteria[filterGroups][1][filters][0][field]', 'price');
    params.append('searchCriteria[filterGroups][1][filters][0][value]', filters.priceFrom);
    params.append('searchCriteria[filterGroups][1][filters][0][conditionType]', 'gteq');
  }

  params.append('searchCriteria[pageSize]', filters.limit || 20);
  params.append('searchCriteria[currentPage]', filters.page || 1);

  const response = await magentoRequest(`/V1/products?${params.toString()}`);
  return response;
};

// Usage
const products = await getProducts({ search: 'shirt', priceFrom: 20, limit: 50 });

products.items.forEach(product => {
  console.log(`${product.sku}: ${product.name} - $${product.price}`);
});
Enter fullscreen mode Exit fullscreen mode

Getting Single Product

Fetch by SKU:

const getProduct = async (sku) => {
  const response = await magentoRequest(`/V1/products/${sku}`);
  return response;
};

// Usage
const product = await getProduct('TSHIRT-001');
console.log(`Name: ${product.name}`);
console.log(`Price: $${product.price}`);
console.log(`Stock: ${product.extension_attributes?.stock_item?.qty}`);
Enter fullscreen mode Exit fullscreen mode

Creating a Product

Create a simple product:

const createProduct = async (productData) => {
  const product = {
    product: {
      sku: productData.sku,
      name: productData.name,
      attribute_set_id: productData.attributeSetId || 4,
      type_id: 'simple',
      price: productData.price,
      status: productData.status || 1,
      visibility: productData.visibility || 4,
      weight: productData.weight || 1,
      extension_attributes: {
        stock_item: {
          qty: productData.qty || 0,
          is_in_stock: productData.qty > 0 ? true : false
        }
      },
      custom_attributes: [
        { attribute_code: 'description', value: productData.description },
        { attribute_code: 'short_description', value: productData.shortDescription },
        { attribute_code: 'color', value: productData.color },
        { attribute_code: 'size', value: productData.size }
      ]
    }
  };

  const response = await magentoRequest('/V1/products', {
    method: 'POST',
    body: JSON.stringify(product)
  });

  return response;
};

// Usage
const newProduct = await createProduct({
  sku: 'TSHIRT-NEW-001',
  name: 'Premium Cotton T-Shirt',
  price: 29.99,
  qty: 100,
  description: 'High-quality cotton t-shirt',
  shortDescription: 'Premium cotton tee',
  color: 'Blue',
  size: 'M'
});
console.log(`Product created: ${newProduct.id}`);
Enter fullscreen mode Exit fullscreen mode

Updating a Product

Update by SKU:

const updateProduct = async (sku, updates) => {
  const product = { product: { sku: sku, ...updates } };

  const response = await magentoRequest(`/V1/products/${sku}`, {
    method: 'PUT',
    body: JSON.stringify(product)
  });

  return response;
};

// Usage
await updateProduct('TSHIRT-001', {
  price: 24.99,
  extension_attributes: {
    stock_item: { qty: 150, is_in_stock: true }
  }
});
Enter fullscreen mode Exit fullscreen mode

Deleting a Product

const deleteProduct = async (sku) => {
  await magentoRequest(`/V1/products/${sku}`, { method: 'DELETE' });
  console.log(`Product ${sku} deleted`);
};
Enter fullscreen mode Exit fullscreen mode

Product Types

Type Description Use Case
Simple Single SKU, no variations Standard products
Configurable Parent w/ variations Size/color options
Grouped Set of simple products Bundles
Virtual Non-physical Services, downloads
Bundle Customizable bundles Build-your-own kits
Downloadable Digital E-books, software

Order Management

Getting Orders

Fetch orders with filters:

const getOrders = async (filters = {}) => {
  const params = new URLSearchParams();

  if (filters.status) {
    params.append('searchCriteria[filterGroups][0][filters][0][field]', 'status');
    params.append('searchCriteria[filterGroups][0][filters][0][value]', filters.status);
    params.append('searchCriteria[filterGroups][0][filters][0][conditionType]', 'eq');
  }

  if (filters.dateFrom) {
    params.append('searchCriteria[filterGroups][1][filters][0][field]', 'created_at');
    params.append('searchCriteria[filterGroups][1][filters][0][value]', filters.dateFrom);
    params.append('searchCriteria[filterGroups][1][filters][0][conditionType]', 'gteq');
  }

  params.append('searchCriteria[pageSize]', filters.limit || 20);
  params.append('searchCriteria[currentPage]', filters.page || 1);

  const response = await magentoRequest(`/V1/orders?${params.toString()}`);
  return response;
};

// Usage
const orders = await getOrders({
  status: 'pending',
  dateFrom: '2026-03-18 00:00:00',
  limit: 50
});

orders.items.forEach(order => {
  console.log(`Order #${order.increment_id}: ${order.customer_email} - $${order.grand_total}`);
});
Enter fullscreen mode Exit fullscreen mode

Getting Single Order

const getOrder = async (orderId) => {
  const response = await magentoRequest(`/V1/orders/${orderId}`);
  return response;
};

// Usage
const order = await getOrder(12345);
console.log(`Order #${order.increment_id}`);
console.log(`Status: ${order.status}`);
console.log(`Total: $${order.grand_total}`);
order.items.forEach(item => {
  console.log(`  - ${item.name} x ${item.qty_ordered}`);
});
Enter fullscreen mode Exit fullscreen mode

Order Status Flow

pending → processing → complete
        → canceled
        → on_hold
        → payment_review
Enter fullscreen mode Exit fullscreen mode

Updating Order Status

Update order status via workflow endpoints:

const updateOrderStatus = async (orderId, newStatus) => {
  // Cancel
  await magentoRequest(`/V1/orders/${orderId}/cancel`, { method: 'POST' });

  // Hold
  await magentoRequest(`/V1/orders/${orderId}/hold`, { method: 'POST' });

  // Unhold
  await magentoRequest(`/V1/orders/${orderId}/unhold`, { method: 'POST' });
};
Enter fullscreen mode Exit fullscreen mode

Creating Invoice

const createInvoice = async (orderId, items = [], notify = true, appendComment = false, comment = null) => {
  const invoice = {
    capture: true,
    last: true,
    items: items
  };

  if (comment) {
    invoice.comment = comment;
    invoice.notify_customer = notify ? 1 : 0;
    invoice.append_comment = appendComment ? 1 : 0;
  }

  const response = await magentoRequest(`/V1/order/${orderId}/invoice`, {
    method: 'POST',
    body: JSON.stringify(invoice)
  });
  return response;
};

// Usage
const invoiceId = await createInvoice(12345, [], true, false, 'Thank you for your order!');
console.log(`Invoice created: ${invoiceId}`);
Enter fullscreen mode Exit fullscreen mode

Creating Shipment

const createShipment = async (orderId, items = [], notify = true, appendComment = false, comment = null, tracks = []) => {
  const shipment = {
    items: items,
    notify: notify ? 1 : 0,
    append_comment: appendComment ? 1 : 0,
    comment: comment,
    tracks: tracks
  };

  const response = await magentoRequest(`/V1/order/${orderId}/ship`, {
    method: 'POST',
    body: JSON.stringify(shipment)
  });
  return response;
};

// Usage
const shipmentId = await createShipment(12345, [], true, false, 'Your order has shipped!', [
  { track_number: '1Z999AA10123456784', title: 'Tracking Number', carrier_code: 'ups' }
]);
console.log(`Shipment created: ${shipmentId}`);
Enter fullscreen mode Exit fullscreen mode

Customer Management

Getting Customers

const getCustomers = async (filters = {}) => {
  const params = new URLSearchParams();

  if (filters.email) {
    params.append('searchCriteria[filterGroups][0][filters][0][field]', 'email');
    params.append('searchCriteria[filterGroups][0][filters][0][value]', filters.email);
    params.append('searchCriteria[filterGroups][0][filters][0][conditionType]', 'eq');
  }

  params.append('searchCriteria[pageSize]', filters.limit || 20);

  const response = await magentoRequest(`/V1/customers/search?${params.toString()}`);
  return response;
};

// Usage
const customers = await getCustomers({ email: 'customer@example.com' });
customers.items.forEach(customer => {
  console.log(`${customer.firstname} ${customer.lastname} - ${customer.email}`);
});
Enter fullscreen mode Exit fullscreen mode

Creating a Customer

const createCustomer = async (customerData) => {
  const customer = {
    customer: {
      websiteId: customerData.websiteId || 1,
      email: customerData.email,
      firstname: customerData.firstname,
      lastname: customerData.lastname,
      middlename: customerData.middlename || '',
      gender: customerData.gender || 0,
      store_id: customerData.storeId || 0,
      extension_attributes: {
        is_subscribed: customerData.subscribed || false
      }
    },
    password: customerData.password
  };

  const response = await magentoRequest('/V1/customers', {
    method: 'POST',
    body: JSON.stringify(customer)
  });

  return response;
};

// Usage
const newCustomer = await createCustomer({
  email: 'newcustomer@example.com',
  firstname: 'John',
  lastname: 'Doe',
  password: 'SecurePass123!',
  subscribed: true
});
console.log(`Customer created: ID ${newCustomer.id}`);
Enter fullscreen mode Exit fullscreen mode

Inventory Management (MSI)

Getting Stock Status

const getStockStatus = async (sku) => {
  const response = await magentoRequest(`/V1/products/${sku}/stockItems/1`);
  return response;
};

// Usage
const stock = await getStockStatus('TSHIRT-001');
console.log(`Qty: ${stock.qty}`);
console.log(`In Stock: ${stock.is_in_stock}`);
console.log(`Min Qty: ${stock.min_qty}`);
Enter fullscreen mode Exit fullscreen mode

Updating Stock

const updateStock = async (sku, qty, isInStock = null) => {
  const stockItem = {
    stockItem: {
      qty: qty,
      is_in_stock: isInStock !== null ? isInStock : qty > 0
    }
  };

  const response = await magentoRequest(`/V1/products/${sku}/stockItems/1`, {
    method: 'PUT',
    body: JSON.stringify(stockItem)
  });

  return response;
};

// Usage
await updateStock('TSHIRT-001', 100, true);
Enter fullscreen mode Exit fullscreen mode

Webhooks and Async Operations

Setting Up Webhooks

Magento does not have built-in webhooks. Use these approaches:

// 1. Poll orders endpoint periodically
const pollNewOrders = async (lastOrderId) => {
  const orders = await getOrders({
    dateFrom: new Date().toISOString()
  });
  const newOrders = orders.items.filter(o => o.id > lastOrderId);
  return newOrders;
};

// 2. Use Adobe I/O Events (Adobe Commerce only)
// Configure events in Adobe Developer Console

// 3. Create custom webhook module
// See: https://devdocs.magento.com/guides/v2.4/extension-dev-guide/message-queues/message-queues.html
Enter fullscreen mode Exit fullscreen mode

Rate Limiting

Understanding Rate Limits

  • Default: No limit (set in Admin)
  • Recommended: 100–1000 requests/minute

Configure: Stores > Configuration > Services > Web API > Security

Implementing Rate Limit Handling

Example exponential backoff:

const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await magentoRequest(endpoint, options);
      return response;
    } catch (error) {
      if (error.message.includes('429') && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000;
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Production Deployment Checklist

Before going live, ensure:

  • [ ] Use integration tokens (avoid admin creds in prod)
  • [ ] Store tokens securely (encrypted storage)
  • [ ] Implement rate limiting and request queues
  • [ ] Add robust error handling
  • [ ] Enable logging for all API calls
  • [ ] Use webhook alternative (polling/Adobe I/O)
  • [ ] Test with production data/volume
  • [ ] Add retry logic for failures

Real-World Use Cases

ERP Integration

  • Challenge: Manual stock sync between ERP and Magento
  • Solution: Bi-directional API sync every 15 min
  • Result: Real-time inventory, no overselling

Mobile App

  • Challenge: Need high-performance mobile experience
  • Solution: GraphQL for product browsing; REST for checkout
  • Result: +40% mobile conversion rate

Conclusion

Magento 2 API enables robust e-commerce integrations:

  • REST, SOAP, and GraphQL APIs
  • Token-based authentication
  • Full CRUD for products, orders, customers
  • MSI for advanced inventory
  • Configurable rate limits
  • Apidog streamlines API testing and team collaboration

FAQ Section

How do I authenticate with Magento API?

Use admin token for internal integrations, or create an Integration for OAuth. Use customer token for customer-facing apps.

What is the difference between REST and GraphQL in Magento?

REST covers full CRUD. GraphQL is optimized for frontend queries and efficient data fetches.

How do I create a product via API?

POST to /V1/products with product data (SKU, name, price, stock_item in extension_attributes).

Can I get webhooks for new orders?

Magento lacks native webhooks. Use polling, Adobe I/O Events (Adobe Commerce), or a custom module.

How do I update stock quantities?

PUT to /V1/products/{sku}/stockItems/1 with qty and is_in_stock values.

Top comments (0)