AI Power Ups
Contents

Concepts

Errors and retries

One envelope for every error, a fixed code-to-status table, and explicit rules for when a retry is safe and when it is billed.

The error envelope

{
  "error": {
    "code": "invalid_request",          // one of the codes below (contract)
    "message": "The execute body does not match the schema.",
    "hint"?: "Inspect the capability for its body_schema.",
    "retryable": false,                 // true only for the four retryable codes
    "violations"?: [ { "path": "/num", "message": "Expected integer to be less or equal to 25" } ],
    "requestId"?: "req-1"               // present on errors produced by the API itself
  }
}

code, retryable and the HTTP status are contract. Messages and hints are for humans and logs; do not branch on them.

Codes

codestatusretryablemeaning
invalid_request400noBody or params failed validation; `violations[]` names each field (JSON pointer path, or "" for the body). Also adapter-level rules, unpaged `more`, unknown record actions, bodies over 256 KB, non-JSON bodies.
unauthorized401noMissing, unknown or revoked key or token.
credits_exhausted402noMonthly allowance reached; wait for `balance.period_end` or upgrade.
capability_disabled403noSwitched off for this account in the dashboard.
capability_unknown404noNo such capability id.
record_unknown404noMalformed or purged `search_id` / `record_id`.
not_found404noNo such route.
session_expired410noSession older than 24 h since last use; execute again.
rate_limited429yesEither the 60/min limiter (has `x-ratelimit-*` headers) or the one-call-per-account admission (`Retry-After: 1`).
internal_error500yesUnexpected failure; carries `requestId` for support.
provider_error502yesThe source failed or answered unusably; message is prefixed with the provider name.
sharpen_no_reviewer503noNo reviewer of another model family answered.
capability_unavailable503noThe vendor key is missing in this deployment (`available: false` in the catalog).
provider_timeout504yesThe search or detail deadline was hit.
service_unavailable503yesThe service is in maintenance or recovery, or a durable record could not be confirmed; nothing was applied. Honour `Retry-After`.

Retry rules

  • Retry blindly only when retryable is true. For rate_limited wait for Retry-After (or the limiter's x-ratelimit-reset) and repeat the same request; it charged nothing.
  • Execute retries are billable. There is no idempotency key. A retry is a new call: if the first attempt completed and settled server-side (for example your client gave up before the response arrived) and the retry also completes, both are charged. If the first attempt was refused or failed, it charged 0 and only the retry is charged. While the first attempt is still running, the retry is refused by admission with 429, which prevents concurrent duplicate spend.
  • No error proves that a mutating call did nothing. A provider_timeout is produced by a server-side deadline that races with the adapter and the session write, so a timed-out more or update may still have advanced or replaced the session; and one variant of 429 rate_limited ("the request admission has expired") is returned after the provider work ran. Failed calls charge 0, but the session state after a failure is not guaranteed.
  • Consequence: do not auto-repeat execute, more or update. The common 429 variant ("Another request is already running for this account", with Retry-After: 1) is refused before any work and is safe to repeat; the API does not distinguish the two variants by code, so a generic client must treat every 429 on a mutating call as "wait, re-check, decide". Before issuing another more, re-check the session's result_count and record ids from the last response you did receive.
  • Record actions and reads are the safe case: a completed record action is cached, so a repeat is normally served at 0 credits with cached: true; a failed one charged 0. Repeating them on 429, provider failures or a lost response is reasonable, with a bounded attempt count.
If exactly-once execution matters to you, keep the search_id of every successful execute and check your own ledger before retrying; the API does not accept an Idempotency-Key today. This is a recorded product decision, see stability and versioning.

Validation details

  • Defaults are applied server-side (num, sort, units …), so an omitted optional field behaves exactly as its documented default.
  • Scalars are coerced ("5"5). This is lenient, not something to rely on; send the documented types.
  • Unknown keys are rejected: every request schema has additionalProperties: false, and the violation path names the key.
  • Rules a schema cannot express (price ranges, passenger counts, selector exclusivity) are listed per capability under "Rules the schema cannot express" and return invalid_request with a plain message and usually no violations[].