API
Solicita acceso →
Más / Cambios
Cambios

Vivo y mantenido

Cada versión de la API queda registrada. Deriva de /v2/version + el changelog del repo.

v0.30.05 sep 2026

Una librería de firma, para que no tengas que escribirla tú

Firmar cada request es lo más delicado de la integración, y los cuatro errores que costaron la primera integración de un partner eran todos el mismo: implementar el sobre canónico a mano. Unir con salto de línea en vez del byte NUL, el nonce en milisegundos, la firma con un prefijo de algoritmo delante, el idempotency-key vacío en un GET. Ahora existe una librería que los hace imposibles: cada uno tiene un test que lo reproduce y falla. Todavía no está publicada, así que esta documentación no te la ofrece — cuando lo esté, te avisamos acá. Mientras tanto el vector de prueba y el helper nextNonce() de la guía de Autenticación siguen siendo la referencia, y los dos se verifican contra esa librería en cada corrida. Lo que la librería no hace a propósito: no envuelve el ciclo de vida del pago, así que no va a romperse cuando exista el estado de devolución.

v0.29.05 sep 2026

Ya puedes ver los códigos de banco, en vez de pedírnoslos

bankCode es obligatorio en los dos rieles y hasta hoy no estaba publicado en ninguna parte: la respuesta era que te pasáramos una lista por chat. Ahora hay una página, Códigos de banco, con los códigos BCV y su institución. Léela en vez de buscar en internet: varias listas que circulan dan 0138 como «Mibanco» cuando es Banco Plaza, y 0177 como «Sofitasa» cuando es BANFANB. Lo que todavía NO hacemos: no rechazamos un código que no esté en la tabla — validamos que sean 4 dígitos y, en CCE, que coincida con el prefijo de la cuenta destino. Y si no encuentras el banco de tu beneficiario, escríbenos: no podemos afirmar que la tabla sea exhaustiva. También: la página de Sandbox y la guía traen ahora las tres variables de entorno en un solo bloque para pegar, con la llave privada como ruta a un archivo y no pegada dentro del .env.

v0.28.02 sep 2026

Ahora puedes saber si un pago mueve dinero de verdad

GET /v2/version trae un campo nuevo, simulado. Es true cuando ese entorno fabrica el resultado de los pagos —el pago te va a decir completed y no se mueve ni un céntimo real— y false cuando los rieles están conectados a un banco. Por qué hacía falta: rails publica lo mismo en los dos casos, así que hasta hoy no había forma de distinguirlos desde afuera: un entorno mal configurado anunciaba sus rieles, respondía completed a cada pago, y no movía nada. Qué haces con esto: míralo antes de dar por buena una prueba. Si el campo no viene, trátalo como true — prometemos de menos a propósito.

v0.27.01 sep 2026

Ya puedes pagar a una cuenta bancaria, no sólo a un pago móvil

El riel "CCE" —la transferencia interbancaria— está construido. Nace cerrado: se habilita por despliegue, así que GET /v2/version deja de publicar un par fijo y el campo rails te dice qué rieles puede despachar el entorno que estás llamando. Léelo, no lo asumas — el sandbox puede tener abierto un riel que producción todavía no. Si pides uno que ese despliegue no tiene habilitado, el pago llega failed con subStatus: "rejected_by_us" y no hubo débito.

v0.27.01 sep 2026

Un beneficiario CCE ahora lleva nombre, banco y documento

Con rail: "CCE" son obligatorios bankCode, docType, docNumber y el campo nuevo beneficiaryName — el nombre que viaja a la cámara de compensación, que no podemos derivar de nada y queda congelado con el resto del destino. Es un cambio incompatible y lo decimos así: aplica sólo a CCE, que todavía no está disponible de forma general y ningún despliegue de producción tiene abierto; el pago móvil no cambió. Qué haces con esto: si guardaste beneficiarios CCE antes de esta versión, no tienen beneficiaryName y no pueden pagar por ese riel. Fíltralos por beneficiaryName: null y reemplázalos — crear el nuevo primero, archivar el viejo después. No recortamos el nombre: si no cabe en 35 caracteres te devolvemos 400 al crearlo, donde lo puedes arreglar, y no al pagar, donde ya no.

v0.27.01 sep 2026

El banco que declaras y la cuenta destino tienen que ser el mismo banco

Una cuenta venezolana empieza por el código BCV de su banco, así que un bankCode que no coincide con los 4 primeros dígitos de la cuenta significa que uno de los dos está mal. Antes eso salía igual hacia la cámara. Ahora te devolvemos 400 y el pago no se crea: no hay débito y tu idempotency-key queda libre. Por qué se corta antes y no después: sobre este riel no hay reverso — un rechazo tardío cuesta comisión y deja la operación en el aire.

v0.26.031 ago 2026

Tu beneficiario de pago móvil ahora lleva banco y documento

Guardar un beneficiario con rail: "PM" ahora exige tres campos nuevos: bankCode (el código BCV del banco, 4 dígitos — Banco Plaza es "0138"), docType y docNumber. Por qué: el pago móvil de Venezuela identifica a quien cobra, y el riel rechaza el pago sin esos datos; no los podemos derivar, porque un prefijo como 0414 identifica a la operadora móvil, no al banco. Hasta esta versión el campo no existía en nuestro contrato, así que ningún pago móvil podía completarse. Qué haces con esto: tus beneficiarios ya guardados probablemente no tengan bankCode, y el destino es inmutable por diseño — hay que archivar el viejo y crear uno nuevo, en ese orden (crear primero da 409). Para encontrarlos, GET /v2/beneficiaries ahora devuelve bankCode: los que traen null son ésos.

v0.26.031 ago 2026

Un rechazo NUESTRO ya no se reporta como si lo hubiera hecho el banco

subStatus: "declined" significa, en esta documentación, que el riel rechazó tu pago. Cuando lo bloqueamos nosotros antes de que el riel lo viera —al beneficiario le falta el banco o el documento, o falta configuración de nuestro lado— eso era falso, y te mandaba a buscar la causa donde no estaba. Esos casos ahora llegan con subStatus: "rejected_by_us". Qué cambia para ti: hay un valor nuevo bajo failed. El status sigue siendo failed y la garantía no cambia —no hubo débito—; lo que cambia es dónde buscar el problema.

v0.26.031 ago 2026

Reusar una clave de idempotencia con otro banco de destino ahora es un 409

El banco y el documento del beneficiario pasan a formar parte de lo que hace única a una operación, igual que el monto y el destino. Antes, mandar la misma idempotency-key con un banco distinto te devolvía el pago original con 200 —al banco viejo— y podías creer que habías corregido. Y mandar beneficiaryId junto con campos del destino en línea, que antes se aceptaba ignorándolos en silencio, ahora es un 400 que te dice cuáles sobran.

v0.25.027 ago 2026

Nueve respuestas más del riel dejaron de reportarse como failed

Misma corrección que en v0.22.0, ahora sobre nueve códigos más. failed significa, en esta documentación, «garantizado que no hubo débito, puedes reemitir con clave nueva» — y una clave nueva desactiva la de-duplicación del riel, así que darlo mal termina en una segunda transferencia real. Revisamos código por código qué dice el riel de cada uno: tres son duplicados (111, 112, 150) y no afirman nada sobre el destino de la operación original; dos son vencimientos de espera (AB01, AB05), que hablan de un reloj y no del dinero; los otros cuatro (A001, A002, A004, 0012) llevaban un comentario nuestro que decía que se rechazan antes de tocar el core, y el riel no dice eso en ningún lado. Qué cambia para ti: si tu sistema ramifica sobre failed para reemitir, esos casos ahora llegan como unknown — no reemitas, consulta y espera la resolución.

v0.24.021 ago 2026

El identificador que ve el banco lo generamos nosotros

Tu idempotency-key sigue siendo tuya y sigue funcionando igual. Lo que cambió es qué viaja al riel: antes iba tu clave tal cual, y el riel se queda con sus últimos 8 caracteres — así que dos claves distintas que terminan igual eran el mismo pago para él. Ahora acuñamos un identificador propio de 8, único por construcción.

v0.23.021 ago 2026

Una transferencia a otro banco ya no se marca completada mientras va en camino

El riel responde «transacción exitosa / enviada a la cámara», y ese «enviada» es literal: si el beneficiario tiene cuenta en otro banco, la operación sigue en vuelo. Ahora esos pagos quedan en pending hasta que la liquidación se confirma, en vez de reportarse como completed antes de tiempo.

v0.22.021 ago 2026

Tres respuestas del riel dejaron de reportarse como failed

Tres códigos —fuera de franja horaria, sistema fuera de línea, y «no se puede procesar»— estaban clasificados como «probadamente no se debitó», y eso te llegaba como failed. Ninguno de los tres lo prueba. Como nuestra guía te dice que ante un failed puedes reemitir con clave nueva, y una clave nueva desactiva la de-duplicación del riel, el peor caso era una segunda transferencia real. Ahora llegan como unknown, que es la verdad: no sabemos todavía. Qué cambia para ti: vas a ver menos failed y más unknown en esos escenarios — no reemitas, espera la resolución.

v0.21.020 ago 2026

«No pude comprobarlo» dejó de tratarse como «no pasó»

Cuando un pago queda en duda lo consultamos al riel. Si esa consulta no concluye, antes escalábamos a intervención manual en el primer intento. Ahora se re-consulta dentro de una ventana antes de escalar: menos pagos detenidos esperando a una persona.

v0.20.020 ago 2026

pending dejó de significar «no sé»

Un riel asíncrono que confirma tener el pago no es lo mismo que un riel que no contesta. Antes los metíamos en el mismo balde y levantábamos una alerta crítica; ahora pending es un estado de tránsito normal y se sigue consultando.

v0.19.220 ago 2026

El servicio se niega a arrancar si la base retrocedió en el tiempo

Endurecimiento interno de la protección anti-replay. No cambia nada de tu integración; se publica porque sostiene la garantía de que una petición firmada tuya no pueda reutilizarse.

v0.19.120 ago 2026

Corregida la recomendación de nonce en la guía de autenticación

Decía que «un timestamp en milisegundos suele bastar». Medido: con 8 peticiones en paralelo pasa exactamente una, porque en el mismo milisegundo todos los nonces son iguales. La guía ahora recomienda un nonce con aleatoriedad y trae un helper ejecutable.

v0.19.020 ago 2026

Las lecturas firmadas ya no te obligan a serializar

Ventana anti-replay deslizante (RFC 4303) en las 7 rutas GET. Antes, dos lecturas en paralelo desde una misma llave se rechazaban entre sí. Medido: la aceptación en paralelo pasó de 31 % a 100 % y la latencia p99 de 111 ms a 21 ms. Las escrituras conservan la marca estricta.

v0.18.219 ago 2026

La doc de autenticación nunca mencionaba el header x-nonce

Y además afirmaba que no era un header. Corregido en la guía y en el contrato.

v0.18.119 ago 2026

La página de Conciliación prometía una automatización que no existe

Decía que emparejábamos el crédito de una devolución con el pago original y lo reflejábamos solo. No es así: un crédito sin fondeo registrado queda como excepción y lo trabaja una persona. La página ahora dice lo que el sistema hace.

v0.18.019 ago 2026

Los webhooks quedan garantizados de punta a punta

El drenador del canal asíncrono cierra el circuito: todo cambio de estado de un pago genera su evento en la misma transacción que el cambio, y el envío se reintenta con respaldo propio. Ningún cambio de estado puede quedarse sin notificar.

v0.17.119 ago 2026

Guard de arranque contra una base sin migrar

Interno. El servicio se niega a arrancar si el esquema no está al día, en vez de servir peticiones contra una base incompleta.

v0.17.019 ago 2026

Outbox de eventos: ningún cambio de estado sin su evento

La fila del evento se escribe en la misma transacción que el cambio de estado del pago. Si una de las dos falla, no pasa ninguna.

v0.16.019 ago 2026

Un webhook caído dejó de ser indistinguible de uno que recibió todo

Antes descartábamos la respuesta HTTP de tu endpoint, así que un 500 tuyo no dejaba rastro — mientras la doc prometía reintentos. Ahora la respuesta se registra y el reintento es real.

v0.15.119 ago 2026

Los 27 parámetros de header salían required: false en el contrato

Reportado por un integrador. La prosa los llamaba obligatorios pero el contrato decía lo contrario, así que un generador de clientes hacía opcionales las credenciales. Corregido: si generaste un cliente antes de esta versión, vuelve a generarlo.

v0.15.019 ago 2026

Gate de fidelidad doc↔contrato, bloqueante

Interno. Ninguna afirmación de esta documentación puede contradecir al contrato OpenAPI sin romper el build. Es la razón por la que lo que lees acá coincide con lo que responde la API.

v0.14.018 ago 2026

Gate de despliegue del API

Interno. Cierra el hueco de que un arreglo se mergee y el ambiente siga sirviendo la versión vieja: ahora el despliegue se verifica contra la huella del build.

v0.13.025 jul 2026

Versión + discovery — GET /v2/version

Endpoint público que un consumidor llama antes de firmar: release vivo, rieles soportados y enlaces al contrato.

v0.12.025 jul 2026

Conciliación automática (recon)

Cuadre continuo del saldo del banco contra el ledger: caza débitos huérfanos, dobles-débitos y pagos sin fondeo.

v0.11.025 jul 2026

Identidad de tu llave — GET /v2/me

Endpoint firmado y read-only: qué entidad eres, qué ambiente, tu webhook y tus límites. Sin filtrar ningún secreto.

v0.10.025 jul 2026

Beneficiarios reutilizables

Guarda un beneficiario una vez y págale por beneficiaryId. Destino congelado tras crearlo (money-safety).

v0.9.025 jul 2026

Contrato OpenAPI público

/v2/openapi.json derivado del schema real: la referencia nunca discrepa de lo desplegado.

v0.8.024 jul 2026

Firma de webhooks salientes

Webhooks firmados con RSA asimétrica + JWKS: verificas el origen sin secreto compartido.