POSThttps://api.veriko.mx/v1/validate

Manually validate a SPEI transfer

Audience
public
Auth
API key
Permission
validations:create
How-to guide →

Validates a SPEI transfer against the Banxico CEP from the fields you send.

The following data is required:

  • Date.
  • Amount.
  • Tracking key / Numeric reference.
  • Sending bank.
  • Receiving bank.
  • Beneficiary account, or a list of candidate accounts.

The beneficiary account (cuenta_beneficiaria) is required on this operation, unless cuentas_candidatas is sent. When both are missing, the request is rejected with 422 preflight_failed and the field error cuenta_required: the service does not look it up among the saved beneficiaries.

When it is not known which of several accounts the payment went to, cuentas_candidatas replaces cuenta_beneficiaria: from 2 accounts up to the maximum the service accepts (3 by default) in a single validation and with a single quota unit. The query goes through the candidates in the order sent and adopts the first one that matches the transfer; that account comes back in full in normalized_data.cuenta_beneficiaria and its position in candidate_match. If none matches, the response is an HTTP status 422 with the reason in code. The two forms cannot be sent together (422 cuenta_y_candidatas_excluyentes) and a list that does not comply is rejected with 422 cuentas_candidatas_invalidas, both before any quota is consumed.

The final verdict (terminal state) can be one of the following:

  • valid: The transfer CEP was found and validated.
  • not_found: The transfer CEP was NOT found.
  • cep_unavailable: Banxico recognized the transfer, but the CEP is not currently available.
  • returned: the transfer was settled and the beneficiary institution later sent it back. The CEP, when there is one, is still delivered.
  • error: Internal service error.

A not_found, cep_unavailable, or error verdict is not necessarily final: the CEP may take time to be published. In that case, automatic retries can be used by sending retry_policy in the request body, according to the retry policy.

Each call consumes plan quota, deducted when the request is accepted. If the quota is exhausted, the endpoint returns HTTP status 429 without attempting the validation.

Parameters
ParameterInTypeRequiredDescription
asyncquerystringoptional

When 1/true/yes, the validation is queued and the server responds 202 immediately with a validation_id; the client polls GET /v1/validations/{id} until the terminal state. Without the flag or with 0, the response is synchronous and returns the final result in the same POST.

Default: 0

Idempotency-Keyheaderstringoptional

Optional client-generated key (Stripe-style) that guarantees the request is processed exactly once within a 24-hour TTL. The scope is (user_id, endpoint, key). Retries with the same key and the same body return the byte-for-byte cached response with the Idempotent-Replayed: true header, without consuming rate-limit quota, without re-firing webhooks, and without creating a new validations row. Same key with a different body → 422 idempotency_key_reused. Same key with an in-flight request → 409 idempotency_key_in_progress. 5xx responses are not cached (retries with the same key are processed for real). Format: 1–255 characters, alphanumeric + _ + -.

e.g. 11111111-2222-3333-4444-555555555555
Parameters
ParameterTypeRequiredDescription
fechastring (date) (pattern, 10–10)required

Sending date of the transfer in ISO 8601 format (YYYY-MM-DD). Banxico locates the CEP with it, and it can differ from the operation day the CEP prints (banxico_result.operationDate).

e.g. 2025-03-15
montonumber (double) (> 0)required

Transfer amount in Mexican pesos (MXN), greater than zero and with up to two decimal places. Scientific notation (e.g. 1e-5) is rejected when sent as text.

e.g. 15000.5
clave_rastreostring (1–30)Required unless referencia_numerica is sent

Transfer tracking key, between 1 and 30 characters. Accepts letters, numbers, spaces, and the punctuation marks Banxico allows (such as hyphens, slashes, periods, commas, #, @, or _), but not <, >, or the backslash. It is trimmed and stripped of zero-width invisible characters before validation, so the same copy-pasted key compares equal everywhere in the platform. Required when referencia_numerica is not sent. If both are sent, the Banxico query uses only the key.

e.g. MXBA20250315001234
referencia_numericastring (pattern, 1–?)Required unless clave_rastreo is sent

Numeric transfer reference, between 1 and 7 digits. Accepts only numbers and spaces. Required when clave_rastreo is not sent. When clave_rastreo is sent, the query uses only the key, and a malformed reference is not rejected: it is ignored and a warning is left.

e.g. 1234567
emisorstring (?–255)optional

SPEI name or code of the sending bank. When it is missing or incorrect, the tracking key may provide it. If it still cannot be resolved, the response is an HTTP status 422.

e.g. BANCO NACIONAL DE MEXICO
receptorstring (?–255)optional

SPEI name / code of the receiving bank. Optional when the bank can be identified from cuenta_beneficiaria. If it cannot be resolved, the response is HTTP status 422.

e.g. BBVA MEXICO
cuenta_beneficiariastring (pattern)optional

Receiving bank account for the transfer. It is required when cuentas_candidatas is not sent: when both are missing, the response is an HTTP status 422 (with preflight_failed and the field error cuenta_required); when both are sent, a 422 with cuenta_y_candidatas_excluyentes. It can be a CLABE (18 digits), a card (16 digits) or a DiMo phone (10 digits), and the type is identified by the length of its digits. Spaces and hyphens separating groups ("0121 8000 4412 345678") are stripped automatically before the length is counted. For a DiMo phone, if the receiving bank cannot be resolved through the receptor field, through the registered beneficiaries or through the account directory, the response is an HTTP status 422 (with bank_code_unresolvable_for_phone in the body).

e.g. 012180004412345678
cuentas_candidatasarray<string> (items: 2–10, unique items)optional

Accounts among which the receiving one is, for when it is not known which. It replaces cuenta_beneficiaria: sending both responds with an HTTP status 422 (with cuenta_y_candidatas_excluyentes in the body). It accepts from 2 up to the platform's current maximum, 3 by default and never more than 10; the 422 for an excess reports the maximum in meta.max. Each account is a CLABE (18 digits), a card (16) or a DiMo phone (10), with a valid check digit and no repeats. A list that does not comply responds with a 422 with cuentas_candidatas_invalidas, and points out in field_errors the position that failed. Both errors happen before any quota is consumed. It consumes a single quota unit, however many accounts it carries. The query goes through the candidates in the order sent and adopts the first one that matches the transfer. The winner is published in full in normalized_data.cuenta_beneficiaria, and candidate_match reports its position. If none matches, the response is an HTTP status 422 with the reason in code (cuenta_unresolvable_after_probes when there is no more precise diagnosis).

e.g. ["012180004412345678","002010077777777771"]
receptor_participanteinteger (enum)optional

Whether the transfer beneficiary is the receiving institution itself («Pago a Banco» in the Banxico CEP) rather than one of its account holders. 0 for a transfer to an account holder (the default); 1 for payments whose beneficiary is the bank —credit card, loan, or services paid to the institution itself. Optional: omitted means 0.

Default: 0

e.g. 0
retry_policyobjectoptional

Automatic retry policy for this validation. If omitted, the general policy configured for the user is applied. Retries do NOT consume validation quota.

enabledbooleanoptional

true when the retry cycle is active. With false, the other fields are ignored.

e.g. true
max_retriesinteger (≥ 1)optional

Maximum number of automatic retries. Once reached, the cycle enters the exhausted terminal state. The allowed limit depends on the plan.

e.g. 3
interval_secondsinteger (≥ 300, ≤ 86400)optional

Seconds to wait between each retry (300–86400, i.e., 5 minutes to 24 hours).

e.g. 600
outcomesarray<string> (items: 1–?, unique items)optional

Outcomes that trigger a retry. By default, they are not_found, cep_unavailable, and error; the combination ["not_found", "cep_unavailable"] excludes error.

e.g. ["not_found","cep_unavailable","error"]
client_refstring (pattern, 1–64)optional

Reference of your own that is returned as sent in the validation, in the validation webhooks, and as an exact filter of GET /v1/validations. Text of 1 to 64 characters, without line breaks or emoji; it is trimmed before being stored. A value that does not comply is rejected with an HTTP status 422 (with invalid_client_ref in the body). It must not contain personal data.

e.g. orden-4812
Request
curl -X POST 'https://api.veriko.mx/v1/validate' \
  -H 'Authorization: Bearer veriko_••••' \
  -H 'Content-Type: application/json' \
  -d '{
    "fecha": "2025-03-15",
    "monto": 15000.5,
    "clave_rastreo": "MXBA20250315001234",
    "referencia_numerica": "1234567",
    "emisor": "BANCO NACIONAL DE MEXICO",
    "receptor": "BBVA MEXICO",
    "cuenta_beneficiaria": "012180004412345678"
  }'

Python example — coming soon.

JavaScript example — coming soon.

PHP example — coming soon.

Retry policy

POST /v1/validate

Validation retry policy: activation, limit, interval, and eligible outcomes.

Attempts
—
Interval
5 min – 1 h × 24
Eligible outcomes
not_found, cep_unavailable, error

This operation accepts an optional retry policy.

Response 2xxValidation
FieldTypeDescription
type*string

JSON:API resource type. Always validation.

e.g. validation
id*string (uuid)

Unique identifier of the validation (UUID v4).

e.g. 3fa85f64-5717-4562-b3fc-2c963f66afa6
attributes*object

Canonical validation data.

validation_typestring

Validation mode — direct: Manual entry of the fields; ocr: Reading of the receipt image.

e.g. direct
is_playgroundboolean

true when the result comes from a playground simulation. The simulation runs without Banxico calls, quota consumption, persistence, webhooks, or notifications.

e.g. false
statusstring

Lifecycle state — queued: Awaiting processing; processing: In progress; valid: The CEP was found and matches; not_found: Banxico cannot find the operation; cep_unavailable: Banxico recognizes the transaction but the CEP is not available; invalid: Banxico did not return a recognizable verdict; returned: the transfer was settled and later returned; failed: The validation stopped because of a problem in the data sent; error: The validation stopped because of a service failure.

e.g. valid
banxico_statusstring | nullnullable

Verdict reported by Banxico. It can be valid, not_found, cep_unavailable, invalid, returned, or error. It remains pending while no Banxico verdict exists. returned means the transfer settled and the beneficiary institution later sent it back — the CEP, when there is one, is still delivered. A valid is not final: it is the verdict of the moment of the query, and it moves to returned when Banxico reports the return in a follow-up check, which is requested with POST /v1/validations/{id}/recheck or which the service runs by itself during the first 72 hours (the validation.returned webhook is emitted). It becomes error only when the request reached Banxico and the service failed; error_code identifies the cause.

e.g. valid
processing_time_msinteger | nullnullable

Milliseconds spent processing the validation.

e.g. 1320
request_dataobject

Copy of the original request fields. fecha keeps the sending date exactly as sent, even when Banxico found the payment with another one (banxico_result._fecha).

client_refstring

Reference of your own sent in the request (client_ref), returned as sent. It only appears when the request included it. It lets you tie the validation to an order of your own, and GET /v1/validations accepts it as an exact filter. It must not contain personal data.

e.g. orden-4812
created_atstring (date-time)

Validation creation timestamp in ISO 8601 UTC.

e.g. 2025-03-15T14:22:10Z
completed_atstring | nullnullable

Date and time of completion, in ISO 8601 UTC. null while it has not finished.

e.g. 2025-03-15T14:22:11Z
enqueued_atstring | nullnullable

Queue-entry timestamp in ISO 8601 UTC.

e.g. 2026-04-30T10:15:00Z
processing_started_atstring | nullnullable

Processing start timestamp in ISO 8601 UTC.

e.g. 2026-04-30T10:15:00Z
expires_atstring | nullnullable

Expiration timestamp for queued validations in ISO 8601 UTC. After this, the validation moves to error with error_code ttl_expired.

e.g. 2026-04-30T10:15:00Z
etag_versioninteger | nullnullable

Incremental version used with If-None-Match in conditional requests.

e.g. 1
image_pathstring | nullnullable

Relative reference to the receipt, image or PDF, only when validation_type is ocr. It is not published when the file is not kept: see image_retained.

e.g. comprobantes/3fa85f64-5717-4562-b3fc-2c963f66afa6.jpg
image_retainedboolean

true when the platform keeps the receipt file; false when it does not, because the request sent retain_image=false or because the validation was purged. It only appears on validations of type ocr. With false, GET /v1/validations/{id}/image responds with an HTTP status 410 (with image_not_retained or validation_purged in the body).

e.g. true
purged_atstring (date-time)

Date and time, in ISO 8601 UTC, when the validation was purged with POST /v1/validations/{id}/purge/execute. It only appears on a purged validation, which is left as a tombstone. A tombstone keeps id, validation_type, status, banxico_status, the dates, processing_time_ms, error_code, and the amount in normalized_data.monto. It does not keep the file, the CEP, request_data, ocr_result, or banxico_result, and its derived resources respond with an HTTP status 410 (with validation_purged in the body).

e.g. 2026-10-02T09:30:00Z
ocr_resultobject | nullnullable

Fields extracted from the receipt, only when validation_type is ocr. extraction_source is cep_pdf when the receipt was the Banxico CEP as a PDF and its data was read from its text, without OCR. comprobantes_detectados is the number of receipts found in a PDF.

ocr_confidencenumber | nullnullable

OCR score from 0 to 1, only when validation_type is ocr.

e.g. 0.94
normalized_dataobject | nullnullable

Fields normalized after OCR (when validation_type is ocr), or the winning account in cuenta_beneficiaria when a direct validation sent cuentas_candidatas. A tombstone keeps only the amount here.

normalization_warningsarray | nullnullable

Normalization warnings present. They can explain an unexpected not_found result.

duplicate_ofobject

Earlier validation that had already confirmed this same transfer in the same account. It only appears when a valid, non-withdrawn validation with the same tracking key exists; it never points to a validation of another account. It is the structured form of the warning that is also added to normalization_warnings. It does not change the verdict: the validation is queried and charged all the same.

id*string (uuid)

Identifier of the earlier validation.

e.g. 3fa85f64-5717-4562-b3fc-2c963f66afa6
created_at*string (date-time)

Creation date and time of the earlier validation, in ISO 8601 UTC.

e.g. 2026-10-01T15:04:05Z
account_conflictobject

Conflict between the account sent and the one shown in the image. It only appears on ocr validations, when cuenta_beneficiaria was sent and the image shows another full account of the same length, valid and with enough confidence, or a masked account whose visible trailing digits (3 or more) are not the end of the account sent. The account sent prevails and is the one queried at Banxico: the field does not change the verdict. If the payment went to the account in the image, a not_found is the expected outcome. It carries only the last 4 digits of each account, and the conflict is also added to normalization_warnings. With a masked account, read_last4 carries the trailing digits the receipt itself shows (3 or 4), never more.

sent_last4*string

Last 4 digits of the account sent in cuenta_beneficiaria.

e.g. 5678
read_last4*string

Last 4 digits of the account shown in the image (the visible ones, 3 or 4, if it is masked).

e.g. 9012
candidate_matchobject

Which of the cuentas_candidatas sent won. It only appears when the request carried that list and one of the accounts matched the transfer. The full account is in normalized_data.cuenta_beneficiaria; this object says which position of the list it is, so it can be correlated with the integrator's own entity without comparing accounts. It does not change the verdict.

index*integer

Position (from 0) of the winning account in the cuentas_candidatas array, as sent.

e.g. 1
account_last4*string

Last 4 digits of the winning account.

e.g. 7771
is_maskedboolean | nullnullable

Whether the beneficiary account is masked in the receipt, be it a CLABE, a card or a phone number. It is included only when it is true, and only when validation_type is ocr.

banxico_resultobject | nullnullable

Data returned by the Banxico CEP. The typed properties below are the 20 declared by the official SPEI complement schema. _ocr_correction records corrected fields, their original reading (requested), the queried value (used) and confirmation (confirmed_by). status_query indicates a hypothesis confirmed by the payment status query; cep indicates that the receipt was also obtained. A status query alone does not verify a transfer. _cep_upload appears when the uploaded receipt was the CEP as a PDF and Banxico confirmed the payment. authenticated is true when its seal and original string match those of the official CEP; with false, differing_fields lists the fields that differ and normalization_warnings reports it. The verdict is still Banxico's. _payment_status is the official payment status, as Banxico gave it the last time it was asked: code (liquidado, en_proceso, cancelado, rechazado, en_proceso_devolucion, devuelto, or desconocido), label, settled, reversed, and checked_at (ISO 8601 UTC). Its absence means it could not be determined, never that the payment is settled. It is updated on every follow-up check, and with devuelto or en_proceso_devolucion the validation moves to returned. _fecha appears when Banxico did not find the payment with the date sent and did find it with another. used is the date it was found with, requested is the date first queried, and reason is why used was tried. Values of reason: clave_embedded_date: The tracking key embeds another date, at most one SPEI business day from the one sent; cutoff_18h: The key embeds no date and the receipt shows a time close to the 18:00 cutoff, so the next day was tried; dia_operacion: The key embeds the date sent, because the receipt carries the operation date, and an earlier day was tried back to the previous business day. The verdict is still Banxico's, and request_data.fecha keeps the date sent.

operationDatestring

SPEI business day that Banxico assigned to the operation, as reported by the CEP (YYYY-MM-DD), in Mexico central time. It can differ from the sending date: what is sent from 18:00 on, on a Saturday, on a Sunday, or on a non-business day operates on the next business day.

e.g. 2025-03-15
processingTimestring

Operation time as reported by the CEP (HH:MM:SS), in Mexico central time, not UTC.

e.g. 14:22:10
speiKeystring

Operation key within the SPEI system (the CEP's ClaveSPEI). Distinct from the tracking key.

trackingKeystring

SPEI tracking key of the operation — the same one sent in the validation request.

e.g. MBAN01002503151422ABCDEF
digitalSignaturestring

Digital seal of the CEP (sello) — the signature Banxico computes over the operation.

certificateNumberstring

Serial number of the digital certificate Banxico used to seal the CEP.

cadenaCdastring

Original data string of the operation (cadenaCDA): the 47 fields the institution sent to Banxico, pipe-separated, including both dates (operation and capture) and the payment type. Lets the CEP be audited without requesting it again.

senderBankstring

Sending bank of the operation, as identified by the CEP.

e.g. BBVA
senderNamestring

Name of the operation's sender, as reported by the CEP.

senderAccountTypestring

Sender's account type (e.g. CLABE or card), as reported by the CEP.

senderAccountstring

Sender's account number, as reported by the CEP — unmasked in this resource (a private lookup, owned by the validation's account).

senderRfcstring

Sender's RFC (Mexican tax ID), as reported by the CEP.

receiverBankstring

Receiving bank of the operation, as identified by the CEP.

e.g. STP
beneficiaryNamestring

Name of the operation's beneficiary, as reported by the CEP.

beneficiaryAccountTypestring

Beneficiary's account type (e.g. CLABE or card), as reported by the CEP.

beneficiaryAccountstring

Beneficiary's account number, as reported by the CEP. Unmasked in this resource (a private lookup, owned by the validation's account). Outgoing webhooks DO mask it to the last 4 digits in banxico_confirmed.beneficiaryAccount (see the webhooks guide).

beneficiaryRfcstring

Beneficiary's RFC (Mexican tax ID), as reported by the CEP.

amountnumber (float)

Operation amount Banxico confirmed via the CEP, in pesos.

e.g. 1500
ivanumber (float)

VAT (IVA) of the operation reported by the CEP, in pesos.

paymentConceptstring

Payment concept of the operation, as reported by the CEP.

error_messagestring | nullnullable

Human-readable error message when terminal.

e.g. Banxico no respondió tras tres intentos.
error_codeValidationErrorCode | null

Stable code of the terminal error, when there is one. After not_found, diagnosis may indicate not_found_identity (date, criterion or banks), not_found_account (account), not_found_amount (amount), not_found_account_and_amount (both) or not_found_account_or_amount (payment found, field not isolated). A diagnosis does not change the verdict or prove payment. Without a conclusive response, the field remains null.

batch_idinteger | nullnullable

Bulk import job identifier, when applicable.

e.g. 318
batch_positioninteger | nullnullable

Position within the job, starting at 1.

e.g. 12
retry_stateobject

Full retry cycle state. Always present; if retries are not active, enabled is false and policy fields are null. Bulk import rows always have enabled equal to false.

enabledboolean

true when the validation has retries configured, even if its cycle has already ended (terminal_state).

e.g. true
max_retriesinteger | nullnullable

Configured maximum number of retries; null when enabled is false.

e.g. 3
interval_secondsinteger | nullnullable

Interval between retries in seconds, from 300 to 86400; null when enabled is false.

e.g. 600
outcomesarray | nullnullable

Outcomes that trigger a retry: not_found, cep_unavailable, and error; null when enabled is false.

e.g. ["not_found","cep_unavailable","error"]
attempts_completedinteger

Number of retries completed so far.

e.g. 1
next_attempt_atTimestampUTC | null

Date of the next retry; null when none is scheduled.

resolved_atTimestampUTC | null

Date when a retry produced valid; null until that occurs.

exhausted_atTimestampUTC | null

Date when attempts were exhausted; null until that occurs.

cancelled_atTimestampUTC | null

Cycle cancellation date; null until that occurs.

terminal_statestring | nullnullable

Cycle state: pending, resolved, exhausted, or cancelled. It is null when the validation has no retry cycle.

e.g. pending
linksobject

Related links (JSON:API links).

selfstring

Canonical link to the validation details.

e.g. /v1/validations/3fa85f64-5717-4562-b3fc-2c963f66afa6
cep_xmlstring | nullnullable

URL of the CEP in XML format. It only appears when banxico_status is valid, or is returned with a receipt, and the validation was not purged; otherwise the links object is omitted.

e.g. /v1/validations/a1b2c3d4-e5f6-4890-abcd-ef0123456789/cep?format=xml
cep_pdfstring | nullnullable

URL of the CEP in PDF format. It only appears when banxico_status is valid, or is returned with a receipt, and the validation was not purged; otherwise the links object is omitted.

e.g. /v1/validations/a1b2c3d4-e5f6-4890-abcd-ef0123456789/cep?format=pdf
Response status codesPOST /v1/validate
StatusClassDescriptionBody
2002xxFinal validation verdict. The status field can be valid, not_found, cep_unavailable, returned, or error. When the response carries links.cep_pdf and links.cep_xml, the CEP certificate is available through GET /v1/validations/{id}/cep.Validation
2022xxValidation enqueued. Poll GET /v1/validations/{id} until one of the terminal statuses (valid, not_found, cep_unavailable, invalid, returned, failed, error). meta.next_poll_after_seconds hints the recommended first-poll interval. ValidationQueued
4004xxThe Idempotency-Key header value does not meet the allowed format (alphanumeric + _ + -, 1–255 characters). ErrorResponse
4014xxAuthentication is required or the provided credentials are invalid.ErrorResponse
4094xxA request with the same Idempotency-Key is still being processed. The client must retry after the number of seconds indicated by the Retry-After header. In-flight rows older than idempotency.in_flight_timeout_seconds (300 by default) are automatically treated as zombies and cleaned up on the next attempt. ErrorResponse
4134xxThe request body exceeds the maximum accepted size (body_too_large).ErrorResponse
4224xxRequest validation failed. Typical codes: clave_or_ref_required, required (fecha/monto), invalid_date, invalid_amount, invalid_account_format, invalid_account_length, invalid_clabe_checksum, invalid_card_luhn, invalid_bank_code (emisor/receptor not recognized), intra_bank_no_cep (sender and receiver are the same bank), invalid_field_type (a field that must be text arrived as an array or object — e.g. emisor, receptor, or referencia_numerica), invalid_receptor_participante, retry_policy_invalid, retry_pending_cap_exceeded, cuenta_y_candidatas_excluyentes (cuenta_beneficiaria and cuentas_candidatas together), cuentas_candidatas_invalidas (the list does not hold from 2 up to the current maximum of valid, distinct accounts) and cuenta_unresolvable_after_probes (no candidate matched the transfer). Also emitted when an Idempotency-Key is reused with a different body (idempotency_key_reused). When the submitted data contradicts itself, the request is rejected before Banxico is queried with preflight_failed and per-field detail in errors (clabe_receptor_mismatch and tarjeta_receptor_mismatch: the account belongs to a bank other than receptor; cuenta_invalid_luhn; clave_fecha_incoherente; clave_longitud_invalida). It is also rejected with preflight_failed when cuenta_beneficiaria is missing (cuenta_required). No preflight_failed rejection on this route consumes quota, whether the data contradicts itself, a field is malformed or the account is absent.ErrorResponse
4294xxRate limit exceededErrorResponse
5035xxBanxico was unavailable (banxico_rate_limit_exhausted) or the asynchronous validation could not be started (dispatch_failed). The request can be repeated after a few minutes.ErrorResponse
Response headers200
HeaderTypeDescription
Idempotent-ReplayedstringOnly present when the request included the Idempotency-Key header. false marks a fresh response; true marks a response reused from the idempotency cache, which remains valid for 24 hours per account, endpoint, and key.
Errors from POST /v1/validate
StatusCodeExample
400invalid_idempotency_key

Invalid Idempotency-Key format. Allowed: A-Z a-z 0-9 _ - (1-255 chars).

Envelope
meta.request_id
3c4d5e6f7a8bb8a7f6e5d4c3
401unauthorized

Invalid or missing authentication credentials.

Envelope
meta.request_id
c4d5e6f7a8b99b8a7f6e5d4c
409idempotency_key_in_progress

A request with this Idempotency-Key is still being processed.

Envelope
meta.request_id
2b3c4d5e6f7aa7f6e5d4c3b2
Response headers
  • Retry-After: integer — Seconds to wait before retrying
413body_too_large

The request body is too large.

Envelope
meta.request_id
1a2b3c4d5e6ff6e5d4c3b2a1
429rate_limit_exceeded

Rate limit exceeded. Try again in 45 seconds.

Envelope
meta.request_id
f7a8b9c0d1e22e1d0c9b8a7f
Response headers
  • Retry-After: integer — Seconds to wait before retrying. Matches the endpoint's rate-limit window (typically 60s for list endpoints, 1-5s for in-flight idempotent operations).
  • X-RateLimit-Limit: integer — Configured request cap for this bucket. It is emitted on every 429 and, on the authenticated API, also on successful responses, where it is the per-key cap of the account plan.
  • X-RateLimit-Remaining: integer — Requests remaining in the current window. Always 0 at the moment of the 429; on a successful response of the authenticated API it is what is left of the per-key cap.
  • X-RateLimit-Reset: integer — Absolute Unix epoch (seconds) when the window resets. Emitted on every 429, alongside Retry-After, and on successful responses of the authenticated API. Per-endpoint overrides exist (e.g. `rate_limited_login`).