← Back to schema index

Validation

JSON:API SPEI validation resource returned by the individual lookup and synchronous validation.

ExtendsJsonApiResourceBase

Properties

FieldTypeDescription
type*stringJSON:API resource type. Always `validation`.
id*string (uuid)Unique identifier of the validation (UUID v4).
attributes*objectCanonical validation data.
validation_typestringValidation mode — `direct`: Manual entry of the fields; `ocr`: Reading of the receipt image.
is_playgroundboolean`true` when the result comes from a playground simulation. The simulation runs without Banxico calls, quota consumption, persistence, webhooks, or notifications.
statusstringLifecycle 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_statusstring | nullVerdict 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_msinteger | nullMilliseconds spent processing the validation.
request_dataobjectCopy 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_refstringReference 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_atstring (date-time)Validation creation timestamp in ISO 8601 UTC.
completed_atstring | nullDate and time of completion, in ISO 8601 UTC. `null` while it has not finished.
enqueued_atstring | nullQueue-entry timestamp in ISO 8601 UTC.
processing_started_atstring | nullProcessing start timestamp in ISO 8601 UTC.
expires_atstring | nullExpiration timestamp for queued validations in ISO 8601 UTC. After this, the validation moves to `error` with `error_code` `ttl_expired`.
etag_versioninteger | nullIncremental version used with `If-None-Match` in conditional requests.
image_pathstring | nullRelative 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_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).
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).
ocr_resultobject | nullFields 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 | nullOCR score from 0 to 1, only when `validation_type` is `ocr`.
normalized_dataobject | nullFields 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 | nullNormalization warnings present. They can explain an unexpected `not_found` result.
duplicate_ofobjectEarlier 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_conflictobjectConflict 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*stringLast 4 digits of the account sent in `cuenta_beneficiaria`.
read_last4*stringLast 4 digits of the account shown in the image (the visible ones, 3 or 4, if it is masked).
candidate_matchobjectWhich 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*integerPosition (from 0) of the winning account in the `cuentas_candidatas` array, as sent.
account_last4*stringLast 4 digits of the winning account.
is_maskedboolean | nullWhether 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 | nullData 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.
operationDatestringSPEI 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.
processingTimestringOperation time as reported by the CEP (`HH:MM:SS`), in Mexico central time, not UTC.
speiKeystringOperation key within the SPEI system (the CEP's `ClaveSPEI`). Distinct from the tracking key.
trackingKeystringSPEI tracking key of the operation — the same one sent in the validation request.
digitalSignaturestringDigital seal of the CEP (`sello`) — the signature Banxico computes over the operation.
certificateNumberstringSerial number of the digital certificate Banxico used to seal the CEP.
cadenaCdastringOriginal 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.
senderBankstringSending bank of the operation, as identified by the CEP.
senderNamestringName of the operation's sender, as reported by the CEP.
senderAccountTypestringSender's account type (e.g. CLABE or card), as reported by the CEP.
senderAccountstringSender's account number, as reported by the CEP — unmasked in this resource (a private lookup, owned by the validation's account).
senderRfcstringSender's RFC (Mexican tax ID), as reported by the CEP.
receiverBankstringReceiving bank of the operation, as identified by the CEP.
beneficiaryNamestringName of the operation's beneficiary, as reported by the CEP.
beneficiaryAccountTypestringBeneficiary's account type (e.g. CLABE or card), as reported by the CEP.
beneficiaryAccountstringBeneficiary'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).
beneficiaryRfcstringBeneficiary's RFC (Mexican tax ID), as reported by the CEP.
amountnumber (float)Operation amount Banxico confirmed via the CEP, in pesos.
ivanumber (float)VAT (IVA) of the operation reported by the CEP, in pesos.
paymentConceptstringPayment concept of the operation, as reported by the CEP.
error_messagestring | nullHuman-readable error message when terminal.
error_codeValidationErrorCode | nullStable 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 | nullBulk import job identifier, when applicable.
batch_positioninteger | nullPosition within the job, starting at 1.
retry_stateobjectFull 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`).
max_retriesinteger | nullConfigured maximum number of retries; `null` when `enabled` is `false`.
interval_secondsinteger | nullInterval between retries in seconds, from `300` to `86400`; `null` when `enabled` is `false`.
outcomesarray | nullOutcomes that trigger a retry: `not_found`, `cep_unavailable`, and `error`; `null` when `enabled` is `false`.
attempts_completedintegerNumber of retries completed so far.
next_attempt_atTimestampUTC | nullDate of the next retry; `null` when none is scheduled.
resolved_atTimestampUTC | nullDate when a retry produced `valid`; `null` until that occurs.
exhausted_atTimestampUTC | nullDate when attempts were exhausted; `null` until that occurs.
cancelled_atTimestampUTC | nullCycle cancellation date; `null` until that occurs.
terminal_statestring | nullCycle state: `pending`, `resolved`, `exhausted`, or `cancelled`. It is `null` when the validation has no retry cycle.
linksobjectRelated links (JSON:API `links`).
selfstringCanonical link to the validation details.
cep_xmlstring | nullURL 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_pdfstring | nullURL 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/validate
  • POST /v1/validate-ocr
  • GET /v1/validations/{id}
  • POST /v1/validations/{id}/recheck