Developer
Items and stock
Products, services, materials and expenses — the catalogue, its stock, its movement and its prices.
Everything sellable or buyable is an item with a type discriminator. One resource, one scope: ops_products.
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /items | List — filter by type and status |
| POST | /items | Create — name required |
| GET | /items/types | The item types this business uses |
| GET | /items/categories | Categories (POST to create, PATCH /categories/{id} to rename) |
| GET | /items/{id} | Detail |
| PATCH | /items/{id} | Update |
| DELETE | /items/{id} | Delete |
Creating one
bash
curl -X POST https://api.trabalance.com/api/v1/items \
-H "Authorization: Bearer tk_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5a1c9e77-…" \
-d '{ "name": "Widget, 40 mm", "sku": "WID-040", "type": "Product",
"rate": 50.00, "cost": 32.00, "measurement": "Unit", "reorder_point": 25 }'| Field | Required | Notes |
|---|---|---|
| name | Yes | Unique within the business |
| sku, barcode | No | sku is unique within the business — and SKU or barcode, never the name, is the identity to match on from your side |
| type | No | Product (default), Service, Material, Expense |
| sub_type | No | buy (default), sell, both |
| rate, cost | No | Selling price and purchase cost |
| measurement | No | Unit of measure; defaults to "Unit" |
| reorder_point | No | Drives the low-stock signal in the app |
| category_id, income_account_id, expense_account_id, inventory_account_id | No | Ledger accounts fall back to the business defaults |
| valuation_method | No | Defaults to the business's method |
Stock, movement and figures
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /items/{id}/stock | Quantity on hand, by location |
| GET | /items/{id}/movement | What moved, when, and the running balance |
| GET | /items/{id}/stats | Inventory statistics for the item |
| GET | /items/{id}/adjustments | Adjustments (POST to record one) |
⚠️Never recompute an inventory figure
Quantities, values and running balances come from the inventory producer and are rendered as they arrive. Re-deriving a running balance from movement rows on your side produces a second answer — and a second answer is a wrong answer, because a per-location view has gaps another location's activity left behind. Ask for the scope you want and read the figure it returns.
Pricing
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /items/{id}/pricing | Prices, per location |
| PATCH | /items/{id}/pricing | Update pricing |
| GET | /items/{id}/price-history | What the price has been |
| GET | /items/{id}/discounts | Discounts (POST to save, DELETE /discounts/{discountId} to remove) |
Reads need ops_products:read; creates need :create, updates :update, deletes :delete.
Related
- Invoices — items become invoice lines
- Request bodies
- Permission scopes