Products API
The Carriyo Products API manages your product catalog. Products are referenced by shipments, orders, returns, and inventory, so keeping the catalog up to date keeps downstream data accurate.
Idempotency
Write endpoints accept an optional Idempotency-Key request header for safe request replay when your integration retries after uncertain network outcomes. Replayed responses include Idempotent-Replayed: true. See https://carriyo.com/docs/api/idempotency/ for the full contract.
Products
The Products resource represents the items in your catalog. Products are scoped to a merchant within your tenant and are referenced by shipments, orders, returns, and inventory.
Identifiers. A product can be addressed in three ways:
product_id: assigned by Carriyo when the product is created. Unique within the tenant and never changed. Use it on paths; a create request that carries one is rejected.product_ref: your reference. Required on create and unique within the merchant, so it is a reliable lookup key. Changing a product'sproduct_ref, or deleting the product, releases the old value for another product to use.sku: stock keeping unit. Not unique, so a lookup by SKU returns an array.
Reading by product_ref is strongly consistent. A product is found by its reference immediately after it is created or its reference is changed. The same applies when a bulk import matches existing products by reference.
Concurrent writes. Two requests that write the same product, or the same reference, at the same moment cannot both succeed. The one that loses receives 409 and should be retried.
Listing products. GET /products is served by the search index and supports free-text search, exact filters, sorting and paging across merchants. The index is updated shortly after each write, so a product written a moment ago may not be listed yet. Use the lookups by product_id or product_ref when you need the latest state.
Cross-border attributes. Carriers and customs typically need these fields on items that cross a border:
hs_code: Harmonized System code for customs classification.origin_country: ISO 3166-1 alpha-2 country code.material_composition: for example100% cotton; used in textile classification.dangerous_goods:truewhen the product is classified as dangerous goods.battery:material_typeandpacking_typewhen the product contains batteries.manufacturer_id: manufacturer reference, required by some carriers in certain destinations.
Custom data. carriyo_metadata holds free name/value pairs. custom_attributes holds values for the custom attributes defined for products on your account and is validated against them.
Bulk operations. Two operations cover larger catalogs:
- Bulk import (
POST /products/{merchant_id}/bulk/import): up to 500 products per request, each created or updated independently, with a result per item. - Bulk delete (
DELETE /products/{merchant_id}/bulk): deletes up to 500 of the merchant's products per call. Repeat whilemore_items_availableistrue.
Related: What a product record carries and which identifier resolves it
11 operations · 0 objects
/productsList products
Returns a page of products matching the filters, search string and sort order you supply.
Scope. Without merchant, the page covers every merchant your credentials can access. Repeat merchant to narrow it. A merchant outside your access is dropped from the selection; when none remains, the request is rejected.
Filters. Each filter is an exact match on the field of the same name. Repeat a filter to match any of its values.
Search. search_string matches product_id exactly and searches sku, barcode, product_ref, description, category, hs_code, manufacturer_id, material_composition, product_type and variant_parent_ref.
Paging. page starts at 0 and page_size is at most 250. A query can reach the first 10,000 results only; narrow the filters to see the rest.
Freshness. The list is served by the search index, which is updated shortly after each write.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| search_string | string | No | Free-text search across `product_id`, `sku`, `barcode`, `product_ref`, `description`, `category`, `hs_code`, `manufacturer_id`, `material_composition`, `product_type` and `variant_parent_ref`. |
| merchant | string | No | Filter by merchant. Repeat the parameter to match multiple merchants. |
| product_id | string | No | Filter by Carriyo product ID. Repeat the parameter to match multiple values. |
| product_ref | string | No | Filter by your reference (`product_ref`). Repeat the parameter to match multiple values. |
| sku | string | No | Filter by SKU. Repeat the parameter to match multiple values. |
| barcode | string | No | Filter by barcode. Repeat the parameter to match multiple values. |
| inventory_key | string | No | Filter by inventory key. Repeat the parameter to match multiple values. |
| category | string | No | Filter by category. Repeat the parameter to match multiple values. |
| product_type | string | No | Filter by product type. Repeat the parameter to match multiple values. |
| variant_parent_ref | string | No | Filter variants by the `product_ref` of their parent. Repeat the parameter to match multiple values. |
| status | string | No | Filter by product status. Repeat the parameter to match multiple values. |
| sort_by | string | No | Field to sort the results by. Unsorted when omitted. |
| sort_direction | string | No | Sort direction. Defaults to `desc`. |
| page | integer | No | Page number, starting from 0. Defaults to 0. |
| page_size | integer | No | Number of results per page. Defaults to 10. Maximum 250. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
product-list-responsemiddleware-error-responseThe request was rejected. One of:
sort_byis not one of the listed fields.page_sizeis above 250, orpageorpage_sizeis not a number.pageandpage_sizetogether reach past the first 10,000 results.
Need the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}Create product
Creates a product for the merchant in the path and returns the stored record with its Carriyo-assigned product_id.
What to send. product_ref is required and must not be in use by another product of the merchant. Do not send product_id; Carriyo generates it. A merchant in the body is ignored in favor of the path. Omitted fields take their defaults: product_type SIMPLE, status ACTIVE, do_not_place_above and do_not_place_below false.
Product types. A VARIANT keeps variant_parent_ref and variant_attributes. A PACK keeps pack_components and must have at least one. Fields that belong to another type are dropped without an error. variant_parent_ref and pack_components[].product_ref are stored as given and not checked against the catalog, so the products they name may be created later.
Custom attributes. custom_attributes is validated against the custom attributes defined for products on your account. An unknown attribute, or a value outside an attribute's allowed list, is rejected.
Idempotency. Supports optional Idempotency-Key for safe retries after timeouts or other uncertain network outcomes. See https://carriyo.com/docs/api/idempotency/.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| Content-Type | application/json | Yes | Media type of the request body. |
Header parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | No | Optional client-generated key that identifies one logical operation. Reuse the same key when retrying with the same payload. Replays the stored response. See https://carriyo.com/docs/api/idempotency/. |
Request body
application/jsonSchema: product-create-requestrequiredResponses
product-responseerror-responseThe request was rejected. One of:
product_refis missing or blank.- another product of the merchant already has this
product_ref. product_idis present in the body.statusis notACTIVE,INACTIVEorDELETED.- the body is not valid JSON, or a value is outside its type or enum.
origin_countryis not a two-letter ISO 3166 code Carriyo recognizes.product_typeisPACKandpack_componentsis empty or has a component withoutproduct_ref.- a pack component has a
quantitythat is not above 0, or two components share aproduct_ref. product_typeisVARIANTandvariant_attributeshas a key other thancolororsize.custom_attributesnames an attribute not defined for products, carries a value the attribute does not allow, or the account is not subscribed to custom attributes.
merchant_id.Schema: error-responseproduct_ref. Nothing was stored; retry the request.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}Search products by SKU
Returns every product of the merchant with the given sku. SKU is not unique, so the response is an array.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| sku | string | Yes | The SKU to look up. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
An array of product-response. Each item has the following fields:
sku query parameter is missing.Schema: error-responsemerchant_id.Schema: error-responsesku.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/{product_id}Get product by ID
Returns one product by its Carriyo product_id.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
| product_id | string | Yes | The Carriyo-assigned product identifier. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
product-responsemerchant_id.Schema: error-responseproduct_id.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/{product_id}Update product
Replaces the whole product record and returns the result.
What happens. Every field takes the value in the body. A field you omit is cleared, or reset to its default as on create. creation_date and creation_source are kept. That includes inventory_key: omit it and the product no longer carries one, while its inventory positions stay stored under the key.
What to send. product_ref is required. It may be a new value as long as no other product of the merchant uses it; the old value is released for reuse. product_id in the body is optional and must equal the path value.
Product types and custom attributes. The rules of Create product apply to the new record.
Use Patch product to change a few fields and keep the rest.
Idempotency. Supports optional Idempotency-Key for safe retries after timeouts or other uncertain network outcomes. See https://carriyo.com/docs/api/idempotency/.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
| product_id | string | Yes | The Carriyo-assigned product identifier. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| Content-Type | application/json | Yes | Media type of the request body. |
Header parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | No | Optional client-generated key that identifies one logical operation. Reuse the same key when retrying with the same payload. Replays the stored response. See https://carriyo.com/docs/api/idempotency/. |
Request body
application/jsonSchema: product-create-requestrequiredResponses
product-responseerror-responseThe request was rejected. One of:
product_refis missing or blank.- another product of the merchant already has this
product_ref. product_idin the body differs from the path.statusis notACTIVE,INACTIVEorDELETED.- the body is not valid JSON, or a value is outside its type or enum.
origin_countryis not a two-letter ISO 3166 code Carriyo recognizes.product_typeisPACKandpack_componentsis empty or has a component withoutproduct_ref.- a pack component has a
quantitythat is not above 0, or two components share aproduct_ref. product_typeisVARIANTandvariant_attributeshas a key other thancolororsize.custom_attributesnames an attribute not defined for products, carries a value the attribute does not allow, or the account is not subscribed to custom attributes.
merchant_id.Schema: error-responseproduct_id.Schema: error-responseproduct_ref. Nothing was stored; retry the request.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/{product_id}Patch product
Updates the fields present in the body and keeps every other field as it is.
Field rules.
product_ref: a new value replaces the current one and releases it for reuse by another product. An empty string is ignored; the reference cannot be removed.sku: an empty string clears it.inventory_key: a new value replaces the current one. An empty string is ignored.variant_parent_ref: an empty string clears it.carriyo_metadata: merged byname. A new name is added, an existing name takes the newvalue, and anullvalue removes the entry.custom_attributes: merged by attribute name. Anullvalue removes the attribute.pack_components,variant_attributes,weight,dimensionandbattery: replaced as a whole.product_id: optional and must equal the path value.
Product types and custom attributes. The rules of Create product apply to the merged record. Changing product_type to PACK therefore needs pack_components in the same request, unless the product already has them.
Idempotency. Supports optional Idempotency-Key for safe retries after timeouts or other uncertain network outcomes. See https://carriyo.com/docs/api/idempotency/.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
| product_id | string | Yes | The Carriyo-assigned product identifier. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| Content-Type | application/json | Yes | Media type of the request body. |
Header parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | No | Optional client-generated key that identifies one logical operation. Reuse the same key when retrying with the same payload. Replays the stored response. See https://carriyo.com/docs/api/idempotency/. |
Request body
application/jsonSchema: product-requestrequiredResponses
product-responseerror-responseThe request was rejected. One of:
product_idin the body differs from the path.statusis notACTIVE,INACTIVEorDELETED.- the body is not valid JSON, or a value is outside its type or enum.
- another product of the merchant already has the new
product_ref. origin_countryis not a two-letter ISO 3166 code Carriyo recognizes.- the merged record is a
PACKwhosepack_componentsis empty or has a component withoutproduct_ref. - a pack component has a
quantitythat is not above 0, or two components share aproduct_ref. - the merged record is a
VARIANTwhosevariant_attributeshas a key other thancolororsize. custom_attributesnames an attribute not defined for products, carries a value the attribute does not allow, or the account is not subscribed to custom attributes.
merchant_id.Schema: error-responseproduct_id.Schema: error-responseproduct_ref. Nothing was stored; retry the request.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/{product_id}Delete product
Deletes the product and returns the record as it was.
What happens. The product's product_ref is released for reuse by another product. When no other product carries the product's inventory_key, the inventory positions held against that key are deleted too. The request has no body.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
| product_id | string | Yes | The Carriyo-assigned product identifier. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
product-responsemerchant_id.Schema: error-responseproduct_id.Schema: error-responseproduct_ref. Nothing was deleted; retry the request.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/product-ref/{product_ref}Get product by product ref
Returns one product by your product_ref. The read is strongly consistent, so a product created or re-referenced a moment ago is found.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
| product_ref | string | Yes | Your reference for the product (`product_ref`). |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
product-responsemerchant_id.Schema: error-responseproduct_ref.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/product-ref/{product_ref}Delete product by product ref
Deletes the product identified by your product_ref and returns the record as it was.
What happens. The product_ref is released for reuse by another product. When no other product carries the product's inventory_key, the inventory positions held against that key are deleted too. The request has no body.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
| product_ref | string | Yes | Your reference for the product (`product_ref`). |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
product-responsemerchant_id.Schema: error-responseproduct_ref.Schema: error-responseproduct_ref. Nothing was deleted; retry the request.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/bulk/importBulk import products
Creates or updates up to 500 products in one request and reports a result for each item.
Matching. An item with product_id must match an existing product of the merchant; otherwise it is rejected. product_id is a lookup key only and is never written. An item without product_id is matched on product_ref, with a strongly consistent read. A matched product is updated with the field rules of Patch product. An unmatched item is created with the rules of Create product, so it needs product_ref.
Within the request. Items are de-duplicated on product_ref, or on product_id when no reference is given; a repeat is rejected with the reason Duplicate Item. sku plays no part in matching. variant_parent_ref and pack_components[].product_ref are stored unverified, so an item may name another item of the same request, in any order.
Results. The response has one entry per item, in request order, so entry n answers item n. result is created, updated or rejected, and reason carries the message. An item that lost a race with a concurrent write is rejected with a reason starting Processing failed:; resend that item.
Idempotency. Supports optional Idempotency-Key for safe retries after timeouts or other uncertain network outcomes. See https://carriyo.com/docs/api/idempotency/.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| Content-Type | application/json | Yes | Media type of the request body. |
Header parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Idempotency-Key | string | No | Optional client-generated key that identifies one logical operation. Reuse the same key when retrying with the same payload. Replays the stored response. See https://carriyo.com/docs/api/idempotency/. |
Request body
application/jsonrequiredAn array of bulk-product-request. Each item has the following fields:
Responses
An array of bulk-create-update-response. Each item has the following fields:
error-responseThe request was rejected. One of:
- the array has more than 500 items.
- the body is not valid JSON, or a value is outside its type or enum. The whole request is rejected; problems with one item come back as
rejectedentries instead.
merchant_id.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →
/products/{merchant_id}/bulkBulk delete products
Deletes up to 500 of the merchant's products in one call and reports the counts. This cannot be undone.
What happens. Each product's product_ref is released for reuse. Inventory positions are deleted for every inventory key that no remaining product carries. Products are deleted in parallel; a product that cannot be deleted is counted in failed_count and left in place.
Repeating. When more_items_available is true, 500 products were found and more may remain. Call again until it is false. The request has no body.
Outcome. Failures do not produce an error status. result is rejected and reason explains when the operation could not run at all; otherwise result is accepted and the counts tell you what happened.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
| merchant_id | string | Yes | The merchant identifier the product belongs to. |
Headers
| Name | Value | Required | Description |
|---|---|---|---|
| Authorization | Bearer YOUR-ACCESS-TOKEN | Yes | OAuth 2.0 bearer token obtained from `POST /oauth/token`. |
| x-api-key | YOUR-API-KEY | Yes | Your tenant's API key, issued in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
| tenant-id | YOUR-TENANT-ID | Yes | Your Carriyo tenant ID, shown in the Carriyo Dashboard. Required on every request except `POST /oauth/token`. |
Responses
bulk-delete-responsemerchant_id.Schema: error-responseNeed the full machine-readable spec? Download the OpenAPI document →