API Reference
Complete reference for the FabHub public API. The branded portal is canonical; you can also load the machine-readable contract into any OpenAPI viewer (Swagger Editor, Redoc, Postman, or your IDE).
Base URL
https://api.fabhub.app/v1
Conventions
- Authenticate with
X-API-Key(orAuthorization: Bearer). See Authentication. - Request bodies are JSON with
camelCasekeys; list filters aresnake_casequery parameters. - List endpoints are page-based and return a
paginationobject; see Pagination. - Write endpoints require an
Idempotency-Keyheader; see Idempotency. - Errors use a stable envelope with a machine-readable
code; see Errors.
All endpoints
This table is generated from the OpenAPI contract and always lists every public operation and its required scope. The sections below are worked examples for the most common resources; the OpenAPI contract is the exhaustive source for request and response schemas.
| Method | Path | Scope |
|---|---|---|
GET | /v1 | authenticated |
GET | /v1/audit/events | audit:read |
GET | /v1/auth/context | authenticated |
GET | /v1/contacts | contacts:read |
POST | /v1/contacts | contacts:write |
DELETE | /v1/contacts/{contact_id} | contacts:write |
GET | /v1/contacts/{contact_id} | contacts:read |
PATCH | /v1/contacts/{contact_id} | contacts:write |
GET | /v1/items | items:read |
POST | /v1/items | items:write |
DELETE | /v1/items/{item_id} | items:write |
GET | /v1/items/{item_id} | items:read |
PATCH | /v1/items/{item_id} | items:write |
GET | /v1/items/{item_id}/ingredients | items:read |
POST | /v1/items/{item_id}/ingredients | items:write |
DELETE | /v1/items/{item_id}/ingredients/{ingredient_id} | items:write |
PATCH | /v1/items/{item_id}/ingredients/{ingredient_id} | items:write |
GET | /v1/items/{item_id}/suppliers | items:read |
POST | /v1/items/{item_id}/suppliers | items:write |
DELETE | /v1/items/{item_id}/suppliers/{supplier_id} | items:write |
PATCH | /v1/items/{item_id}/suppliers/{supplier_id} | items:write |
GET | /v1/orders | orders:read |
POST | /v1/orders | orders:write |
GET | /v1/orders/{order_id} | orders:read |
PATCH | /v1/orders/{order_id} | orders:write |
GET | /v1/orders/{order_id}/lines | orders:read |
GET | /v1/organization | organization:read |
GET | /v1/stock-documents | inventory:read |
POST | /v1/stock-documents | inventory:write |
DELETE | /v1/stock-documents/{document_id} | inventory:write |
GET | /v1/stock-documents/{document_id} | inventory:read |
PATCH | /v1/stock-documents/{document_id} | inventory:write |
POST | /v1/stock-documents/{document_id}/approve | inventory:write |
POST | /v1/stock-documents/{document_id}/cancel | inventory:write |
GET | /v1/stock-documents/{document_id}/lines | inventory:read |
POST | /v1/stock-documents/{document_id}/lines | inventory:write |
DELETE | /v1/stock-documents/{document_id}/lines/{line_id} | inventory:write |
PATCH | /v1/stock-documents/{document_id}/lines/{line_id} | inventory:write |
POST | /v1/stock-documents/{document_id}/submit | inventory:write |
GET | /v1/stock-levels | inventory:read |
GET | /v1/usage | usage:read |
GET | /v1/webhooks | webhooks:read |
POST | /v1/webhooks | webhooks:write |
DELETE | /v1/webhooks/{webhook_id} | webhooks:delete |
GET | /v1/webhooks/{webhook_id} | webhooks:read |
PATCH | /v1/webhooks/{webhook_id} | webhooks:write |
GET | /v1/webhooks/{webhook_id}/deliveries | webhooks:deliveries:read |
Service
GET /v1
Returns the capabilities (method, path, scope) the calling credential can use. No scope required.
GET /v1/auth/context
Returns the calling credential's tenant, plan, scopes, rate-limit tier, and expiry. No scope required. See the example in Quickstart.
Items
GET /v1/items
Scope: items:read. Lists items (products, materials, combos).
| Query | Type | Notes |
|---|---|---|
page | integer | 1-based page number (default 1) |
page_size | integer | Items per page (default 20) |
search | string | Free-text match on name/SKU |
curl "https://api.fabhub.app/v1/items?page=1&page_size=2&search=widget" \
-H "X-API-Key: $FABHUB_API_KEY"
{
"data": [
{
"id": "a1c9...",
"name": "Blue Widget",
"sku": "WIDG-BLUE",
"itemType": "product",
"salePrice": 19.99,
"purchasePrice": 8.5,
"isActive": true,
"category": { "id": "cat_1", "name": "Widgets" },
"supplier": { "id": "sup_1", "name": "Acme", "company": "Acme Ltd" },
"updatedAt": "2026-06-19T14:02:00Z"
}
],
"pagination": { "page": 1, "pageSize": 2, "total": 57, "totalPages": 29 }
}
POST /v1/items
Scope: items:write. Requires Idempotency-Key. Creates an item.
| Body field | Type | Notes |
|---|---|---|
name | string | Required |
itemType | product | material | combo | Defaults to product |
sku, mpn, barcode | string | null | Optional identifiers |
categoryId, unitId, supplierId | string | null | Optional references |
salePrice, purchasePrice | number | null | Optional pricing |
supplierCode, notes | string | null | Optional |
isActive | boolean | Defaults to true |
curl -X POST https://api.fabhub.app/v1/items \
-H "X-API-Key: $FABHUB_API_KEY" \
-H "Idempotency-Key: 0b9c4a2e-..." \
-H "Content-Type: application/json" \
-d '{"name":"Blue Widget","itemType":"product","salePrice":19.99}'
Returns { "data": { ...item } } with the created item.
GET /v1/items/{item_id}
Scope: items:read. Returns { "data": { ...item } }, or 404 with code: "NOT_FOUND".
PATCH /v1/items/{item_id}
Scope: items:write. Requires Idempotency-Key. Accepts any subset of the create fields and returns the updated item.
Item sub-resources
GET /v1/items/{item_id}/ingredients(scopeitems:read) - components for acombo/manufactured item.GET /v1/items/{item_id}/suppliers(scopeitems:read) - suppliers linked to an item.
Orders
GET /v1/orders
Scope: orders:read.
| Query | Type | Notes |
|---|---|---|
module | buy | sell | make | check | fix | Required |
status | order status | Optional filter (draft, open, in_progress, waiting, completed, cancelled) |
page, page_size, search | - | Standard list parameters |
{
"data": [
{
"id": "ord_1",
"module": "sell",
"orderNumber": "SO-1042",
"status": "open",
"contactId": "con_7",
"orderDate": "2026-06-18",
"dueDate": "2026-06-25",
"siteId": null,
"priority": "normal",
"assignedTo": null,
"contact": { "id": "con_7", "name": "Globex" },
"site": null,
"createdAt": "2026-06-18T10:00:00Z",
"updatedAt": "2026-06-18T10:05:00Z"
}
],
"pagination": { "page": 1, "pageSize": 20, "total": 3, "totalPages": 1 }
}
Orders also support POST /v1/orders, GET /v1/orders/{order_id}, and PATCH /v1/orders/{order_id} (writes require Idempotency-Key), plus GET /v1/orders/{order_id}/lines (scope orders:read) for line items. See the OpenAPI contract for the exact request bodies.
Contacts
GET /v1/contacts
Scope: contacts:read.
| Query | Type | Notes |
|---|---|---|
contact_types | string | Comma-separated: customer, supplier, both |
page, page_size, search | - | Standard list parameters |
Each contact: id, name, email, phone, company, contactType, country, contactGroup, isPrimaryContact, isActive, updatedAt.
Contacts also support POST /v1/contacts, GET /v1/contacts/{contact_id}, and PATCH /v1/contacts/{contact_id} (writes require Idempotency-Key); see the OpenAPI contract for fields.
Organization
GET /v1/organization
Scope: organization:read. Returns { "data": { "id", "name", "slug", "plan", "createdAt" } } where plan is free | standard | pro | enterprise.
Usage
GET /v1/usage
Scope: usage:read. Returns the current billing period, request totals (overall and by capability), and the rate-limit tier with remaining budget. See Rate Limits.
Audit events
GET /v1/audit/events
Scope: audit:read (Enterprise). Cursor-paginated export.
| Query | Type | Notes |
|---|---|---|
since, until | ISO 8601 | Time window |
action_prefix | string | Filter by action prefix |
actor_type | user | system | api | Filter by actor |
limit | integer | Page size |
cursor_created_at, cursor_id | - | Resume from a previous page |
{
"data": [
{
"id": "evt_1",
"actorType": "api",
"actorId": "key_8f...",
"action": "item.created",
"resourceType": "item",
"resourceId": "a1c9...",
"metadata": {},
"ipAddress": "203.0.113.10",
"createdAt": "2026-06-19T14:02:00Z"
}
],
"pagination": { "hasMore": true, "nextCursor": { "createdAt": "2026-06-19T14:02:00Z", "id": "evt_1" } }
}
Stock
GET /v1/stock-levels
Returns current stock levels for the tenant's items (see the table above for the required scope, and the OpenAPI contract for filters and the response shape).
Webhooks
Full lifecycle and signing details are in Webhooks.
| Method | Path | Scope |
|---|---|---|
GET | /v1/webhooks | webhooks:read |
POST | /v1/webhooks | webhooks:write (Enterprise) |
GET | /v1/webhooks/{webhook_id} | webhooks:read |
PATCH | /v1/webhooks/{webhook_id} | webhooks:write |
DELETE | /v1/webhooks/{webhook_id} | webhooks:delete |
GET | /v1/webhooks/{webhook_id}/deliveries | webhooks:deliveries:read |