Every error has a consistent JSON shape:Documentation Index
Fetch the complete documentation index at: https://developers.flowestate.app/llms.txt
Use this file to discover all available pages before exploring further.
error.code are always consistent. Switch on code, surface message to your end user.
Codes
| HTTP | error.code | Meaning |
|---|---|---|
400 | BAD_REQUEST | Generic client error. |
400 | VALIDATION_ERROR | Request body or query failed validation. The message lists the offending fields. |
401 | UNAUTHORIZED | Bearer missing, malformed, unknown, or expired. |
403 | FORBIDDEN | Authenticated but not permitted: missing scope, plan limit reached, inactive key, or business rule violation. |
404 | NOT_FOUND | Resource does not exist or is in a different organization. |
429 | BAD_REQUEST | Rate limit exceeded. Retry after Retry-After seconds. See Rate limits. |
500 | INTERNAL_ERROR | Unexpected server failure. Safe to retry idempotently after a short backoff. |
Plan-limit errors
Plan-limitFORBIDDEN errors carry a localized message such as “You have reached the maximum number of leads for your plan.” — surface it to your end users as-is, since they’re the ones who can take action (upgrade or remove records).
These come from the billing guards on:
POST /leads— whenmaxLeadsis exceeded.POST /projects— whenmaxProjectsis exceeded.POST /webhooks/subscriptions— whenmaxWebhookEndpointsis exceeded.
Validation errors
VALIDATION_ERROR messages list every field that failed in path: reason form, joined by ; :
Idempotency and retries
5xxand429are safe to retry. Use exponential backoff capped at theRetry-Aftervalue when present.4xx(other than429) means the request itself is wrong. Don’t retry without changing it.POST /webhooks/subscriptionsis idempotent when you passexternal_id— see Create a subscription.- Other writes are not idempotent. If you retry a
POST /leadsblindly, you’ll create duplicates. Use Search a lead first to de-dupe.