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 offsetupdated_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) orcsv
provider
- Optional: Export only mappings for specific providerchannel
- 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):
- Export existing mappings:
GET /api/v1/mappings/export?format=csv
- Transform to provider’s template
- Import to provider system
- Bulk update with provider’s SKUs:
POST /api/v1/mappings/bulk
Order Routing
When routing an order:
- Order arrives with Shopify SKU
- Lookup canonical:
GET /api/v1/mappings/lookup?scope=channel&source=shopify&type=sku&value=TSHIRT-BLACK-M
- Get provider SKU from response
- Send to provider with their SKU
Inventory Sync
When provider reports inventory:
- Provider webhook: “SB-98765 has 42 units”
- Reverse lookup:
GET /api/v1/mappings/lookup?scope=provider&source=shipbob&type=sku&value=SB-98765
- Update all channels using their respective SKUs
3PL Provider Migration
When switching 3PL providers:
- Export all mappings:
GET /api/v1/mappings/export
- Archive old provider mappings
- Import new provider mappings:
POST /api/v1/mappings/import
- Verify with test orders
Authentication
Authorization: Bearer {api_key}
API keys are scoped:
read
- Read-only accesswrite
- Full CRUD accessadmin
- 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
- Success201
- Created400
- Bad request401
- Unauthorized404
- Not found409
- Conflict (e.g., version mismatch)429
- Rate limited500
- 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 recognizedINVALID_BUNDLE
- Bundle definition is invalidMAPPING_CONFLICT
- Conflicting mapping existsVERSION_MISMATCH
- Optimistic locking version conflictRATE_LIMITED
- Too many requestsUNAUTHORIZED
- 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 →