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

Validar una transferencia SPEI (directa)

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

Valida una transferencia SPEI contra el CEP de Banxico usando los campos proporcionados: fecha, monto, clave de rastreo, referencia numérica, banco emisor, banco receptor y cuenta beneficiaria. Devuelve un veredicto con estado valid, not_found, cep_unavailable o error. Usa ?async=1 para encolar la operación y recibir 202 inmediato; sondea GET /v1/validations/{id} hasta el estado terminal. Diferencia clave con POST /v1/validate-ocr: este endpoint recibe campos explícitos; el OCR acepta imagen de comprobante e infiere los campos automáticamente. Acepta Idempotency-Key opcional para evitar duplicados en reintentos de red. Si se reutiliza la clave con un body distinto el server responde 422 idempotency_key_reused; si la operación previa sigue en curso responde 409 idempotency_key_in_progress. Las respuestas con status 5xx no se cachean. Tras un not_found / cep_unavailable / error puedes activar reintentos automáticos con PUT /v1/validations/{id}/retry-policy o pasar retry_policy directamente en el body. El historial completo se consulta vía GET /v1/validations.

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
fecha string (date) (patrón, 10–10) obligatorio

Fecha de la transferencia en formato ISO 8601 (YYYY-MM-DD). Debe coincidir con la fecha registrada en el CEP; diferencias de ±1 día pueden producir un resultado `not_found`.

p. ej. 2025-03-15
monto number (double) (> 0) obligatorio

Importe de la transferencia en pesos mexicanos (MXN), mayor que cero y con hasta dos decimales. Debe coincidir exactamente con el monto registrado en el CEP; cualquier diferencia puede producir `not_found`.

p. ej. 15000.5
clave_rastreo string (1–30) Obligatorio si no se envía referencia_numerica

Clave de rastreo SPEI generada por el banco emisor: cadena alfanumérica de 18 a 30 caracteres. Requerida si `referencia_numerica` está ausente; pueden enviarse ambas simultáneamente para mayor precisión de búsqueda.

p. ej. MXBA20250315001234
referencia_numerica string (patrón, 1–7) Obligatorio si no se envía clave_rastreo

Referencia numérica de la transferencia: entre 1 y 7 dígitos. Requerida si `clave_rastreo` está ausente; ambas pueden enviarse simultáneamente.

p. ej. 1234567
emisor string (?–255) opcional

Nombre del banco emisor. Texto libre; el sistema lo normaliza contra el catálogo Banxico. Ignorado para CLABE y tarjeta, ya que el banco emisor se deriva del prefijo. Para celular/DiMo (10 dígitos), su presencia mejora la resolución del banco receptor.

p. ej. BANCO NACIONAL DE MEXICO
receptor string (?–255) opcional

Nombre del banco receptor. Para CLABE (18 dígitos) y tarjeta (13-19 dígitos) el banco se deriva automáticamente del prefijo/BIN y este campo se ignora. Solo es relevante cuando `cuenta_beneficiaria` es de 10 dígitos (celular/DiMo) y no puede resolverse por otros medios.

p. ej. BBVA MEXICO
cuenta_beneficiaria string (patrón) opcional

Cuenta destino del SPEI: CLABE de 18 dígitos, número de tarjeta de 13 a 19 dígitos, o número de celular DiMo de 10 dígitos. El tipo se autodetecta por longitud y se valida el checksum correspondiente (CLABE: dígito verificador estándar; tarjeta: Luhn). Para celular, el banco receptor se resuelve en orden: whitelist del usuario → catálogo global; si no se encuentra, el resultado es `error` con código `bank_code_unresolvable_for_phone`.

p. ej. 012180004412345678
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' \
  -H 'Authorization: Bearer mxcep_••••' \
  -H 'Content-Type: application/json' \
  -d '{
    "fecha": "2025-03-15",
    "monto": 15000.5,
    "clave_rastreo": "MXBA20250315001234",
    "referencia_numerica": "1234567",
    "emisor": "BANCO NACIONAL DE MEXICO",
    "receptor": "BBVA MEXICO",
    "cuenta_beneficiaria": "012180004412345678"
  }'

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
Código Clase Descripción Cuerpo
200 2xx Veredicto síncrono de la validación. El campo `status` toma uno de: `valid` (transferencia confirmada en el CEP), `not_found` (no existe en el CEP para los datos proporcionados), `cep_unavailable` (Banxico no respondió a tiempo) o `error` (fallo inesperado en el pipeline). Cuando `has_cep: true` el certificado CEP está disponible vía `GET /v1/validations/{id}/cep`. 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 típicos: `clave_or_ref_required`, `required` (fecha/monto), `invalid_date`, `invalid_amount`, `invalid_account_format`, `invalid_account_length`, `invalid_clabe_checksum`, `invalid_card_luhn`, `retry_policy_invalid`, `retry_pending_cap_exceeded`. También se emite cuando se reutiliza `Idempotency-Key` con un cuerpo distinto (`idempotency_key_reused`). ErrorResponse
429 4xx Límite de tasa excedido ErrorResponse
503 5xx Falla del upstream Banxico O fallo de despacho async (Redis caído → `dispatch_failed`). Se devuelve `banxico_rate_limit_exhausted` cuando Banxico aplica throttling y la plataforma agotó sus reintentos automáticos. Espera unos minutos y reintenta. ErrorResponse
Cabeceras de respuesta 200
Cabecera Tipo Descripción
Idempotent-Replayed string Presente solo cuando el cliente envió la cabecera `Idempotency-Key`. `false` para respuestas frescas; `true` cuando la respuesta es replay del caché de idempotencia (TTL 24h por usuario+endpoint+key).
Errores de POST /v1/validate
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

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.