Errors
Handle Lookio API failures with one error format, stable error codes, request IDs and retry guidance, with an explanation for every code.
Every failure of the API uses one envelope. Branch on error.code, never on the message.
{
"error": {
"type": "permission_error",
"code": "insufficient_scope",
"message": "This credential does not have the 'resources:write' scope. Grant it at https://dashboard.lookio.app/developer on the workspace that owns the credential, or use a credential that already has it.",
"docs_url": "https://lookio.app/docs/api/errors#insufficient_scope"
},
"request_id": "req_0123456789abcdef0123456789abcdef"
}| Field | Meaning |
|---|---|
error.type | The family of the failure. |
error.code | The stable code. Adding a code is not a breaking change, so handle unknown codes with their type and HTTP status. |
error.message | A sentence that names the offending value and, where possible, the fix. Do not parse it. |
error.param | The field at fault, when there is one. |
error.docs_url | The explanation of the code, on this page. |
error.action_url | A link to fix it, when there is one, such as the Permissions page. |
request_id | Also in the X-Request-Id header. Keep it in your logs. |
The error types are invalid_request_error, authentication_error, permission_error, not_found_error, conflict_error, rate_limit_error and api_error.
A 401 also carries a WWW-Authenticate header, a 405 carries Allow and a 429 carries Retry-After.
Status codes
| Status | Meaning | What to do |
|---|---|---|
| 400 | Malformed request, unknown field, bad value | Fix the request. |
| 401 | Credential missing, invalid, expired or revoked | Replace or renew it. |
| 402 | Not enough credits | Add credits, then ask again. |
| 403 | Authenticated but not allowed | Grant the scope or permission. |
| 404 | Absent, or in another workspace | Check the ID and the workspace. |
| 409 | The current state conflicts with the request | Read the resource, then decide. |
| 405 | The endpoint exists, but not for this HTTP method | Use a method listed in the Allow header. |
| 413 | Body or file too large | Send less. |
| 422 | Valid request that the plan cannot take | Change the plan or the content. |
| 429 | Rate limited | Wait for Retry-After. |
| 500, 503 | Lookio failed, or is briefly unavailable | Retry with backoff. |
A resource of another workspace answers the same resource_not_found as one that does not exist, so the API never reveals what other workspaces hold.
Authentication codes
authentication_required
No bearer credential was sent. Add the Authorization: Bearer header.
invalid_api_key
The credential is malformed or unknown, or an OAuth token was used on a resource it was not issued for. Check that the whole sk_live_... value was copied.
invalid_access_key
An access (/a/{access_id}) refused the key: it is malformed, revoked, belongs to another access, or is a workspace API key (sk_live_...) where an access key (ak_live_...) is needed. Ask the access’s owner for a key.
api_key_expired
The credential passed its expiry date. Create a replacement.
api_key_revoked
An admin revoked or rotated the key, or the person who authorised a connection is no longer a member of the workspace. Use an active credential.
Permission codes
insufficient_scope
The credential is valid but lacks the scope this endpoint needs. The message names the scope. See Authentication.
feature_not_available
The plan or the kind of credential does not include this. Granular member permissions need a paid plan, and thumbs on an answer (Send feedback on an answer) work for an API key’s conversations, not yet for a person’s own chats.
admin_required
Only a workspace admin may do this, for example renaming a tag or listing members. Use a personal connection signed in by an admin.
permission_denied
The person behind a connection lacks a Lookio permission, such as creating resources, or using the API or MCP on a paid plan. The error carries an action_url to the Permissions page. Ask a workspace admin.
Request codes
invalid_request
The request cannot be understood: the JSON is malformed, a required value is missing, or two options exclude each other, such as conversation_id with history.
unknown_field
A property of the JSON body is not recognised. The message suggests the closest valid field. Unknown query parameters never cause this error: they are ignored.
invalid_parameter
A value is invalid. error.param names the field. A bad Idempotency-Key also lands here.
invalid_cursor
The cursor matches no resource. Start again from the first page.
request_too_large
The JSON body is over 1 MB, or a file is over the limit of its format. See File formats.
method_not_allowed
The path is an endpoint, but not for this HTTP method. The status is 405 and the Allow header lists the methods it does answer, for example GET, POST on /v1/resources.
Not found and conflict codes
resource_not_found
The ID does not exist in this workspace, or the caller may not see it. This covers resources, assistants, widgets, conversations, members and tags, and a path that is not an endpoint.
conflict
The request is valid but the current state forbids it: a resource that an assistant still uses cannot be deleted, an assistant that a widget still uses cannot be deleted, a site action was sent to a resource that is not a site, or an Idempotency-Key was reused for a different request or is still running. Read the state, then decide.
assistant_has_no_resources
The assistant reads no resource, so it cannot answer: none is connected (a Selected pick that is empty, a Tags mode with a tag nobody carries, or All in a workspace with no resource), or none is ready yet. The question is refused before any credit is held and before any model runs, so it costs nothing. The status is 409. Connect resources to the assistant (or wait for them to be ready), then ask again. Every question that does reach the model is charged, even when it finds nothing.
Credit and plan codes
insufficient_credits
The balance cannot cover the price of the answer’s mode. Add credits, then ask again. The status is 402, and error.action_url links to the pricing page.
request_too_large_for_plan
Adding this content would pass your plan’s words-stored limit. Delete resources or change plan. See Word allowance.
Rate limit code
rate_limited
Too many requests. Wait for the number of seconds in Retry-After. See Rate limits.
Server codes
internal_error
Something failed on Lookio’s side. Retry with backoff, and contact support with the request_id if it persists.
service_unavailable
A dependency is unreachable: the engine, file storage, or a maintenance window. Retry with backoff.