Validation flow

Validation flows — what are they?

In Veriko, we define a "validation flow" as the process that takes the data of a SPEI transfer (as text or image) and searches whether Banxico issued a CEP or a transaction record with that data.
A validation always ends in a "terminal state" (see below).

Manual validation vs image-based (OCR)


  • Manual (POST /v1/validate): You must send the following data in plain text:
    • clave_rastreo — Optional if referencia_numerica is sent.
    • cuenta_beneficiaria
    • monto
    • fecha
    • emisor
    • receptor — Optional if cuenta_beneficiaria is CLABE/Card.
    • receptor_participante — Optional. 0 for an account holder (default) or 1 when the beneficiary is the receiving institution itself («Pago a Banco»).

Full guide at: Validate a SPEI transfer (manual)


  • Image-based (OCR) (POST /v1/validate-ocr): You must send an image (Base64) or a URL (https):
    • image — Optional if image_url is sent.
    • image_url — Optional if image is sent.
    • cuenta_beneficiaria, banco_emisor, banco_receptor — Optional. Only if they are not present in the image.

Full guide at: Validate a SPEI transfer from an image (OCR)

Sync vs async

By default both endpoints are synchronous: that is, the system holds the request until Banxico responds (the median is 3-5s; the recommended timeout is 30s).
If you need to close the connection sooner or set a shorter timeout, simply add ?async=1 to the URL as a GET parameter. Then:

  1. The endpoint instantly returns 202 with a validation_id, plus an ETag and meta.next_poll_after_seconds.
  2. The system enqueues and begins processing the validation.
  3. You can poll GET /v1/validations/{id} periodically to retrieve the validation's status (preferably sending If-None-Match with the last ETag seen). As long as the row does not transition, the server responds 304 Not Modified; when the status changes the ETag changes and the poll's body carries the final result.

Full detail at: Async validations.

Terminal states

Each row can resolve to one of these 7 values:

  • valid — CEP found. It is the only verdict that obtains the CEP and counts as "verified" for your finance (see CEP and Finance).
  • not_found — No CEP or transaction found with that data.
  • cep_unavailable — The transaction was found but not the CEP (typically not yet settled or there are delays in the banking system).
  • returned — The payment settled and the beneficiary institution later sent it back. The CEP, if one exists, is still delivered.
  • invalid — Banxico answered in a way the service does not recognize; not a problem with the submitted data.
  • failed — The validation stopped because the submitted data was rejected; the reason travels in error_code.
  • error — Failure of the service or of Banxico during processing; the reason travels in error_code.

Follow-up check of a valid

A valid is the verdict of the moment of the query. Banxico can report the return of the payment hours or days later; the validation then moves from valid to returned, keeps its CEP, and emits the validation.returned webhook. There are two ways to detect it:

  • On demand: POST /v1/validations/{id}/recheck queries only the payment status. It consumes no quota, accepts one query every 10 minutes per validation, and only responds during the first 72 hours.
  • Automatic: the service rechecks the valid validations of the last 72 hours at 1 hour, 6 hours, 1 day, and 3 days of age.

Full detail at: CEP.

Keeping or deleting the receipt

The receipt file is kept by default. retain_image=false on POST /v1/validate-ocr deletes it when the validation reaches a terminal status and leaves the verdict and the extracted data. To permanently delete a validation and everything it left behind, POST /v1/validations/{id}/purge/prepare and POST /v1/validations/{id}/purge/execute leave it as a tombstone: no file, no CEP, and no extracted data, with its verdict, its dates, and its amount.

Full detail at: Retention of receipts and data.

Retries

A terminal row may enter a retry cycle when its outcome (terminal state) is one of these:

  • not_found
  • cep_unavailable
  • error

The account's default policy is set with PUT /v1/users/me/retry-policy, and a single validation is adjusted with PUT /v1/validations/{id}/retry-policy. It defines enabled, max_retries, interval_seconds, and the specific outcomes from the list.

Full detail at: Retry policy.

Idempotency-Key

The Idempotency-Key header is optional. It is handled as follows:

  • New key → The request is processed normally, and the response is persisted for replays.
  • Same body with a repeated key → The endpoint replays the stored response, with its same status code and the Idempotent-Replayed: true header.
  • Different body with a repeated key → The endpoint responds 422 idempotency_key_reused.
  • Same key still processing → The endpoint responds 409 idempotency_key_in_progress.

Full detail at: Idempotency.