Products
Products are the foundation of your commerce catalog—each product represents something you sell, whether physical goods requiring shipping, digital downloads, or intangible services. The Products API gives you precise control over every aspect of your offerings: pricing across currencies, rich media galleries, custom attributes for variants, shipping dimensions, tax classification, and arbitrary metadata for your own business logic.
Create, add price, update, publish, unpublish, and archive support idempotency. A successful response can be replayed with the same idempotency key and request body for 24 hours. Lookup and page do not opt in to idempotent replay.
The product object
A product object contains everything needed to list, sell, and fulfill an item: core identification fields (name, description, reference), pricing information, prices attached to the product, categorization for reporting and filtering, media assets for customer-facing displays, physical dimensions for shipping calculations, and extensible custom data for application-specific needs. Products belong to a specific application and can be referenced in order line items.
Properties
Product media fields can store either Commerce file references or plain remote URLs. Prefer File API IDs when you want Commerce to validate ownership, enforce file-purpose rules, and prevent deleting files that products still reference. Keep web_page_url for the product's canonical landing page only.
Create a product
Create a new product in your catalog with media, attributes, and fulfillment details. Products must have a name and type. Create prices separately after the product exists.
The product type determines which optional fields are relevant: physical products should include dimensions and shipment details for carrier calculations, digital products benefit from download URLs and file sizes, services typically need only core information. You can update products later as your catalog evolves.
Request attributes
- Name
custom_data- Type
- object
- Description
Arbitrary string key-value pairs for application-specific needs. Attach internal catalog IDs, supplier references, merchandising metadata, or any data your system requires. Maximum size when serialized: 25 KB. See the Custom Data guide for best practices.
Request
curl https://api.zebo.dev/products/create \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Cotton T-Shirt",
"type": "physical",
"description": "Comfortable everyday wear",
"about": "Our premium cotton t-shirt is made from 100% organic cotton...",
"category": "clothing",
"attributes": [
{ "name": "Size", "value": "Medium" },
{ "name": "Color", "value": "Blue" }
],
"media": {
"hero_image": "file_abc123",
"gallery": ["file_def456", "file_ghi789"]
},
"custom_data": {
"season": "summer",
"material": "organic_cotton"
}
}'
{
"product": {
"id": "prod_abc123xyz789",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": false,
"description": "Comfortable everyday wear",
"category": "clothing",
"reference": "SKU-SHIRT-BLUE-M-2024",
"created_at": "2026-02-08T23:45:00Z"
}
}
Lookup a product
Retrieve the complete details of a previously created product by its ID. This returns all product information including media assets, attributes, dimensions, shipment configuration, and custom metadata. Use this to display product details in your catalog, verify product information before adding to orders, or refresh cached product data.
The endpoint requires only the product ID—all other details come from the stored product record. Products are scoped to your authenticated application, so you can only lookup products you own. If the product doesn't exist or has been archived, you'll receive an error.
Request attributes
Request
curl https://api.zebo.dev/products/lookup \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123xyz789"
}'
{
"product": {
"id": "prod_abc123xyz789",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": false,
"description": "Comfortable everyday wear",
"category": "clothing",
"reference": "SKU-SHIRT-BLUE-M-2024",
"attributes": [
{
"name": "Size",
"value": "Medium"
},
{
"name": "Color",
"value": "Blue"
}
],
"prices": [
{
"id": "pr_abc123xyz789",
"active": true,
"nominal": {
"currency": "usd",
"value": 2999
}
}
],
"created_at": "2026-02-08T23:45:00Z",
"updated_at": "2026-02-08T23:50:15Z"
}
}
Add a price to a product
Create a price attached to an existing product. The operation returns the created price; the product object has no default-price field or default-price mutation.
This operation supports idempotency. Send the same idempotency_key and request body to replay a successful response for up to 24 hours.
Request attributes
Request
curl https://api.zebo.dev/products/add_price \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123xyz789",
"label": "Wholesale",
"about": "Preferred rate for repeat buyers",
"amount": {
"currency": "ghs",
"value": 85000
}
}'
{
"price": {
"id": "pr_abc123xyz789",
"label": "Wholesale",
"about": "Preferred rate for repeat buyers",
"active": true,
"nominal": {
"currency": "ghs",
"value": 85000
},
"product_id": "prod_abc123xyz789",
"created_at": "2026-02-08T23:55:00Z"
}
}
Update a product
Modify an existing product's details by providing only the fields you want to change. Any field you omit remains unchanged. Update or create prices through the Prices API; this endpoint rejects inline price data.
The endpoint requires the product ID and at least one field to update. Some fields like name, about, and tax_code cannot be cleared once set—they can only be updated to new non-empty values. This protects data integrity for fields that affect downstream systems like invoicing and tax calculations.
For media changes, send the full media object you want stored. The legacy images array is still accepted and maps to media.gallery for backward compatibility.
Request attributes
Request
curl https://api.zebo.dev/products/update \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123xyz789",
"description": "Premium everyday comfort",
"category": "apparel"
}'
{
"product": {
"id": "prod_abc123xyz789",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": false,
"description": "Premium everyday comfort",
"category": "apparel",
"reference": "SKU-SHIRT-BLUE-M-2024",
"created_at": "2026-02-08T23:45:00Z",
"updated_at": "2026-02-09T15:30:00Z"
}
}
Publish a product
Make a product publicly available by publishing it. Publishing sets active to true, making the product available through Zebo checkout—customers can access shareable product links and complete purchases. This also controls visibility in your storefront.
The published_at timestamp is set only on the first publish and never changes, even if you unpublish and republish later. This preserves the original publication date for historical tracking. The endpoint fails if the product is already published—unpublish it first if you need to modify publication state.
Request attributes
Request
curl https://api.zebo.dev/products/publish \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123xyz789"
}'
{
"product": {
"id": "prod_abc123xyz789",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": true,
"category": "apparel",
"created_at": "2026-02-08T23:45:00Z",
"published_at": "2026-02-09T16:30:00Z",
"updated_at": "2026-02-09T16:30:00Z"
}
}
Unpublish a product
Remove a product from public availability by unpublishing it. Unpublishing sets active to false while preserving the published_at timestamp—you retain the historical record of when the product was first published. Inactive products are unavailable through Zebo checkout: shareable product links stop working and customers can't complete purchases. This also hides the product from your storefront.
The endpoint fails if the product is already unpublished. Unlike archiving, unpublished products remain in your catalog and can be republished at any time. Use this for temporary removal from sale: seasonal products, out-of-stock items, or products under revision. Existing orders with the product remain unaffected.
Request attributes
Request
curl https://api.zebo.dev/products/unpublish \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123xyz789"
}'
{
"product": {
"id": "prod_abc123xyz789",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": false,
"category": "apparel",
"created_at": "2026-02-08T23:45:00Z",
"published_at": "2026-02-09T16:30:00Z",
"updated_at": "2026-02-09T17:15:00Z"
}
}
Archive a product
Permanently retire a product from your catalog by archiving it. Archiving sets archived_at timestamp and active to false. Archived products can't be published, modified, or added to new orders. This action is irreversible—archived products cannot be unarchived.
The endpoint fails if the product is already archived. Archive products you'll never sell again: discontinued items, replaced products, legacy SKUs. Unlike unpublishing (temporary), archiving signals permanent retirement. Existing orders with archived products remain unaffected—archiving only prevents future use.
Request attributes
Request
curl https://api.zebo.dev/products/archive \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_id": "prod_abc123xyz789"
}'
{
"product": {
"id": "prod_abc123xyz789",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": false,
"category": "apparel",
"created_at": "2026-02-08T23:45:00Z",
"archived_at": "2026-02-09T18:00:00Z",
"updated_at": "2026-02-09T18:00:00Z"
}
}
Page through products
Browse your product catalog in pages. Products are sorted by created_at in descending order—page 1 always contains the newest entries and subsequent pages step back in time.
Each response returns the full product object, including all fields: media assets, attributes, dimensions, shipment details, and custom data. page_number is required; page_size defaults to 256 if omitted.
Request attributes
Response shape
- Top-level
pageobject containingnumber,size, and aproductsarray. - Each entry is a full product object identical to what Lookup a product returns: all core fields, optional nested objects (
media,dimensions,attributes,shipment), and lifecycle timestamps. - Stop paginating when the response
sizeis less than thepage_sizeyou requested, or whenproductsis an empty array.
Request
curl https://api.zebo.dev/products/page \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"page_number": 1,
"page_size": 50
}'
{
"page": {
"number": 1,
"size": 2,
"products": [
{
"id": "prod_mK9XzR2qLpT4nW8sVcJ1bHfYuAeD3gN5oI6Ph7Qa",
"name": "Premium Cotton T-Shirt",
"type": "physical",
"active": true,
"description": "Comfortable everyday wear",
"category": "clothing",
"reference": "SKU-SHIRT-BLUE-M",
"tax_code": "TX-APPAREL",
"attributes": [
{ "name": "Size", "value": "Medium" },
{ "name": "Color", "value": "Blue" }
],
"prices": [
{
"id": "pr_M4n8Q2w7X5z1C9v6B3k0LpR",
"active": true,
"label": "Retail",
"nominal": {
"currency": "usd",
"value": 2999
}
},
{
"id": "pr_J7s3D1f9H6k2L8m5N4p0QwT",
"active": false,
"label": "Wholesale",
"nominal": {
"currency": "usd",
"value": 2799
}
}
],
"media": {
"hero_image": "file_abc123",
"thumbnail": "file_xyz789"
},
"created_at": "2026-01-15T09:30:00Z",
"published_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-02-01T14:22:00Z"
},
{
"id": "prod_aB3CdE4FgH5IjK6LmN7OpQ8RsT9UvW0XyZ1AbCd",
"name": "Annual SaaS Subscription",
"type": "digital",
"active": true,
"description": "Unlimited platform access",
"category": "software",
"created_at": "2026-01-10T08:00:00Z",
"published_at": "2026-01-10T08:05:00Z"
}
]
}
}