Errors
The error envelope, every error code, and how rate limiting behaves.
Errors
Every error response uses one stable envelope:
{
"error": {
"code": "tier_not_found",
"message": "Tier plan 9c1f... does not match a live plan in this organization."
}
}Branch your handling on code - it is part of the API's stability contract. message is human-readable context and may change wording over time. Every response, including errors, carries an X-Request-Id header; include it when contacting support.
Error codes
| Code | Status | Meaning |
|---|---|---|
unauthorized | 401 | Missing or malformed Authorization header. Send Authorization: Bearer fw_live_.... |
invalid_api_key | 401 | The key doesn't match any active key. |
api_key_revoked | 401 | The key exists but has been revoked. |
member_removed | 401 | A personal key whose owner is no longer a member of the organization. The key stops working the moment they leave. |
member_key_required | 403 | This endpoint (the MCP server) needs a personal key; organization keys are not accepted there. |
api_disabled | 403 | The developer API, the Apps endpoints, or the MCP server is not enabled for your organization yet. |
feature_not_available | 403 | Your organization's plan doesn't include the developer API (Pro and Agency). Existing keys stop working after a downgrade. Also returned by POST /{agents,flows,apps}/{id}/tests when the plan has no quality checker. |
insufficient_scope | 403 | The key lacks the scope this endpoint requires, or, for a personal key, the member's role doesn't allow it. |
invalid_request | 400 | Malformed JSON, a failed validation (the message names the field), a bad cursor/limit, a malformed Idempotency-Key, or Flow inputs that don't match the Flow's schema (every problem is named). A document upload over the 4.5 MB request limit answers this code with status 413. |
not_found | 404 | No Agent, Flow, App, Knowledgebase, page, end user, user group, or Portal with that ID in your organization. An unpublished Agent, Flow or App, an end user's own notebook, and anything in another organization, read the same. |
groups_disabled | 403 | User groups are not enabled for your organization yet - the /user-groups and /portals/{id}/admissions endpoints are gated while the feature rolls out. |
group_not_found | 422 | The groupId in a Portal admission, or an entry in groupIds on POST /end-users, doesn't match a user group in your organization. Nothing was written. |
plan_group | 422 / 409 | The group belongs to a plan and follows it. Adding a member answers 422: people join by holding the plan, so assign it with tierPlanIds on POST /end-users. Renaming or deleting the group answers 409: rename or archive the plan instead. Nothing was written. |
grants_unsupported | 400 | POST /end-users sent per-user grants to an organization that manages access with groups. Give a group the access and pass it in groupIds instead. Nothing was written. |
portal_scope_unsupported | 400 | A group grant named a deploymentId on an organization that manages access with groups. Group access applies at every Portal the group is admitted to: omit deploymentId and choose Portals with admissions. Nothing was written. |
deleted_identity | 409 | POST /end-users named the email of a deleted account. A deletion can't be undone through provisioning. Nothing was written. |
tier_not_found | 422 | A tierPlanId doesn't match a live plan in your organization (archived plans count as not found). |
grant_target_not_found | 422 | A grant's targetId doesn't exist in your organization. |
end_user_not_found | 422 | The endUserId in a group-member add doesn't match an end user in your organization. |
live_paid_subscription | 409 | The end user has a live paid Stripe subscription on a requested plan. Cancel it in Stripe first; nothing was written. |
service_disabled | 403 | The requested App service (Conversation or Transaction) is toggled off in the App's published API config. Republish the App with the service enabled. |
insufficient_credits | 402 | Your organization's subscription or credit allowance can't cover the run, or the document search. Nothing ran and nothing was charged. |
plan_limit | 403 | Your organization's plan has no room for another Knowledgebase. The body carries limit and used. Nothing was created; upgrade, or remove one, to continue. |
search_unavailable | 503 | The document search service could not answer a Knowledgebase search. Nothing was charged; retry shortly. Page search is unaffected: pass kinds: ["pages"] to keep going. |
export_too_large | 413 | The Knowledgebase is over the 50 MB export cap. Read its pages one by one with the pages endpoints instead. |
output_invalid | 502 | A Transaction call ran, but the App's reply wasn't a JSON object matching its output schema. The error body carries the raw reply (raw) and, for schema violations, JSON-pointer details. The run was still billed. |
forbidden_role | 403 | The personal key's member does not have the role this needs: creating and editing Agents, Flows, Apps and Knowledgebase pages needs Member or above; deleting needs Admin. Nothing was written. |
conflict | 409 | The tool changed since you last read it (the expectedUpdatedAt or If-Unmodified-Since you sent is stale): read the draft again, then retry with the new updatedAt. Also returned when an Idempotency-Key is reused with a different body, or while the first request with that key is still running. Nothing was written. |
invalid_workflow | 422 | The Flow document was refused by validation. The error body carries feedback written so a model can correct its next attempt. Nothing was written. |
invalid_model | 422 | The model id is unknown, or not available to your organization on its current billing. GET /models lists what you can use. Nothing was written. |
unpublished_dependencies | 422 | The App's adviser or a member is not published yet. The error body lists them in dependencies; publish those first, then retry. Nothing was written. |
rate_limited | 429 | Too many requests - see below. Knowledgebase export has its own, tighter limit of 3 per minute per key. |
server_error | 500 | Something went wrong on our side. Safe to retry; include the X-Request-Id if it persists. |
Validation failures on POST /end-users happen before any write - a request that fails with tier_not_found, group_not_found, plan_group, grants_unsupported, grant_target_not_found, deleted_identity, or live_paid_subscription leaves no partial account behind.
Rate limits
Each API key may make 120 requests per minute, measured over a sliding 60-second window. When you exceed it:
- The response is
429with coderate_limited. - The
Retry-Afterheader gives the number of seconds until capacity frees up.
Back off and retry after that interval. If you need sustained higher throughput, batch your work (for example, provisioning accepts plans and groups in a single call) or contact support.