Appearance
Errors
Every error has a stable code, a message and a hint written for the agent: what to do next.
REST answers with the HTTP status of the code and this body (details only when there are details):
json
{ "error": { "code": "SCOPE_MISSING", "message": "This key lacks scope 'send'.", "hint": "…", "details": { "scope": "send" } } }An MCP tool answers with isError: true and one text block, CODE: message hint. A missing or revoked key and a rate limit are refused before any tool runs: HTTP 401 or 429 with a JSON-RPC error whose message is the same text.
| Code | HTTP | Message | Hint |
|---|---|---|---|
UNAUTHENTICATED | 401 | Missing or invalid API key. | Pass the project key as Authorization: Bearer brk_live_…. Run npx brynth init to get one. |
KEY_REVOKED | 401 | This API key has been revoked. | This key was revoked. Ask the project owner for a new key. |
SCOPE_MISSING | 403 | This key lacks a required scope. | Create a key with that scope (POST /v1/keys, needs admin). |
VALIDATION_FAILED | 400 | The request is invalid. | Fix the listed fields and retry. |
NOT_FOUND | 404 | Not found. | |
SLUG_TAKEN | 409 | This slug is already taken. | Choose another slug or omit it to get one derived from the name. |
LOGIN_NOT_VERIFIED | 409 | The sign-in link has not been confirmed yet. | The user has not clicked the email link yet. Keep polling /v1/auth/poll. |
LOGIN_EXPIRED | 410 | This sign-in has expired. | Start again with /v1/auth/start. |
LOGIN_CONSUMED | 409 | This sign-in was already used. | This login was already used to create a project. Start a new login. |
PROJECT_LIMIT_REACHED | 409 | This account already has the maximum number of projects. | Reuse an existing project: run npx brynth status or connect it with BRYNTH_KEY. Contact support to raise the limit. |
LAST_ADMIN_KEY | 409 | This is the last active admin key of the project. | Create another admin key before revoking this one. |
RATE_LIMITED | 429 | Too many requests. | Wait retry_after seconds. |
EMAIL_DELIVERY_FAILED | 502 | The sign-in email could not be sent. | Retry in a minute. If it keeps failing, contact support. |
INGRESS_SIGNATURE_INVALID | 401 | The webhook signature is missing or invalid. | Signature missing or wrong. Check the source secret set with source_add. |
PAYLOAD_TOO_LARGE | 413 | The request body is too large. | Webhook bodies are limited to 5 MB. |
SOURCE_NAME_TAKEN | 409 | A source with this name already exists in the project. | Choose another name. |
EMAIL_SOURCE_EXISTS | 409 | The project already has an email source. | The project already has its email address; see source_list. |
EVENT_NOT_CLAIMABLE | 409 | The event cannot be claimed or changed in its current state. | The event is already claimed or closed. Call inbox_list for pending events. |
EVENT_ROUTED | 409 | The event is delivered by a routing rule. | This event is delivered by callback, not by pull. |
LEASE_NOT_HELD | 409 | Another key holds the lease on this event. | Another key holds this event. Claim a pending event instead. |
LEASE_EXPIRED | 409 | The lease on this event has expired. | Your lease expired and the event went back to the queue. Claim it again with inbox_claim. |
TOO_MANY_WAITS | 429 | Too many concurrent waits. | Too many concurrent inbox_wait (10 per key, 25 per project). Wait for one to return. |
CALLBACK_URL_REJECTED | 400 | The callback URL is not allowed. | Use an https URL on a public address. |
KEY_LIMIT_REACHED | 409 | The project has reached its limit of active keys. | The project has 20 active keys. Revoke one first. |
CHANNEL_NOT_VERIFIED | 409 | An approver is not an active channel of this project. | An approver is not an active channel. Call channel_list, or channel_add("telegram") and ask the user to complete verification. |
CHANNEL_ADDRESS_REJECTED | 400 | This address cannot be used as a channel. | Use a valid email outside the Brynth inbound domain. |
CHANNEL_EXISTS | 409 | This address is already a channel of the project. | This address is already a channel; see channel_list. |
CHANNEL_OWNER_PROTECTED | 409 | The owner's channel cannot be removed. | The owner's channel cannot be removed. |
CHANNEL_KIND_UNAVAILABLE | 400 | This channel kind is not available on this server. | This channel kind is not configured on this server. Use email. |
POLICY_INVALID | 400 | The policy document is invalid. | Fix the field at path and call policy_set again. |
TOO_MANY_PENDING_REQUESTS | 429 | The project has too many pending requests. | 50 requests are pending. Wait for answers or let old ones expire. |
CALLBACK_SECRET_MISSING | 409 | The project has no request callback secret. | Create the project's callback secret with POST /v1/request-callback-secret, or omit callback_url. |
DETAILS_REQUIRED | 400 | A high-risk request needs details. | Put in details what you will do, why, what it touches (resources, people, amounts) and whether it can be undone. If the action is not high risk, lower risk. |
QUOTA_EXCEEDED | 409 | The project disk is full. | The project disk is full (limit, used). Delete keys or files you no longer need, then retry. |
POLICY_DENIED | 403 | A project policy denies this action. | A project policy denies this action (rule). Ask the user to change the policy with policy_set if it should be allowed. |
APPROVAL_NOT_APPLICABLE | 409 | The approval does not apply to this call. | The approval does not match this call: it must be an approved file_url request for the same file and expires_in, not yet used, redeemed with the API key that asked for it within 24 hours of the decision. Call file_url without approval to ask again. |
UPLOAD_INCOMPLETE | 409 | The upload is incomplete. | The upload is missing or its size differs from the declared one. PUT the file to upload_url with upload_headers, then call file_put with complete again. |
UPLOAD_LIMIT | 429 | Too many open uploads at this path. | 3 presigned uploads are already open at this path. Finish one with complete, or wait for its upload_url to expire (15 minutes after upload), then call file_put with upload again. |
PATH_RESERVED | 400 | This key or path is reserved. | Keys under state/ are managed by state_save; paths under evt_…/ are inbound attachments and read-only. |
SEND_LIMIT_REACHED | 429 | The project reached its sending limit. | The project reached its sending limit (limit, window). Retry after retry_after, or send to fewer recipients. |
SEND_BLOCKED | 403 | Sending is blocked for this project. | Sending is blocked for this project after too many bounces or complaints, or by the operator. Tell the user; only Brynth support can unblock it. |
EMAIL_SOURCE_REQUIRED | 409 | The project has no active email source. | The project has no active email address, so replies would be lost. Add one with source_add (type email), then retry. |
INTERNAL | 500 | Internal error. | Retry later. Quote the X-Request-Id header if it keeps failing. |