SKU Wrangler
Developer Preview v1

Canonical SKU Mapping API

API specification for a portable, merchant-owned SKU mapping service

Developer Preview: We're piloting this API with select merchants and 3PLs. The spec below reflects real workflows. If you'd like early access or have feedback, contact us at hello [at] skuwrangler.com.

Why this matters: Without a canonical API, every 3PL switch means remapping SKUs by hand. This spec is designed to eliminate that.

What is the Canonical SKU Mapping API?

The Canonical SKU Mapping API is a centralized service that stores and manages how your products are identified across different channels and 3PL providers. Instead of maintaining SKU mappings in spreadsheets or inside each 3PL’s portal, you own a single, portable mapping layer that:

  • Translates between your internal SKUs and external identifiers (sales channels and 3PL providers)
  • Preserves your mappings when switching 3PL providers (no more starting from scratch)
  • Handles bundles and kits by defining component relationships once
  • Enables real-time lookups for order routing and inventory sync

Think of it as your SKU translation service that you control, not your vendors.

Overview

A RESTful API for managing canonical SKU mappings across sales channels and 3PL providers. This allows merchants to maintain a single source of truth for product identifiers that’s portable between 3PL providers (ShipBob, ShipMonk, Amazon FBA) and sales channels (Shopify, Amazon, Walmart).

Key principle: The API returns order-relevant identifiers for channels (what appears in orders) and fulfillment-relevant identifiers for providers (what’s needed to ship).

Core Concepts

Canonical SKU

Your internal, master SKU that all other systems reference.

Mapping

A relationship between your canonical SKU and how external channels or providers identify the same product. Uses identifier type as the key for clarity:

  • Channels: Order-relevant identifiers (SKU, seller_sku, ASIN)
  • Providers: Fulfillment-relevant identifiers (SKU, FNSKU)

Bundle

A canonical SKU that represents multiple component SKUs.

Identifier Types

  • sku: Standard SKU used by most systems
  • asin: Amazon Standard Identification Number
  • seller_sku: Your SKU in Amazon Seller Central
  • fnsku: Fulfillment Network SKU (Amazon FBA)

Endpoints

List & Filter Mappings

Retrieve all mappings with optional filtering.

GET /api/v1/mappings

Query Parameters:

  • provider - Filter by specific 3PL provider (e.g., ?provider=shipbob)
  • channel - Filter by specific sales channel (e.g., ?channel=shopify)
  • limit - Number of results (default: 100, max: 1000)
  • offset - Pagination offset
  • updated_since - ISO 8601 timestamp

Example:

GET /api/v1/mappings?provider=shipbob&limit=50

Response:

{
  "mappings": [
    {
      "canonical_sku": "TSHIRT-BLACK-M",
      "type": "product",
      "channels": {
        "shopify": {"sku": "TSHIRT-BLACK-M"},
        "amazon": {
          "seller_sku": "AMZ-TEE-BLK-M",
          "asin": "B08XYZ123"
        }
      },
      "providers": {
        "shipbob": {"sku": "SB-12345"}
      }
    }
  ],
  "pagination": {
    "total": 2847,
    "limit": 50,
    "offset": 0
  }
}

Get Single Mapping

Retrieve mappings for order routing and fulfillment. Returns only the primary identifiers needed for operations.

Use this for:

  • Order routing (Shopify order → 3PL fulfillment)
  • Inventory updates (3PL stock → sales channels)
  • Real-time lookups during fulfillment

For debugging or audit information, see Get Mapping Details.

GET /api/v1/mappings/{canonical_sku}

Response:

{
  "canonical_sku": "TSHIRT-BLACK-M",
  "type": "product",
  "channels": {
    "shopify": {"sku": "TSHIRT-BLACK-M"},
    "amazon": {
      "seller_sku": "AMZ-TEE-BLK-M",
      "asin": "B08XYZ123"
    },
    "walmart": {"sku": "WMT-TEE-BLK-MD"}
  },
  "providers": {
    "shipbob": {"sku": "SB-12345"},
    "shipmonk": {"sku": "SM-98765"},
    "amazon_fba": {"fnsku": "X001ABCDEF"}
  },
  "metadata": {
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2025-08-30T15:30:00Z",
    "version": 3
  }
}

Reverse Lookup

Find canonical SKU from any system’s identifier.

GET /api/v1/mappings/lookup

Query Parameters:

  • scope - Either “provider” or “channel” (required)
  • source - The provider or channel name (required)
  • type - The identifier type: sku, asin, seller_sku, fnsku (required)
  • value - The identifier value (required)

Example:

GET /api/v1/mappings/lookup?scope=channel&source=amazon&type=seller_sku&value=AMZ-TEE-BLK-M

Response:

{
  "canonical_sku": "TSHIRT-BLACK-M",
  "lookup_scope": "channel",
  "lookup_source": "amazon",
  "lookup_type": "seller_sku",
  "lookup_value": "AMZ-TEE-BLK-M",
  "channels": {
    "shopify": {"sku": "TSHIRT-BLACK-M"},
    "amazon": {
      "seller_sku": "AMZ-TEE-BLK-M",
      "asin": "B08XYZ123"
    },
    "walmart": {"sku": "WMT-TEE-BLK-MD"}
  },
  "providers": {
    "shipbob": {"sku": "SB-12345"},
    "amazon_fba": {"fnsku": "X001ABCDEF"}
  }
}

Create/Update Single Mapping

Add or update mappings for a canonical SKU.

PUT /api/v1/mappings/{canonical_sku}

Headers:

Idempotency-Key: unique-request-id-123

Request:

{
  "providers": {
    "shipmonk": {"sku": "SM-456789"}
  }
}

Response:

{
  "canonical_sku": "TSHIRT-BLACK-M",
  "metadata": {
    "version": 4,
    "updated_at": "2025-08-31T16:00:00Z"
  }
}

Bulk Create/Update

Create or update multiple mappings in one request.

POST /api/v1/mappings/bulk

Request:

{
  "mappings": [
    {
      "canonical_sku": "TSHIRT-BLACK-M",
      "providers": {
        "shipbob": {"sku": "SB-456789"}
      }
    },
    {
      "canonical_sku": "TSHIRT-BLACK-L",
      "providers": {
        "shipbob": {"sku": "SB-456790"}
      }
    }
  ]
}

Response:

{
  "processed": 2,
  "succeeded": 2,
  "failed": 0,
  "results": [
    {
      "canonical_sku": "TSHIRT-BLACK-M",
      "status": "success"
    },
    {
      "canonical_sku": "TSHIRT-BLACK-L",
      "status": "success"
    }
  ]
}

Bulk Import

Upload CSV or JSON file for mass import.

POST /api/v1/mappings/import

Request:

Content-Type: multipart/form-data
file: [CSV or JSON file]
format: "csv" | "json"

CSV Format:

canonical_sku,scope,source,id_type,value
TSHIRT-BLACK-M,channel,shopify,sku,TSHIRT-BLACK-M
TSHIRT-BLACK-M,channel,amazon,seller_sku,AMZ-TEE-BLK-M
TSHIRT-BLACK-M,channel,amazon,asin,B08XYZ123
TSHIRT-BLACK-M,provider,shipbob,sku,SB-98765

Export All Mappings

Export all mappings for backup or migration.

GET /api/v1/mappings/export

Query Parameters:

  • format - Export format: json (default) or csv
  • provider - Optional: Export only mappings for specific provider
  • channel - Optional: Export only mappings for specific channel

Response:

{
  "export_id": "exp_123456",
  "created_at": "2025-08-31T10:00:00Z",
  "total_mappings": 2847,
  "format": "json",
  "download_url": "/exports/exp_123456.json",
  "expires_at": "2025-09-01T10:00:00Z"
}

Bundle Operations

Manage bundle definitions.

GET /api/v1/bundles/{canonical_sku}

Response:

{
  "canonical_sku": "BUNDLE-3PACK-BLACK-M",
  "type": "bundle",
  "components": [
    {
      "canonical_sku": "TSHIRT-BLACK-M",
      "quantity": 3
    }
  ],
  "channels": {
    "shopify": {"sku": "3PACK-BLACK-M"},
    "amazon": {
      "seller_sku": "AMZ-3PACK-BLK-M",
      "asin": "B09ABC456"
    }
  },
  "providers": {
    "shipbob": {"sku": "SB-BUNDLE-001"}
  }
}
PUT /api/v1/bundles/{canonical_sku}

Request:

{
  "components": [
    {
      "canonical_sku": "TSHIRT-BLACK-M",
      "quantity": 3
    }
  ]
}

Get Mapping Details

Retrieve complete mapping information for debugging, auditing, and understanding how mappings were created.

Use this for:

  • Debugging why a mapping isn’t working
  • Auditing mapping history and confidence
  • Viewing all additional identifiers (UPC, GTIN, variant IDs)
  • Understanding how the mapping was created (match method, confidence)
GET /api/v1/mappings/{canonical_sku}/details

Response includes:

  • All primary and additional identifiers
  • Product-level identifiers (UPC, GTIN)
  • Mapping metadata (how it was matched)
  • Audit trail (who created/updated, when)

Response:

{
  "canonical_sku": "TSHIRT-BLACK-M",
  "type": "product",
  "identifiers": {
    "upc": "123456789012",
    "gtin": "00123456789012",
    "mpn": "AC-TEE-BLK-M"
  },
  "channels": {
    "shopify": {
      "primary": {"sku": "TSHIRT-BLACK-M"},
      "additional": {
        "variant_id": "1234567890",
        "barcode": "123456789012"
      }
    },
    "amazon": {
      "primary": {
        "seller_sku": "AMZ-TEE-BLK-M",
        "asin": "B08XYZ123"
      },
      "additional": {
        "marketplace_id": "ATVPDKIKX0DER"
      },
      "metadata": {
        "match_method": "upc_lookup",
        "confidence": 0.95
      }
    }
  },
  "providers": {
    "shipbob": {
      "primary": {"sku": "SB-12345"},
      "additional": {
        "location": "DFW1",
        "bin": "A-12-3"
      }
    }
  },
  "audit": {
    "created_at": "2024-01-15T10:00:00Z",
    "updated_at": "2025-08-30T15:30:00Z",
    "created_by": "user@example.com",
    "version": 3
  }
}

Archive Mapping

Soft delete a mapping (preserves history).

DELETE /api/v1/mappings/{canonical_sku}

Response:

{
  "canonical_sku": "TSHIRT-BLACK-M",
  "status": "archived",
  "archived_at": "2025-08-31T10:00:00Z",
  "version": 4
}

Use Cases

3PL Provider Onboarding

When adding a new 3PL provider (including Amazon FBA):

  1. Export existing mappings: GET /api/v1/mappings/export?format=csv
  2. Transform to provider’s template
  3. Import to provider system
  4. Bulk update with provider’s SKUs: POST /api/v1/mappings/bulk

Order Routing

When routing an order:

  1. Order arrives with Shopify SKU
  2. Lookup canonical: GET /api/v1/mappings/lookup?scope=channel&source=shopify&type=sku&value=TSHIRT-BLACK-M
  3. Get provider SKU from response
  4. Send to provider with their SKU

Inventory Sync

When provider reports inventory:

  1. Provider webhook: “SB-98765 has 42 units”
  2. Reverse lookup: GET /api/v1/mappings/lookup?scope=provider&source=shipbob&type=sku&value=SB-98765
  3. Update all channels using their respective SKUs

3PL Provider Migration

When switching 3PL providers:

  1. Export all mappings: GET /api/v1/mappings/export
  2. Archive old provider mappings
  3. Import new provider mappings: POST /api/v1/mappings/import
  4. Verify with test orders

Authentication

Authorization: Bearer {api_key}

API keys are scoped:

  • read - Read-only access
  • write - Full CRUD access
  • admin - Includes bulk operations

Rate Limits

  • Read operations: 1000/minute
  • Write operations: 100/minute
  • Bulk operations: 10/minute

Versioning

All responses include version numbers for audit trails:

GET /api/v1/mappings/{canonical_sku}?version=2

Returns the mapping as it existed at version 2.

Webhooks

Get notified when mappings change:

  • mapping.created
  • mapping.updated
  • mapping.archived
  • bundle.created
  • bundle.updated

Configure webhooks:

POST /api/v1/webhooks
{
  "url": "https://your-app.com/webhooks",
  "events": ["mapping.updated", "mapping.created"]
}

Status Codes

  • 200 - Success
  • 201 - Created
  • 400 - Bad request
  • 401 - Unauthorized
  • 404 - Not found
  • 409 - Conflict (e.g., version mismatch)
  • 429 - Rate limited
  • 500 - Server error

Error Responses

{
  "error": {
    "code": "MAPPING_CONFLICT",
    "message": "A different mapping already exists for this SKU",
    "details": {
      "existing_mapping": "SB-12345",
      "attempted_mapping": "SB-67890"
    }
  }
}

Common error codes:

  • UNKNOWN_SOURCE - Provider or channel not recognized
  • INVALID_BUNDLE - Bundle definition is invalid
  • MAPPING_CONFLICT - Conflicting mapping exists
  • VERSION_MISMATCH - Optimistic locking version conflict
  • RATE_LIMITED - Too many requests
  • UNAUTHORIZED - Invalid or missing API key

SDK Support (Coming Soon)

  • Node.js/TypeScript
  • Python
  • PHP

GraphQL API (Under Consideration)

We’re also exploring a GraphQL implementation for more flexible querying and reduced over-fetching. This would allow:

  • Single request for complex mapping relationships
  • Selective field queries to minimize payload size
  • Real-time subscriptions for mapping changes

Interested in GraphQL? Let us know.

Status

Current Status: Developer Preview

We’re actively piloting this with select partners. The spec reflects real workflows from merchant feedback.


Ready to eliminate SKU mapping chaos? Contact us at hello [at] skuwrangler.com for early access.

Request Early Access

We're piloting this API with select partners. Join the developer preview to help shape the final specification.

Read the blog post →