Products endpoints
Products are read-only over the API today. You can list them (with filters) and fetch them individually. Write endpoints (create, update, delete) aren't exposed yet — manage products through the dashboard or CSV import for now.
GET /api/v1/products
List products in your company.
Required scope: products:read
Query parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Page size, capped at 100. See Pagination. |
cursor | string | — | Pagination cursor from a previous response. |
category | string | — | Exact-match filter on category. |
search | string | — | Case-insensitive substring match on name, sku, or category. |
active | true / false | — | Filter by isActive. Any other value is ignored. |
Example
curl "https://distribu.app/api/v1/products?active=true&limit=100" \
-H "Authorization: Bearer dk_..."
Response
{
"data": [
{
"id": "clxx1234abc...",
"name": "Widget Blue",
"sku": "WDG-001",
"description": "A small blue widget.",
"category": "Hardware",
"unit": "each",
"price": 8.5,
"stock": 42,
"imageUrl": "https://images.distribu.app/products/widget-blue.png",
"isActive": true,
"createdAt": "2026-03-01T12:00:00.000Z",
"updatedAt": "2026-04-10T09:30:00.000Z"
}
],
"pagination": {
"hasMore": false,
"nextCursor": null
}
}
Sorted by createdAt descending — newest products first.
Notes on fields
price— Returned as a JSON number (not a string). Precision is two decimal places internally.stock— Integer count. May be negative transiently during high-concurrency order bursts; rare but possible.description,sku,imageUrl,category— All can benull.unit— Always a string (each,case,lb,kg, whatever you've configured). Defaults toeachfor products that don't set it.
GET /api/v1/products/{id}
Fetch a single product by its ID.
Required scope: products:read
Example
curl https://distribu.app/api/v1/products/clxx1234abc... \
-H "Authorization: Bearer dk_..."
Response
{
"data": {
"id": "clxx1234abc...",
"name": "Widget Blue",
"sku": "WDG-001",
"description": "A small blue widget.",
"category": "Hardware",
"unit": "each",
"price": 8.5,
"stock": 42,
"imageUrl": "https://...",
"isActive": true,
"createdAt": "2026-03-01T12:00:00.000Z",
"updatedAt": "2026-04-10T09:30:00.000Z"
}
}
Errors
404—Product not found.— The ID doesn't exist, or belongs to another company, or you passed a malformed ID.
Common patterns
Sync your catalog to a downstream system
Paginate through GET /api/v1/products daily. Store updatedAt with each
synced record. You don't have a server-side ?since= filter today, so
you'll need to do a full scan and compare timestamps locally.
Find a product by SKU
There's no direct SKU lookup endpoint, but search does a
case-insensitive substring match across name, SKU, and category:
curl "https://distribu.app/api/v1/products?search=WDG-001&limit=5" \
-H "Authorization: Bearer dk_..."
Then filter client-side by sku === "WDG-001" to discard partial matches
(if your SKUs aren't unique substrings).
Handling stock
Stock is only accurate at the moment of the response. A concurrent order
placement from the storefront or POST /api/v1/orders can decrement it
between your read and your next write. Treat stock as a guidance value,
not a reservation — actual stock enforcement happens server-side at
order-creation time.
What's not here (yet)
POST /api/v1/products— Create a product.PATCH /api/v1/products/{id}— Update fields.PATCH /api/v1/products/{id}/stock— Adjust stock directly (useful for returns / receiving shipments).DELETE /api/v1/products/{id}— Soft-delete (isActive = false).
All planned. Email us if any of these are blocking an integration and we'll prioritize.
Next: Orders endpoints.
