Modules

Products

Physical products with cost, barcode, category and brand, on top of the catalog.

Overview

A product is a catalog item (itm_...) of type product with an extra profile: cost price, barcode, category, brand and shelf life. Products can be used in quotes and invoices like any item, and they are what the Inventory, Purchases, Point of sale and Work orders modules move.

Requires the Products module. An owner or admin turns it on in Settings > Modules. While it is off, every endpoint on this page returns 403 with type permission_error and code module_disabled.

The Product Object

JSON
1{
2 "id": "itm_9f2c1a",
3 "object": "product",
4 "item_code": "PRD-000012",
5 "name": "USB-C cable 2m",
6 "description": "Braided cable",
7 "unit": "unit",
8 "unit_price": 12.5,
9 "currency": "USD",
10 "tax_rate": 18,
11 "cost_price": 4.2,
12 "barcode": "7750000000012",
13 "category_id": "pcat_1a2b",
14 "category_name": "Accessories",
15 "brand_id": "pbrd_3c4d",
16 "brand_name": "Anker",
17 "expiry_days": null,
18 "image_url": null,
19 "is_active": true,
20 "created_at": "2026-10-11T15:00:00.000Z",
21 "updated_at": "2026-10-11T15:00:00.000Z"
22}
FieldDescription
item_codeGenerated with the module numbering when you omit it (prefix editable in Settings > Prefixes)
unit_priceSale price in the major unit of currency (2 decimals)
cost_priceUnit cost, up to 4 decimals. Used for margins and as the default cost of stock
barcodeUnique per company. A duplicate returns 409 resource_conflict
category_id / brand_idOptional masters (pcat_..., pbrd_...) with their names expanded
expiry_daysShelf life in days (0 to 36500), or null
image_urlSigned URL valid for about 24 hours

Endpoints

MethodPathPermissionDescription
GET/v1/productsreadList products (query, category_id, brand_id, barcode, is_active)
POST/v1/productswriteCreate a product (Idempotency-Key supported)
GET/v1/products/{id}readRetrieve a product
POST/v1/products/{id}writeUpdate a product (PATCH is accepted as an alias)
DELETE/v1/products/{id}adminDelete a product (soft delete)
GET/v1/product-categoriesreadList categories (query)
POST/v1/product-categoriesadminCreate a category
GET/v1/product-brandsreadList brands (query)
POST/v1/product-brandsadminCreate a brand

Create a Product

1curl -X POST "https://api.corebill.io/v1/products" \
2 -H "Authorization: Bearer sk_live_your_api_key" \
3 -H "Content-Type: application/json" \
4 -H "Idempotency-Key: prd-usb-c-2m" \
5 -d '{
6 "name": "USB-C cable 2m",
7 "unit_price": 12.5,
8 "currency": "USD",
9 "cost_price": 4.2,
10 "barcode": "7750000000012",
11 "category_id": "pcat_1a2b",
12 "brand_id": "pbrd_3c4d"
13 }'

name and unit_price (a JSON number) are required. The product starts active, unit defaults to unit and currency to USD. Creating a product emits item.created; updating it emits item.updated and deleting it item.deleted.

Find a Product by Barcode

1curl "https://api.corebill.io/v1/products?barcode=7750000000012" \
2 -H "Authorization: Bearer sk_live_your_api_key"

Categories and Brands

Categories and brands are simple masters with a name. Creating them is module configuration, so it needs an admin key; a name that already exists returns 409 resource_conflict.

1curl -X POST "https://api.corebill.io/v1/product-categories" \
2 -H "Authorization: Bearer sk_live_your_admin_key" \
3 -H "Content-Type: application/json" \
4 -d '{ "name": "Accessories" }'