POST https://api.veriko.mx/v1/validate-ocr

Validar una transferencia SPEI (OCR)

Audiencia
public
Autenticación
API key
Permiso
validations_ocr:create
Guía de uso →

Sube una imagen de comprobante, extrae los campos vía OCR y valida contra Banxico CEP en una sola llamada. Acepta imagen como base64 (image) o como URL remota (image_url). El campo cuenta_beneficiaria es opcional: si la imagen muestra la cuenta enmascarada, el sistema la resuelve desde las cuentas registradas en /v1/beneficiaries. Usa ?async=1 para encolar la pipeline OCR y recibir 202 inmediato; la imagen se sanea y persiste síncronamente antes del encolado. Sondea GET /v1/validations/{id} hasta el estado terminal. Acepta Idempotency-Key opcional con la misma semántica que POST /v1/validate — usa este último cuando ya conoces los campos del comprobante. Tras el veredicto, el detalle completo (incluyendo ocr_result, image_path y retry_state) se consulta vía GET /v1/validations/{id}.

Parámetros
Parámetro Ubicación Tipo Obligatorio Descripción
async query string opcional

Cuando es `1`/`true`/`yes`, encola la validación y responde 202 inmediato con `validation_id`; el cliente sondea `GET /v1/validations/{id}` hasta el estado terminal. Sin el flag o con `0`, la respuesta es síncrona y devuelve el resultado final en el mismo POST.

Predeterminado: 0

Idempotency-Key header string opcional

Llave opcional generada por el cliente (estilo Stripe) que garantiza que la petición se procese **exactamente una vez** dentro de un TTL de 24 horas. El alcance es `(user_id, endpoint, llave)`. Los reintentos con la misma llave y el mismo cuerpo devuelven la respuesta cacheada byte a byte con la cabecera `Idempotent-Replayed: true`, sin consumir cuota de rate-limit, sin re-disparar webhooks y sin crear una nueva fila en `validations`. Misma llave con cuerpo distinto → 422 `idempotency_key_reused`. Misma llave con una petición en vuelo → 409 `idempotency_key_in_progress`. Las respuestas 5xx no se cachean (los reintentos con la misma llave procesan de verdad). Formato: 1–255 caracteres, alfanuméricos + `_` + `-`.

Parámetros
Parámetro Tipo Obligatorio Descripción
image string (byte) Obligatorio si no se envía image_url

Imagen del comprobante codificada en base64 (JPEG, PNG o WebP). Tamaño máximo: 12 MB. Dimensiones máximas: 12 000 px por lado. Mutuamente excluyente con `image_url`; si ambos se envían, `image` tiene precedencia.

image_url string (uri) Obligatorio si no se envía image

URL pública HTTPS de la imagen del comprobante. El servidor descarga la imagen al recibir la petición y la persiste igual que en el flujo `image`. Tamaño y formato idénticos (JPEG, PNG o WebP, máximo 12 MB).

p. ej. https://storage.example.com/receipts/comprobante-2025-03.jpg
cuenta_beneficiaria string (patrón) opcional

Pista opcional de la cuenta beneficiaria: CLABE (18 dígitos), tarjeta (13-19 dígitos) o celular DiMo (10 dígitos), autodetectada por longitud. Se usa para desambiguar cuando el OCR extrae un número parcial o enmascarado del comprobante.

p. ej. 012180004412345678
banco_emisor string (patrón) opcional

Override opcional del banco emisor. Solo se aplica cuando el valor es un código numérico Banxico de 4 a 5 dígitos. Valores textuales se ignoran — el texto extraído por OCR es más confiable que el override del cliente.

p. ej. 40012
banco_receptor string (patrón) opcional

Override opcional del banco receptor. Solo se aplica cuando el valor es un código numérico Banxico de 4 a 5 dígitos. Valores textuales se ignoran. Útil cuando el OCR no pudo derivar el banco receptor o cuando el cliente conoce el código Banxico exacto.

p. ej. 40002
retry_policy object opcional

Política de reintentos automáticos para esta validación. Si se omite, se aplica la política configurada en `PUT /v1/users/me/retry-policy`. Los reintentos no consumen cuota de validaciones.

Petición
curl -X POST 'https://api.veriko.mx/v1/validate-ocr' \
  -H 'Authorization: Bearer mxcep_••••' \
  -H 'Content-Type: application/json' \
  -d '{
    "image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
  }'

Ejemplo en Python — próximamente.

Ejemplo en JavaScript — próximamente.

Ejemplo en PHP — próximamente.

Respuesta 2xx Validation
Campo Tipo Descripción
id * string (uuid)

Identificador único de la validación (UUID v4).

type * string

Tipo de recurso JSON:API. Siempre `validation`.

attributes * object

Datos canónicos de la validación.

validation_type string

`direct` para peticiones con parámetros textuales; `ocr` para peticiones con imagen de comprobante.

is_playground boolean

Indica si la validación fue ejecutada en modo playground. Las ejecuciones playground sí consultan Banxico pero no consumen cuota, no emiten webhooks ni notificaciones.

status string

Estado del ciclo de vida: `queued` — encolado para worker; `processing` — worker procesando; `valid` — CEP encontrado y datos coinciden; `not_found` — Banxico consultado, transferencia no encontrada; `cep_unavailable` — servicio Banxico no disponible; `invalid` — payload rechazado post-encolado; `failed` — fallo terminal; `error` — error retriable (Banxico HTTP 5xx).

banxico_status string | null anulable

Estado reportado por Banxico tras la consulta. `null` antes de consultar.

processing_time_ms integer | null anulable

Milisegundos transcurridos entre encolado y resolución terminal.

request_data object

Snapshot literal de los campos del request original.

created_at string (date-time)

Marca temporal UTC del encolado.

completed_at string | null anulable

Marca temporal UTC de resolución terminal. `null` mientras `status` esté en `queued`/`processing`.

enqueued_at string | null anulable

Marca temporal del encolado en el bus de mensajería.

processing_started_at string | null anulable

Marca temporal del primer XCLAIM del worker.

expires_at string | null anulable

Marca temporal de expiración para validaciones encoladas. Tras esta marca, el job pasa a `failed`.

etag_version integer | null anulable

Versión incremental para `If-None-Match` en consultas polling.

image_path string | null anulable

Ruta relativa de la imagen del comprobante. Solo OCR.

ocr_result object | null anulable

Resultado bruto del OCR. Solo OCR.

ocr_confidence number | null anulable

Puntaje OCR 0–1. Solo OCR; `null` para `direct`.

normalized_data object | null anulable

Campos normalizados post-OCR para consulta a Banxico.

normalization_warnings array | null anulable

Advertencias de la pipeline de normalización.

is_masked boolean | null anulable

Indica si el PAN viene enmascarado en el comprobante OCR.

banxico_result object | null anulable

Payload literal devuelto por Banxico CEP.

error_message string | null anulable

Mensaje legible del error terminal cuando aplique.

error_code string | null anulable

Código machine-readable del error terminal.

batch_id integer | null anulable

Identificador del lote de import masivo si aplica.

batch_position integer | null anulable

Posición dentro del batch (1-indexed).

retry_state object

Estado completo del ciclo de reintentos. Siempre presente; si la validación no tiene reintentos activos, `enabled=false` y los campos de política son `null`. Las validaciones de import masivo siempre tienen `enabled=false`.

enabled boolean

Indica si el ciclo de reintentos está activo para esta validación.

max_retries integer | null anulable

Número máximo de reintentos configurado. El tope superior depende del plan (`retry_max_retries`) o del default global `max_retries_cap` (típicamente 5–10). `null` si `enabled=false`.

interval_seconds integer | null anulable

Intervalo entre reintentos en segundos (300–86400). `null` si `enabled=false`.

outcomes array | null anulable

Resultados de validación que habilitan un reintento (`not_found`, `cep_unavailable`, `error`). `null` si `enabled=false`.

attempts_completed integer

Número de reintentos completados hasta el momento.

next_attempt_at union

Timestamp del próximo reintento programado. `null` si el ciclo está en estado terminal o si no hay reintentos activos.

resolved_at union

Timestamp cuando un reintento resolvió la validación a `valid`. `null` si el ciclo no ha terminado por resolución.

exhausted_at union

Timestamp cuando se agotaron los reintentos sin resolución. `null` si el ciclo no ha terminado por agotamiento.

cancelled_at union

Timestamp cuando el ciclo fue cancelado explícitamente. `null` si no fue cancelado.

terminal_state string | null anulable

Estado terminal del ciclo: `pending` — activo, sin resultado final aún; `resolved` — un reintento obtuvo `valid`; `exhausted` — se agotaron los intentos; `cancelled` — cancelado por el usuario.

links object

Enlaces relacionados (JSON:API `links`).

self string

URL de la validación.

cep_xml string | null anulable

URL del CEP en formato XML. `null` si `status` no es `valid`.

cep_pdf string | null anulable

URL del CEP en formato PDF. `null` si `status` no es `valid`.

Códigos de respuesta POST /v1/validate-ocr
Código Clase Descripción Cuerpo
200 2xx Veredicto de la validación con los campos extraídos por OCR. El campo `ocr_confidence` (0–1) indica la confianza de la extracción. Sin cuerpo
202 2xx Validación encolada. El cliente debe sondear `GET /v1/validations/{id}` hasta uno de los estados terminales (`valid`, `not_found`, `cep_unavailable`, `invalid`, `failed`, `error`). `meta.next_poll_after_seconds` indica el intervalo recomendado para el primer poll. ValidationQueued
400 4xx El valor de la cabecera `Idempotency-Key` no cumple el formato permitido (alfanumérico + `_` + `-`, 1–255 caracteres). ErrorResponse
401 4xx Se requiere autenticación o las credenciales son inválidas ErrorResponse
409 4xx Una petición con la misma `Idempotency-Key` aún se está procesando. El cliente debe reintentar después de los segundos que indica la cabecera `Retry-After`. Las filas en vuelo más antiguas que `idempotency.in_flight_timeout_seconds` (300 por defecto) se tratan automáticamente como zombies y se limpian en el siguiente intento. ErrorResponse
422 4xx Falló la validación de la petición. Códigos de body: `image_or_image_url_required`, `invalid_image`, `invalid_image_format`, `image_too_large`, `invalid_url`, `invalid_url_scheme`, `url_ssrf_blocked`, `invalid_clabe_checksum`. Códigos de sanitización post-decode (path sync y async pre-dispatch): `image_too_small`, `image_mime_mismatch`, `image_dimensions_too_large`, `image_decompression_bomb`, `image_polyglot_detected`, `image_url_unreachable`, `image_url_too_large`, `image_url_too_many_redirects`. En modo async la falla genérica de sanitización se reporta como `image_invalid`. Reusó `Idempotency-Key` con cuerpo distinto → `idempotency_key_reused`. ErrorResponse
429 4xx Límite de tasa excedido ErrorResponse
503 5xx OCR no configurado en este deploy (`ocr_not_configured`), falla del upstream Banxico (`banxico_rate_limit_exhausted`), o fallo de despacho async (Redis caído → `dispatch_failed`). Espera unos minutos y reintenta. ErrorResponse
Cabeceras de respuesta 200
Cabecera Tipo Descripción
Idempotent-Replayed string Presente solo cuando el cliente envió `Idempotency-Key`. `false` para respuestas frescas; `true` cuando es replay del caché.
Errores de POST /v1/validate-ocr
Código Clave Detalle
400 invalid_idempotency_key

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

Envelope
meta.request_id
3c4d5e6f7a8b
401 unauthorized

Invalid or missing authentication credentials.

Envelope
meta.request_id
c4d5e6f7a8b9
409 idempotency_key_in_progress

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

Envelope
meta.request_id
2b3c4d5e6f7a
Cabeceras de respuesta
  • Retry-After : integer — Segundos a esperar antes de reintentar
429 rate_limit_exceeded

Rate limit exceeded. Try again in 45 seconds.

Envelope
meta.request_id
f7a8b9c0d1e2
Cabeceras de respuesta
  • Retry-After : integer — Segundos a esperar antes de reintentar. Coincide con la ventana de rate-limit del endpoint (típicamente 60s para listas, 1-5s para operaciones idempotentes en vuelo).
  • X-RateLimit-Limit : integer — Límite de solicitudes configurado para este bucket (emitido sólo en 429).
  • X-RateLimit-Remaining : integer — Solicitudes restantes en la ventana actual — siempre 0 en el momento del 429 (emitido sólo en 429).
  • X-RateLimit-Reset : integer — Unix epoch absoluto (segundos) en que se reinicia la ventana. Emitido sólo en 429, junto con Retry-After. Puede existir sobreescritura por endpoint (p. ej. `rate_limited_login`).

Política de reintentos

POST /v1/validate-ocr

Política de reintentos automáticos. Configura cuándo y cuántas veces el sistema reintenta una validación cuyo resultado es elegible (`not_found`, `cep_unavailable` o `error` por defecto).

Intentos
Intervalo
5 min – 1 h × 24
Resultados elegibles
not_found , cep_unavailable , error

Esta operación admite una política de reintentos opcional.