Passthrough API

Proxy requests to Amazon SP-API with automatic data handling

Passthrough API

The Passthrough API proxies requests to whitelisted Amazon SP-API endpoints with automatic authentication, data scrubbing, and optional label handling.

Overview

GET|POST|DELETE /passthrough-api/*

Requests to /passthrough-api/orders/v0/orders are proxied to https://sellingpartnerapi-{region}.amazon.com/orders/v0/orders with:

  • Automatic Amazon access token injection
  • Automatic RDT (Restricted Data Token) generation when needed
  • PII scrubbing from responses
  • Optional label storage for shipping endpoints

Authentication

HeaderRequiredDescription
x-seller-access-tokenYesValid seller access token
x-amazon-token-secretYesSecret used during OAuth

Basic Usage

Get Orders

curl -X GET "https://adb.example.com/passthrough-api/orders/v0/orders?MarketplaceIds=ATVPDKIKX0DER" \
  -H "x-seller-access-token: YOUR_SELLER_TOKEN" \
  -H "x-amazon-token-secret: YOUR_TOKEN_SECRET"

Response

{
  "payload": {
    "Orders": [
      {
        "AmazonOrderId": "123-4567890-1234567",
        "OrderStatus": "Unshipped",
        "PurchaseDate": "2024-01-15T10:30:00Z",
        "OrderTotal": {
          "CurrencyCode": "USD",
          "Amount": "29.99"
        }
      }
    ]
  }
}

ShippingAddress is automatically scrubbed. Use the PII API or Label Proxy to access customer addresses.


Transparent RDT Handling

Data Border automatically handles Restricted Data Tokens for endpoints that require them:

Loading diagram...

No code changes needed - RDT generation is fully automatic.


Label Handling Mode

When shipping-related headers are provided, Data Border enters label handling mode:

Additional Headers

HeaderDescription
x-amazon-order-idAmazon order ID for PII lookup
x-unique-shipment-idYour unique shipment identifier
x-unredacted-piiSet to "true" for unredacted response

Label Mode Response

{
  "success": true,
  "data": {
    "scrubbed_response": { /* SP-API response with PII removed */ },
    "shipment_id": "ship_abc123def456",
    "amazon_order_id": "123-4567890-1234567",
    "unique_shipment_id": "WMS-SHIP-001",
    "documents": [
      { "uuid": "550e8400-e29b-41d4-a716-446655440000", "path": "label.pdf" }
    ]
  }
}

Example: Shipping with Label Storage

curl -X POST "https://adb.example.com/passthrough-api/shipping/v2/shipments" \
  -H "Content-Type: application/json" \
  -H "x-seller-access-token: YOUR_SELLER_TOKEN" \
  -H "x-amazon-token-secret: YOUR_TOKEN_SECRET" \
  -H "x-amazon-order-id: 123-4567890-1234567" \
  -H "x-unique-shipment-id: WMS-SHIP-001" \
  -d '{ "shipment data..." }'

Whitelisted Endpoints

Orders API

EndpointMethodDescription
/orders/v0/ordersGETList orders (addresses scrubbed)
/orders/v0/orders/{orderId}GETGet order details
/orders/v0/orders/{orderId}/orderItemsGETGet order items
/orders/v0/orders/{orderId}/buyerInfoGETGet buyer info (RDT auto)
/orders/v0/orders/{orderId}/addressGETGet address (RDT auto)

Reports API

EndpointMethodDescription
/reports/2021-06-30/reportsGET, POSTReport management
/reports/2021-06-30/documents/{id}GETDownload reports

Fulfillment

EndpointMethodDescription
/mfn/v0/shipmentsGET, POSTMFN shipments
/shipping/v2/shipmentsPOSTBuy Shipping labels
/fba/outbound/2020-07-01/*GET, POSTFBA fulfillment

Catalog & Listings

EndpointMethodDescription
/catalog/2022-04-01/itemsGETProduct catalog
/listings/2021-08-01/*GET, PATCH, PUT, DELETEListing management

Other APIs

EndpointMethodDescription
/feeds/2021-06-30/*GET, POSTFeed submissions
/products/pricing/v0/*GETProduct pricing
/products/fees/v0/*GET, POSTFBA fees
/sales/v1/*GETSales analytics
/finances/2024-06-19/*GETFinancial data
/notifications/v1/*GET, POST, DELETENotification subscriptions
/services/v1/*GET, POSTService API
/vendor/directFulfillment/*GET, POSTVendor Central

Data Scrubbing

What Gets Scrubbed

Data Border automatically removes PII from responses:

FieldScrubbed To
ShippingAddress.Name[REDACTED]
ShippingAddress.AddressLine1[REDACTED]
ShippingAddress.AddressLine2[REDACTED]
ShippingAddress.City[REDACTED]
ShippingAddress.Phone[REDACTED]
BuyerEmail[REDACTED]
BuyerName[REDACTED]

Preserved Data

Non-PII fields are preserved:

  • Order IDs, status, dates
  • Product information (ASINs, SKUs, prices)
  • Tracking numbers
  • Country codes, state codes, postal codes (partial)

Implementation Examples

Sync Orders

async function syncOrders(sellerId, marketplaceId, lastSync) {
  const { token, secret } = await tokenManager.getSellerAccessToken(sellerId)
  
  const params = new URLSearchParams({
    MarketplaceIds: marketplaceId,
    CreatedAfter: lastSync.toISOString()
  })
  
  const response = await fetch(
    `${ADB_URL}/passthrough-api/orders/v0/orders?${params}`,
    {
      headers: {
        'x-seller-access-token': token,
        'x-amazon-token-secret': secret
      }
    }
  )
  
  const data = await response.json()
  
  for (const order of data.payload.Orders) {
    await db.orders.upsert({
      amazonOrderId: order.AmazonOrderId,
      sellerId,
      status: order.OrderStatus,
      purchaseDate: order.PurchaseDate,
      total: order.OrderTotal?.Amount
      // Note: Address is scrubbed
    })
  }
  
  return data.payload.Orders.length
}

Create Shipment with Labels

async function createShipmentWithLabels(order, shipmentData) {
  const { token, secret } = await tokenManager.getSellerAccessToken(order.sellerId)
  
  const response = await fetch(
    `${ADB_URL}/passthrough-api/shipping/v2/shipments`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-seller-access-token': token,
        'x-amazon-token-secret': secret,
        'x-amazon-order-id': order.amazonOrderId,
        'x-unique-shipment-id': `${order.id}-${Date.now()}`
      },
      body: JSON.stringify(shipmentData)
    }
  )
  
  const data = await response.json()
  
  // Store shipment with document references
  await db.shipments.create({
    orderId: order.id,
    adbShipmentId: data.data.shipment_id,
    trackingNumber: data.data.scrubbed_response.trackingId,
    documents: data.data.documents
  })
  
  return data.data
}

Error Handling

Data Border Errors

{
  "is_adb_error": true,
  "success": false,
  "error": {
    "message": "Endpoint not whitelisted",
    "details": "/some/custom/endpoint is not in the allowed list"
  }
}

Amazon SP-API Errors

Amazon errors are passed through:

{
  "errors": [
    {
      "code": "InvalidInput",
      "message": "MarketplaceIds is required",
      "details": ""
    }
  ]
}

Common Error Codes

StatusMessageCause
400Endpoint not whitelistedURL not in allowed list
401Invalid seller access tokenToken expired
403Access deniedSeller not authorized for endpoint
429Rate limit exceededAmazon throttling
500Amazon API errorUpstream Amazon error

Best Practices

Use Query Parameters Correctly

// Good: URL-encode marketplace IDs
const params = new URLSearchParams({
  MarketplaceIds: 'ATVPDKIKX0DER'
})

// Good: Multiple values
params.append('OrderStatuses', 'Unshipped')
params.append('OrderStatuses', 'PartiallyShipped')

Handle Pagination

async function getAllOrders(sellerId, marketplaceId) {
  const orders = []
  let nextToken = null
  
  do {
    const params = new URLSearchParams({ MarketplaceIds: marketplaceId })
    if (nextToken) params.set('NextToken', nextToken)
    
    const data = await fetchOrders(sellerId, params)
    orders.push(...data.payload.Orders)
    nextToken = data.payload.NextToken
  } while (nextToken)
  
  return orders
}

Respect Rate Limits

Amazon SP-API has per-endpoint rate limits. Implement backoff:

async function fetchWithRetry(url, options, retries = 3) {
  for (let i = 0; i < retries; i++) {
    const response = await fetch(url, options)
    
    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || (2 ** i)
      await delay(retryAfter * 1000)
      continue
    }
    
    return response
  }
  throw new Error('Rate limit exceeded')
}

Next Steps

Label Proxy

Use placeholder-based label generation.

PII Access

Access customer data directly when needed.