Validation
JSON:API SPEI validation resource returned by the individual lookup and synchronous validation.
ExtendsJsonApiResourceBase
Properties
| Field | Type | Description |
|---|---|---|
type* | string | JSON:API resource type. Always `validation`. |
id* | string (uuid) | Unique identifier of the validation (UUID v4). |
attributes* | object | Canonical validation data. |
validation_type | string | Validation mode — `direct`: Manual entry of the fields; `ocr`: Reading of the receipt image. |
is_playground | boolean | `true` when the result comes from a playground simulation. The simulation runs without Banxico calls, quota consumption, persistence, webhooks, or notifications. |
status | string | 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. |
banxico_status | string | null | 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. |
processing_time_ms | integer | null | Milliseconds spent processing the validation. |
request_data | object | 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_ref | string | 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. |
created_at | string (date-time) | Validation creation timestamp in ISO 8601 UTC. |
completed_at | string | null | Date and time of completion, in ISO 8601 UTC. `null` while it has not finished. |
enqueued_at | string | null | Queue-entry timestamp in ISO 8601 UTC. |
processing_started_at | string | null | Processing start timestamp in ISO 8601 UTC. |
expires_at | string | null | Expiration timestamp for queued validations in ISO 8601 UTC. After this, the validation moves to `error` with `error_code` `ttl_expired`. |
etag_version | integer | null | Incremental version used with `If-None-Match` in conditional requests. |
image_path | string | null | 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`. |
image_retained | boolean | `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). |
purged_at | string (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). |
ocr_result | object | null | 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_confidence | number | null | OCR score from 0 to 1, only when `validation_type` is `ocr`. |
normalized_data | object | null | 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_warnings | array | null | Normalization warnings present. They can explain an unexpected `not_found` result. |
duplicate_of | object | 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. |
created_at* | string (date-time) | Creation date and time of the earlier validation, in ISO 8601 UTC. |
account_conflict | object | 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`. |
read_last4* | string | Last 4 digits of the account shown in the image (the visible ones, 3 or 4, if it is masked). |
candidate_match | object | 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. |
account_last4* | string | Last 4 digits of the winning account. |
is_masked | boolean | null | 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_result | object | null | 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. |
operationDate | string | 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. |
processingTime | string | Operation time as reported by the CEP (`HH:MM:SS`), in Mexico central time, not UTC. |
speiKey | string | Operation key within the SPEI system (the CEP's `ClaveSPEI`). Distinct from the tracking key. |
trackingKey | string | SPEI tracking key of the operation — the same one sent in the validation request. |
digitalSignature | string | Digital seal of the CEP (`sello`) — the signature Banxico computes over the operation. |
certificateNumber | string | Serial number of the digital certificate Banxico used to seal the CEP. |
cadenaCda | string | 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. |
senderBank | string | Sending bank of the operation, as identified by the CEP. |
senderName | string | Name of the operation's sender, as reported by the CEP. |
senderAccountType | string | Sender's account type (e.g. CLABE or card), as reported by the CEP. |
senderAccount | string | Sender's account number, as reported by the CEP — unmasked in this resource (a private lookup, owned by the validation's account). |
senderRfc | string | Sender's RFC (Mexican tax ID), as reported by the CEP. |
receiverBank | string | Receiving bank of the operation, as identified by the CEP. |
beneficiaryName | string | Name of the operation's beneficiary, as reported by the CEP. |
beneficiaryAccountType | string | Beneficiary's account type (e.g. CLABE or card), as reported by the CEP. |
beneficiaryAccount | string | 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). |
beneficiaryRfc | string | Beneficiary's RFC (Mexican tax ID), as reported by the CEP. |
amount | number (float) | Operation amount Banxico confirmed via the CEP, in pesos. |
iva | number (float) | VAT (IVA) of the operation reported by the CEP, in pesos. |
paymentConcept | string | Payment concept of the operation, as reported by the CEP. |
error_message | string | null | Human-readable error message when terminal. |
error_code | ValidationErrorCode | 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_id | integer | null | Bulk import job identifier, when applicable. |
batch_position | integer | null | Position within the job, starting at 1. |
retry_state | object | 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`. |
enabled | boolean | `true` when the validation has retries configured, even if its cycle has already ended (`terminal_state`). |
max_retries | integer | null | Configured maximum number of retries; `null` when `enabled` is `false`. |
interval_seconds | integer | null | Interval between retries in seconds, from `300` to `86400`; `null` when `enabled` is `false`. |
outcomes | array | null | Outcomes that trigger a retry: `not_found`, `cep_unavailable`, and `error`; `null` when `enabled` is `false`. |
attempts_completed | integer | Number of retries completed so far. |
next_attempt_at | TimestampUTC | null | Date of the next retry; `null` when none is scheduled. |
resolved_at | TimestampUTC | null | Date when a retry produced `valid`; `null` until that occurs. |
exhausted_at | TimestampUTC | null | Date when attempts were exhausted; `null` until that occurs. |
cancelled_at | TimestampUTC | null | Cycle cancellation date; `null` until that occurs. |
terminal_state | string | null | Cycle state: `pending`, `resolved`, `exhausted`, or `cancelled`. It is `null` when the validation has no retry cycle. |
links | object | Related links (JSON:API `links`). |
self | string | Canonical link to the validation details. |
cep_xml | string | null | 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. |
cep_pdf | string | null | 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. |
Used in operations
POST /v1/validatePOST /v1/validate-ocrGET /v1/validations/{id}POST /v1/validations/{id}/recheck