A validation queries the CEP at Banxico, and that wait belongs to an external service. The ?async=1 parameter decouples the two: the request enqueues the work and responds immediately, instead of holding the connection until Banxico answers.
POST /v1/validate?async=1
POST /v1/validate-ocr?async=1The response is 202 with the validation identifier, and no verdict yet:
{
"data": {
"type": "validation",
"id": "9f3c2a1b-4d5e-6f70-8192-a3b4c5d6e7f8",
"attributes": { "status": "queued", "expires_at": "2026-08-21T15:12:44Z" }
}
}The verdict is obtained by polling GET /v1/validations/{id} until the state is terminal.
States
| state | terminal | meaning |
|---|---|---|
queued | No | Enqueued, not processed yet |
processing | No | Under way against Banxico |
valid | Yes | The CEP exists and matches the submitted data |
not_found | Yes | Banxico holds no CEP matching that data |
cep_unavailable | Yes | Banxico could not answer on this attempt |
invalid | Yes | The submitted data does not form a queryable transfer |
failed | Yes | Processing was exhausted without a result |
error | Yes | Failure during processing; the reason travels in error_code |
Polling cadence
The poll response states when to ask again, so the client does not have to pick an interval:
| signal | content |
|---|---|
Retry-After | Suggested seconds until the next poll |
meta.next_poll_after_seconds | The same value, in the body, for clients that do not read headers |
ETag | Signature of the current state, shaped W/"{version}-{state}" |
The suggestion starts at 2 seconds and widens to 5 from the tenth attempt onwards. A terminal state stops emitting Retry-After: that is the signal to stop polling.
Conditional polling
The ETag changes on every state transition. Sending it back as If-None-Match lets a poll with no news resolve as a 304 with no body:
GET /v1/validations/9f3c2a1b-…
If-None-Match: W/"3-processing"A 304 means the state has not changed since the previous query. It is the cheap way to poll: the response carries no resource.
Expiry
An enqueued validation carries an expires_at. Past that deadline without reaching a terminal state, the validation is closed as expired and stops being processed. The value comes in the 202 response and allows capping the client's polling cycle.
Choosing between synchronous and asynchronous
Without ?async=1 the request returns the verdict in the same response, at the cost of holding the connection while Banxico answers. The asynchronous path fits high volumes, clients that cannot keep long connections open, or results processed later through webhooks.