Product catalog
An optional product catalog that links automatically to your orders' line items.
The product catalog is optional. Order line items work inline with zero setup. If you sell the same products over and over, the catalog saves you from repeating name, price, weight, and customs data: they copy into every order.
Endpoints
| Method | Path | Scope | Description |
|---|---|---|---|
POST |
/v1/products |
products:write |
Create a product |
GET |
/v1/products |
products:read |
List active products (?sku= exact, ?search= contains, ?page=, ?limit=) |
GET |
/v1/products/all |
products:read (ADMIN) |
List all, including inactive |
GET |
/v1/products/:id |
products:read |
Get a product |
PUT |
/v1/products/:id |
products:write |
Update a product |
DELETE |
/v1/products/:id |
products:write (ADMIN) |
Delete (soft delete) |
Create a product
Body parameters
namestring
The product's name.
stringsku?string
Unique among your non-deleted products. Enables SKU auto-linking.
stringdescription?string
The product's description.
stringprice?number
Per-unit price; copied into the order line item when linked.
numbercurrency?string
stringMXNweight?number
Weight in kg. It is the packing and quoting default.
numberlength?number
Length in cm.
numberwidth?number
Width in cm.
numberheight?number
Height in cm.
numberhsCode?string
HS tariff code (international shipments).
stringsatProductClassCode?string
SAT product-classification key.
stringcountryOfOrigin?string
Country of origin (ISO).
stringcustomsDescription?string
Customs description.
stringdeclaredValue?number
Per-unit declared value (insurance and customs).
numberdeclaredValueCurrency?string
stringMXNshipsSeparately?boolean
The product always travels in its own parcel.
booleanfalseimageUrl?string
URL of the product image.
stringisActive?boolean
Inactive products don't list by default and never auto-link.
booleantruemetadata?object
Your own key-value pairs; returned as-is.
objectcurl -X POST https://api.sendit.mx/v1/products \
-H "X-API-Key: sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"sku": "TSHIRT-L-ROJO",
"name": "Red t-shirt size L",
"description": "100% cotton t-shirt, round neck",
"price": 450.00,
"weight": 0.25,
"length": 30, "width": 25, "height": 3,
"hsCode": "610910",
"satProductClassCode": "53102002",
"countryOfOrigin": "MX",
"declaredValue": 450.00
}'
{
"success": true,
"data": {
"id": "prod_x1y2z3",
"sku": "TSHIRT-L-ROJO",
"name": "Red t-shirt size L",
"description": "100% cotton t-shirt, round neck",
"price": 450.00,
"currency": "MXN",
"weight": 0.25,
"length": 30,
"width": 25,
"height": 3,
"hsCode": "610910",
"satProductClassCode": "53102002",
"countryOfOrigin": "MX",
"declaredValue": 450.00,
"declaredValueCurrency": "MXN",
"shipsSeparately": false,
"isActive": true,
"createdAt": "2026-07-18T10:00:00.000Z"
}
}
How it links to orders
When creating an order, each line item can reference the catalog:
- By
productId. This is the explicit link. The product’s data is frozen into the item. - By
sku. If the SKU matches an active product, it links on its own. - No link. The item lives inline with its own data.
In every case, what stays on the order is a snapshot: editing or deleting the product later never touches existing orders.
The snapshot freezes: name, price (as unitPrice), sku, weight, hsCode, satProductClassCode, countryOfOrigin, customsDescription, and declaredValue.
SKU rules
A sku is unique among your non-deleted products. An inactive product still holds its SKU.
| Code | When | How to resolve it |
|---|---|---|
400 SKU_ALREADY_EXISTS |
You create or update a product with a SKU another product already uses | The conflicting productId is in details; use another SKU or edit that product |
Deleting a product (soft delete) frees its SKU for reuse.
The catalog is not split by mode
Products are not separated between live and test. Your LIVE and TEST orders point at the same catalog, and an sk_test_ key sees exactly the same products.