Consuming the API
Cannahub does not publish official client SDKs. There is no @cannahub/* package for JavaScript, Python, Ruby, Go or any other language. You consume the API directly over HTTPS with whatever HTTP client your stack already uses — fetch, axios, cURL, etc. This page shows the patterns that work today.
If you find an unofficial third-party client, treat it as community software — it is not maintained by Cannahub and may lag behind the API.
Authentication pattern
Every request needs two things (see Authentication for the full flow):
- Name
Authorization- Type
- string
- Description
A Bearer JWT:
Authorization: Bearer {token}. Obtain the token from the auth endpoints (/auth/customer/emailpassfor members,/auth/user/emailpassfor staff/admin).
- Name
Tenant-id- Type
- string
- Description
The organization (club) the request targets, e.g.
Tenant-id: high-up. Required for tenant-scoped writes and used to filter tenant-scoped reads.
The base URL for the production API is https://api.cannahub.tech.
Examples
Authenticated request
curl https://api.cannahub.tech/api/members \
-H "Authorization: Bearer {token}" \
-H "Tenant-id: high-up"
Creating a resource works the same way — send a JSON body and read the returned entity:
Creating a member
const { member } = await api<{ member: Member }>('/api/members', {
method: 'POST',
body: JSON.stringify({
firstName: 'Juan',
lastName: 'Pérez',
email: 'juan@club.com',
}),
})
List endpoints are paginated with limit/offset and return a count — see Pagination. Errors follow a single { error: { code, message, details? } } shape — see Errors.
How the web frontend consumes the API
The Cannahub web app (Next.js) does not use a generated SDK either. It organizes API access per domain using TanStack Query (React Query) hooks, colocated with each feature. Each domain exposes typed query and mutation hooks that wrap the corresponding /api/* routes, so components never call fetch directly.
Per-domain hooks (frontend pattern)
// List
const { data, isLoading } = useInventoryItemsQuery({
locationId: 'sloc_high_up',
})
// Mutate
const updateLevel = useUpdateInventoryLevelMutation()
updateLevel.mutate({
inventoryItemId: 'iitem_01HQ_BD_7G',
locationId: 'sloc_high_up',
data: { stockedQuantity: 60 },
})
These hooks are documented alongside their entity. For example, the inventory hooks live on the Inventory API page and the member hooks on the Members API page. If you are building against Cannahub from an external app, replicate the same shape: one small typed client per domain that centralizes the Bearer + Tenant-id headers and the shared error handling.