Errors, Rate Limits, and Pagination

Chab uses stable error codes and machine-readable response metadata so scripts and coding agents can recover safely.

Error Envelope

{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after the provided delay.",
    "retryable": true
  },
  "request_id": "req_123"
}

error.details is present only when the error includes structured field-level information. Validation failures include it:

{
  "error": {
    "code": "validation_failed",
    "message": "One or more fields failed validation.",
    "retryable": false,
    "details": {
      "data": [
        "The data field must be an array."
      ]
    }
  },
  "request_id": "req_123"
}

Billing and free-use errors also include error.user_action, a short sentence an agent can pass on to the person, so CLI, MCP and API clients can show the next step without fetching the catalog first. Errors about credits or a missing account (signup_required, free_credits_exhausted, insufficient_credits) add a link:

  • For a guest trial: error.signup_url, plus error.next_step telling the agent to ask the person for their email address and call chab_sign_up (hosted MCP) or POST /v1/signup (guest key). The person confirms by email and the trial moves into their new account.
  • For an account: error.upgrade_url, where the signed-in person can see plans and buy credit packs.

Hosted MCP tool errors carry the same fields.

Error documentation should explain:

  • what happened
  • whether the request can be retried
  • whether credits can be charged
  • what the user should do next

Authentication and scope error codes are listed in Authentication and API Keys, including guest trial API credential lifecycle errors such as guest_credential_expired, guest_credential_revoked, and guest_credential_limit_exceeded.

Foundation Error Codes

Code HTTP Retry Chargeable What to do
validation_failed 422 No No Fix the fields listed in error.details.
malformed_request_body 400 No No Send valid JSON when using a JSON Content-Type.
idempotency_key_required 400 No No Add an Idempotency-Key header.
idempotency_key_invalid 400 No No Use 8 to 255 letters, digits, ., _, -, or :.
idempotency_key_conflict 409 No No Use a new key, or retry with the exact original body.
idempotency_request_in_progress 409 Yes No Wait for Retry-After, then retry the same key and body.
operation_result_not_ready 409 Yes No Wait for Retry-After, then fetch the result again or poll the status URL.
rate_limited 429 Yes No Slow down or wait for Retry-After.
not_found 404 No No Check the path and API version.
method_not_allowed 405 No No Use a documented method for the endpoint.
server_error 500 Yes No Retry later; reuse the same idempotency key for idempotent requests.

The full machine-readable catalog is available from GET /v1/errors.

For a mutating /v1 request, X-Chab-Idempotency-Outcome: released means the processing claim was removed and no operation was accepted by that attempt; settled means the response was durably saved for that key, including when that saved response is replayed. A 429 without this header may have been rejected before idempotency was checked, so after an uncertain network failure retry the same key and body to reconcile it. Do not switch to a new key merely because a retry returned an unmarked 429 or idempotency_request_in_progress. An unmarked server error or in-progress response can also follow a committed operation, file, billing hold, or an uncertain mail-provider submission. Keep the same key and body while reconciling; do not infer that a new key is safe.

Operation artifact, artifact download, single-cancel, and bulk-cancel endpoints reuse the standard auth, not_found, rate_limited, server_error, validation_failed, and idempotency error codes where applicable.

Code HTTP Retry Chargeable What to do
artifact_creation_failed 500 Yes No Retry later by starting a new operation with a new idempotency key.

Start Safety and Policy Errors

These checks happen before rate consumption, credit reservation, operation creation, callback-secret storage, or provider work. They are not chargeable. For an idempotent start, Chab releases the processing claim so the same key and body can be retried after remediation.

Code HTTP Retry Chargeable What to do
operation_family_degraded 503 Yes No The tool family is paused for a short time. Wait for Retry-After, check service health, then retry the same request.
operation_family_disabled 503 No No The tool is switched off. Do not retry in a loop; check service health and retry only after it is switched back on.
security_restriction_active 403 No No Review the security notice or contact authenticated support.
secret_content_detected 422 No No Remove credentials or secret-like content from the request.
secret_scan_unavailable 503 Yes No Retry the unchanged request later.
policy_acceptance_required 403 No No Ask an authorized natural user to accept the policy versions listed in the response.

See Service Health for what the two operation family codes mean and how a paused family reopens.

Connected Data Errors

Chab authorizes the project before looking up an exact connection, so missing, cross-team, cross-project, deleted, and ungranted identifiers all return not_found. The more specific errors below appear only after project ownership has been established. connected_data is the emitted_by catalog value for these errors.

Code HTTP Retry Chargeable What to do
connection_action_required 409 No No Repair, reconnect, reauthorize, or replace the connection, then reuse the idempotency key when applicable.
connection_temporarily_unavailable 503 Yes No Wait for Retry-After (always 5–300 seconds), then retry the same request and key.
connection_capability_unavailable 422 No No Choose or update a connection that exposes the exact required capability.
connection_access_removed 409 No Yes Restore access before starting new work. Already-incurred accepted work may still settle.

The first three errors happen before request acceptance and release a mutable idempotency claim. No operation, new hold, callback secret, or provider effect is created. Although action-required and capability-unavailable are not retryable without remediation, the released key may be reused after the connection changes. Protected operation reads continue to use not_found instead of revealing a retained inaccessible operation.

Billing and Credit Errors

Billing and credit errors are not retryable until the billing state, plan, operation family, or credit balance changes. They are not chargeable. When Chab returns insufficient_credits, no operation work has started and no credits have been held or charged.

Code HTTP Retry Chargeable What to do
paid_plan_required 403 No No Subscribe or upgrade before using operations that require a paid API plan.
subscription_unhealthy 402 No No Fix the billing or payment state, or contact support.
api_access_not_included 403 No No Upgrade to a plan that includes paid API access, then retry.
operation_family_not_included 403 No No Upgrade to a plan that includes the requested operation family, then retry.
spend_threshold_exceeded 402 No No Lower the request budget, raise your operation spend threshold, or move to a larger plan.
token_spending_disabled 403 No No Ask a team owner to enable spending for this API key.
token_budget_exceeded 402 No No Reduce the request cost or ask a team owner for a new allowance.
insufficient_credits 402 No No Purchase credits where available, add billing capacity, or reduce the requested operation size.
max_budget_exceeded 402 No No Raise max_credit_budget, reduce requested output size, or choose a lower-cost model alias.

Free-Mode Operation Errors

Some operations may be available through a free promotional allowance. Free operation starts never fall back to paid credits automatically. If the request cannot run on free credits, no operation work starts, no provider work is dispatched, and no paid credits are held.

free_credits_exhausted means the beneficiary has no unexpired free-credit lot capacity for the requested estimate or estimate increase. For verified free accounts, this usually means the one-off signup bonus has already been spent or is reserved by accepted work. Free promotional credits do not refresh monthly. Expired lots and already-held free credits are not counted as available for new free-funded work. Guest trial credits are one-off; a new credential does not refresh them. An active guest trial can move into a free account: at sign-up in the same browser, or through the agent with chab_sign_up or POST /v1/signup. Expired trials cannot be moved. For signed-in accounts whose free balance is used up, error.upgrade_url shows plans and credit packs, which are coming soon.

promotional_budget_exhausted means free credits are paused for a while, usually because Chab's daily free-use limit has been reached. Wait for Retry-After when provided, then retry. Work paid with your own credits is not affected. Free starts that include one-off callback fields return validation_failed before callback-secret storage, operation creation, credit holds, or provider dispatch; omit those fields and poll instead.

When a free request returns challenge_required, error.details.challenge identifies the verification provider, action, response field, and challenge expiry. Browser-trial clients render the challenge, submit the returned token using the named response field, and retry the same request. Failed or expired challenge attempts do not create an operation, reserve credits, or dispatch provider work. If the challenge provider is temporarily unavailable, Chab returns promotional_budget_exhausted with Retry-After instead of counting a failed challenge attempt.

Code HTTP Retry Chargeable What to do
free_credits_exhausted 402 No No Trial and bonus credits are one-off. Guests: create a free account (signup_url, or the agent signs the person up). Accounts: choose a plan or buy credit packs at upgrade_url.
signup_required 401 No No This guest trial cannot start new work. Create a free account (signup_url, or the agent signs the person up) or sign in.
email_verification_required 403 No No Verify the email address on your account, then retry.
upgrade_required 403 No No Upgrade before retrying the operation.
free_usage_paused 429 Yes No Wait for Retry-After when provided, then retry.
challenge_required 403 Yes No Complete the required verification challenge, then retry.
market_not_eligible 403 No No Use a paid plan or try again from an eligible market.
operation_not_available_on_free 403 No No This operation is not available to the current free credential. Check its current availability and connection requirements.
guest_credential_limit_exceeded 429 No After Retry-After for rolling issuance limits. Revoke an older credential only for an active-count limit; otherwise wait for the issuance window to recover.
promotional_budget_exhausted 503 Yes No Free use is paused for a while. Wait for Retry-After when provided, then retry. Paid credits are not affected.

Quota Errors

Billable operation starts can be limited by plan, API key, team, operation family, and usage window. Daily windows use a UTC calendar day. Monthly windows reset with the team's monthly credit cycle.

Quota errors are not chargeable and do not create an operation.

Code HTTP Retry Chargeable What to do
quota_exceeded 429 No No Wait for the day or month quota window to reset, reduce starts for that family, or move to a larger plan.
concurrency_limit_exceeded 429 Yes No Retry when an active operation completes, reduce parallel starts, or move to a larger plan.

Provider Throttling

provider_temporarily_rate_limited means Chab accepted the request path but a provider is temporarily unable to accept more work. Chab may keep an operation in running while retrying internally. If retries are exhausted, the terminal operation keeps this provider-neutral code. Retry guidance comes from the error catalog and any Retry-After or polling hints; failed terminal operations do not use warnings for retry advice. The response does not expose internal provider names.

Code HTTP Retry Chargeable What to do
provider_temporarily_rate_limited 503 Yes No For active operations, keep polling with next_check_at or Retry-After. If terminal, create a new operation later or retry the original idempotent request when safe.

Target URL Errors

URL-based operations can publish target URL errors when a target cannot be used safely or when target fetch/render work times out.

Code HTTP Retry Chargeable What to do
target_fetch_blocked 422 No No Check that the URL is public, supported, reachable, and does not redirect to a private or unsafe destination.
target_timeout 504 Yes Yes, after work starts Retry later, reduce target complexity, or use operation-specific rendering and wait options.

Source Input Errors

File and artifact based operations can publish source-state errors before work starts. Missing, cross-team, or unauthorized sources return not_found without disclosing which condition applied.

Code HTTP Retry Chargeable What to do
file_expired 410 No No Upload or select a fresh file source.
artifact_expired 410 No No Use a non-expired artifact.
artifact_deletion_in_progress 409 Yes No Respect Retry-After, then retry the artifact request.
artifact_deletion_failed 503 Yes No Contact support with the public artifact reference.
source_scan_pending 409 Yes No Wait for scanning to finish, then retry.
source_scan_failed 422 No No Upload or select a clean supported source.
source_quarantined 422 No No Choose a different source or contact support.

Provider Errors

Provider errors mean the service Chab uses to complete an operation is not available, returned an unusable response, or could not finish the request. Chab keeps these errors provider-neutral and does not expose provider task IDs, raw responses, or internal provider names.

Code HTTP Retry Chargeable What to do
provider_unavailable 503 Yes No For an active operation, keep polling. For a terminal response, retry later with the same idempotency key when the endpoint is idempotent.
provider_error 502 No No Check the request input and operation warnings before retrying.
provider_response_invalid 502 Yes No Retry later with the same idempotency key when the endpoint is idempotent.

When a new start returns provider_unavailable, no provider is ready for that tool right now. Nothing is billed, the idempotency key is released, and the response includes Retry-After. Other tools keep working.

Scrape operations also publish extraction errors. Screenshot operations publish capture errors. See Scrape Endpoints and Screenshot Endpoints for operation-specific charge and retry rules.

Code HTTP Retry Chargeable What to do
selector_not_found 422 No Yes Check the selector or capture the viewport/full page instead.
capture_timeout 504 Yes Yes Retry later, reduce capture complexity, or capture a smaller viewport.
capture_failed 502 No Yes Check the request options and target behavior before retrying.

Convert operations publish conversion-specific errors. See Convert Endpoints for supported source/output pairs and endpoint examples.

Translation operations publish translation-specific validation errors. See Translation Endpoints for supported formats, source limits, repair behavior, and charge rules.

LLM operations publish model-alias, context, structured-output, tool-call, embedding-size, and oversized-response errors. See LLM Endpoints for charge and retry rules.

Research operations publish budget, timeout, and citation-extraction errors. See Research Endpoints for mode limits, source-budget semantics, partial-result behavior, and charge rules.

Code HTTP Retry Chargeable What to do
unsupported_file_type 422 No No Use a supported source category.
unsupported_conversion_pair 422 No No Pick an output format supported by the source category.
unsupported_file_content 422 No No Use a file with extractable text.
conversion_timeout 504 Yes Yes, after work starts Retry later or reduce source complexity.
conversion_failed 502 No Yes, after work starts Check the source and output format before retrying.
unsupported_format 422 No No Use a supported translation format or artifact.
source_too_large 422 No No Reduce translation source content to 100,000 characters or less.
structure_validation_failed 422 No Yes, after work starts Split or simplify the source and retry.
placeholder_integrity_failed 422 No Yes, after work starts Check placeholders and retry with a simpler source if needed.
repair_exhausted 422 No Yes, after work starts Split the source, simplify glossary or placeholder requirements, then retry.
research_budget_exhausted 402 No No before dispatch; possible after work starts Start a new research operation with a larger max_credit_budget, smaller source_budget, or cheaper mode.
research_timeout 504 No Yes, after work starts Start a new operation later, narrow the question, reduce source_budget, or choose a faster mode.
citation_extraction_failed 502 No Yes, after work starts Start a new operation with a clearer research question or narrower source guidance.

Resource Errors

These errors describe resource behavior shared by more than one API family. They are nonretryable and nonchargeable unless the endpoint documentation says otherwise.

Code HTTP What to do
inline_content_too_large 413 Request a smaller page or reduce content below the endpoint's documented inline limit.
range_not_supported 416 Remove the Range header and request the complete resource.
resource_revision_conflict 409 Read the current resource and retry with its latest revision.
resource_state_conflict 409 Read the resource and resolve the current state that blocks the requested action.

Drive API Errors

Drive API routes are non-billable. Chab-served download bytes can still incur egress credits as documented by the endpoint.

Code HTTP Retry What to do
drive_item_action_unavailable 422 No Re-read the item and use only an action currently advertised for it.
drive_export_format_unavailable 422 No Re-read the item and choose one of its current export formats.
drive_item_too_large 413 No Download a file no larger than the endpoint's 100 MiB delivery limit.
drive_export_too_large 413 No Export a document whose produced artifact fits the 100 MiB limit.

Mail API Errors

Mail API routes are synchronous and not billable, so every error below is nonchargeable. They also use the standard validation, authentication, plan, scope, connected-data, provider, rate-limit, and idempotency errors documented elsewhere on this page.

Code HTTP Retry What to do
attachment_too_large 413 No Download or stage a smaller attachment, or remove another staged attachment.
source_too_large 422 No Use a reusable artifact no larger than 26,214,400 bytes.

not_found deliberately covers inaccessible projects, connections, messages, drafts, folders, attachments, and artifacts without confirming whether a resource exists outside the current API key's authorization.

Source Size Errors

source_too_large means a reusable input exceeds the endpoint's per-source limit. It is a nonretryable, nonchargeable 422; use a smaller source or split the content. Mail draft attachments allow at most 26,214,400 bytes per source. Other endpoint families can document a different, smaller limit.

Structured Warnings and Availability

Successful operations can include warnings in status and result responses:

{
  "code": "result_truncated",
  "message": "Results were capped at 10 rows.",
  "field": "results",
  "severity": "info"
}

Warning codes are partial_results, field_unavailable, unsupported_field, stale_data, low_confidence, duplicate_candidate, result_truncated, glossary_preferred_missed, and provider_degraded. Severity is info or warning; field is nullable.

Availability metadata uses these values: available, missing, unsupported, unavailable, withheld, stale, low_confidence, and unknown.

Idempotency

Mutating foundation requests require an Idempotency-Key header. The key must be 8 to 255 characters and may contain letters, digits, periods, underscores, hyphens, and colons.

Within the 24 hour idempotency window:

  • Idempotency keys are scoped to the authenticated team API key, HTTP method, endpoint operation, and any resource identifiers in the path. Reusing the same key on a different endpoint or path target starts a separate idempotency record.
  • On the same endpoint and path target, the same key and byte-identical request body replays the stored response.
  • On the same endpoint and path target, the same key with a different request body returns idempotency_key_conflict.
  • A second request while the first one is still processing returns idempotency_request_in_progress and Retry-After.
  • Validation failures are replayable.
  • Unexpected server errors are not cached as final responses, so a later retry can recover after the processing lease expires. If durable work already exists, the retry reattaches that work before starting anything new or remains in progress; it never creates a second charge under the same key.
  • A currently valid credential may reconcile a previously accepted operation with the same key after a plan or funding change, even when a new operation would now be denied. Revoked or claimed guest credentials do not regain access for replay; after claiming a guest trial, use the claimed account's operation history instead.
  • Claims tied to retained operations, files, pending purchases, or uncertain mail sends may be kept beyond the usual 24-hour replay window so a retry cannot silently replace their identity. Continue using the original key and body while the work is being reconciled.
  • Mutable connection-state denials release the processing row. Reuse the same key and byte-identical body only after the documented repair or retry delay.

Rate Limit Headers

Chab returns RFC 9333 rate-limit headers where possible:

RateLimit-Limit: 100
RateLimit-Remaining: 42
RateLimit-Reset: 60

For 429 responses, Chab also returns:

Retry-After: 60

The foundation limiter applies to /v1 route families, including billable starts, and may also include legacy X-RateLimit-* headers for compatibility. Billable operation starts use plan- and family-aware limits keyed by team, API key, operation family, and route profile. The RFC 9333 RateLimit-* headers are the contract.

For 429 and retryable 503 usage responses, use Retry-After as the minimum delay before retrying. For quota and spend errors, also review Credits and Billing before retrying.

Operation status and result endpoints also use Retry-After for active operations and not-ready results. See Operations.

Deprecation and Sunset Headers

When Chab deprecates a public API field or endpoint, responses can include:

Deprecation: @1794355200
Sunset: Wed, 11 Nov 2026 00:00:00 GMT
Link: <https://www.chab.ai/docs/deprecations/example>; rel="deprecation"

If both Deprecation and Sunset apply, the Link header can include both rel="deprecation" and rel="sunset" references.

Inline Result Size

Inline JSON data is limited to 1 MB after serialization unless an endpoint documents a smaller limit. Larger results are returned through artifacts or files instead of one huge response body.

Pagination

List endpoints use cursor pagination:

{
  "data": [],
  "meta": {
    "next_cursor": "cursor_abc",
    "prev_cursor": null,
    "has_more": true,
    "limit": 50,
    "request_id": "req_123"
  }
}

Default page size is 50. Maximum page size is 100 unless an endpoint documents a smaller cap.

GET /v1/operations uses this same pagination shape.