Start here
Authentication
Every endpoint except the health check requires an API key. Keys are created in the desktop app and belong to the user who created them — a call made with your key can do exactly what you can do, and nothing more.
Create a key#
- 1
Open the API key settings
In IntelligenceBox, go to Settings → System → API key. - 2
Name it after what will use it
A label likezapier-invoicesorci-notificationsmakes it obvious later which key to revoke. - 3
Copy the key
It starts withkey-and is shown once. Store it in your secret manager, not in source control.
Treat the key like a password
A key carries its owner’s full access to the box: their folders, their assistants, their conversations. Anyone holding it can read those. Revoke a key the moment it might have leaked — the same settings screen lists and deletes them.Sending the key#
Either header works. Pick one and use it consistently.
x-api-key: YOUR_API_KEY
# or, if your HTTP client prefers standard auth:
Authorization: Bearer YOUR_API_KEYcurl BOX_URL/api/public/me \
-H "x-api-key: YOUR_API_KEY"GET /api/public/me is the cheapest way to verify a key: it returns the identity behind it, the workspace the request resolved to, and a few counts. Use it as a connectivity check before doing real work.
Workspace scoping#
Optional headers that decide which workspace a request reads and writes in.
x-organization-idstring- The organization workspace the request belongs to. Omit it and the call is scoped to the key owner’s personal workspace.
x-organization-scopePERSONAL | ORGANIZATION | LEGACY- How resources created by this request are scoped. Ignored unless
x-organization-idis also set.Default:PERSONAL.
Sensible default
Without these headers, everything you create — folders, assistants, notifications — lands in the key owner’s personal workspace. That is deliberate: a stray header should never be able to publish resources into an organization the key was not granted.Error responses#
Every failure uses the same envelope, so you can branch on code rather than parsing prose:
{
"error": "Request body validation failed",
"code": "VALIDATION_ERROR",
"details": [
{ "path": "title", "message": "Expected string, received number" }
]
}400VALIDATION_ERROR— the body or query is malformed.detailslists the offending fields.401UNAUTHORIZED— missing, malformed, or revoked key.403FORBIDDEN— the key is valid but its owner cannot touch this resource.404NOT_FOUND— no such resource, or one you are not allowed to know exists.409CONFLICT— a uniqueness rule rejected the write, e.g. an assistant handle already in use.500INTERNAL_ERROR— something failed on the box. Safe to retry with backoff.
404 is sometimes a 403 in disguise
Endpoints that mutate a resource answer404 when the caller can see the object but does not own it. That is intentional — an assistant shared with your team should not confirm its existence to a key that cannot edit it.The one unauthenticated endpoint#
GET /health takes no key. Use it for uptime monitoring and to tell “box unreachable” apart from “bad credentials”.
curl BOX_URL/health
# {"status":"ok"}