Beneficiarios
Un beneficiario es un destino de dinero que guardas una vez para reutilizarlo tantas veces como quieras. En lugar de escribir el teléfono o la cuenta cada vez que emites un pago, lo guardas con POST /v2/beneficiaries, recibes un beneficiaryId y de ahí en adelante pagas citando ese id. El destino queda congelado el instante en que lo creas —rail, cuenta y documento son inmutables— y nunca se borra a la fuerza: se archiva. Todo esto existe por una sola razón, money-safety: que el dinero salga siempre hacia donde tú verificaste, y no hacia donde un typo o un cambio silencioso lo desvíe.
Qué es un beneficiario y por qué usarlo
Piensa en tu libreta de contactos del teléfono. La primera vez guardas el número de una persona con su nombre; después la llamas por el nombre, no marcando los once dígitos de memoria. Un beneficiario es exactamente eso para mover dinero: registras el rail (el carril por el que viaja el dinero), la cuenta o teléfono destino y el documento del titular, le pones un alias legible, y a cambio recibes un identificador estable —el beneficiaryId—.
Ese id es la pieza que te ahorra trabajo y, más importante, te ahorra errores. Cuando emites un pago con POST /v2/payments tienes dos maneras de decir hacia dónde va el dinero:
1) Destino en línea (inline): pasas rail + beneficiary en el mismo cuerpo del pago. Útil para un destino de una sola vez.
2) Destino guardado: pasas solo beneficiaryId. Alibanca ya conoce el rail, la cuenta y el documento porque los verificaste al crear el beneficiario.
Estas dos maneras son excluyentes (un XOR, en jerga: una o la otra, jamás las dos). Si mandas beneficiaryId y rail+beneficiary en el mismo pago, la petición se rechaza. La razón es de seguridad: un pago no puede tener dos destinos ambiguos.
El destino se congela al crearse
Este es el concepto más importante de todo el recurso, así que léelo con calma. En el momento exacto en que creas un beneficiario, sus tres campos de destino —rail, beneficiary (la cuenta o el teléfono) y documento— quedan congelados: son inmutables. No hay ningún endpoint que los cambie. Ni PATCH, ni ningún otro.
¿Por qué tan estricto? Porque un beneficiario representa hacia dónde va el dinero. Si esos campos fueran editables, existiría un ataque clásico: alguien guarda una cuenta legítima, la deja pasar tus controles internos, y después la reemplaza en silencio por otra cuenta justo antes de que corra tu nómina. Todos tus pagos futuros a ese alias irían al lugar equivocado sin que nada se vea sospechoso. Congelar el destino cierra esa puerta de raíz: el par (alias → cuenta) que verificaste hoy es el mismo par que se paga dentro de seis meses.
La consecuencia práctica es simple y debes tenerla presente al diseñar tu integración: si una cuenta destino cambia, creas un beneficiario nuevo. No editas el viejo —no puedes—; archivas el viejo y guardas el nuevo con los datos correctos. Es un beneficiario por cada destino real.
PATCH cambia el alias (cómo lo llamas tú) y el estado (activo/archivado). El rail, la cuenta y el documento no se tocan nunca. Si necesitas otra cuenta, es otro beneficiario.Se archiva, no se borra
Cuando ya no quieres usar un beneficiario, lo archivas con DELETE /v2/beneficiaries/:id. Ojo con el nombre del verbo: aunque el método HTTP es DELETE, la operación es un soft-delete —un borrado suave—. El beneficiario no desaparece de la base de datos; se marca como archivado y deja de estar disponible para pagos nuevos.
Esto también es money-safety, pero de otro tipo: la trazabilidad. Un beneficiario que recibió dinero es parte de la historia de tus movimientos. Si se borrara de verdad, un pago viejo apuntaría a un destino que ya no existe y tu auditoría quedaría con un hueco. Al archivar, el registro se conserva intacto: puedes consultar el beneficiario por su id, ver a dónde fueron esos pagos y reconstruir cualquier historia. En un sistema que mueve dinero, la regla es preservar y marcar, nunca destruir.
Archivar es reversible en el sentido de la etiqueta: con PATCH puedes volver a poner el estado en activo si te equivocaste. Lo que jamás cambia, insistimos, es el destino congelado.
Los endpoints del recurso
El recurso Beneficiarios tiene cinco endpoints: uno para crear, dos para leer (listar y ver uno), uno para editar la etiqueta y uno para archivar. Todos viven bajo /v2 y todos exigen tus cabeceras de autenticación —x-api-key y x-signature— igual que el resto del API. Los que modifican datos (POST, PATCH, DELETE) llevan además idempotency-key.
Crear un beneficiario
Guarda un destino nuevo. Le pasas el rail, la cuenta o teléfono, el documento del titular y, opcionalmente, un alias legible. Alibanca valida los datos, los congela y te devuelve el beneficiario con su id —ese es el beneficiaryId que usarás al pagar—.
Cuerpo de la petición
| Campo | Tipo | Descripción |
|---|---|---|
| railreq | string | El carril por el que viaja el dinero. "PM" = pago móvil (el destino es un teléfono). "CCE" = transferencia interbancaria por CCE (el destino es una cuenta). Este valor queda congelado. |
| beneficiaryreq | string | El destino en sí: el número de teléfono cuando el rail es PM, o el número de cuenta cuando el rail es CCE. Queda congelado. |
| documentoreq | string | Documento de identidad del titular de la cuenta destino (por ejemplo cédula V-12345678 o RIF J-…). Es parte del destino verificado y también queda congelado. |
| alias | string | Etiqueta legible para que tú reconozcas el destino (por ejemplo "María — Nómina"). Es lo único, junto al estado, que podrás editar después. Si lo omites, el beneficiario existe igual; el alias es para tu comodidad. |
rail+beneficiary. El beneficiaryId nace de esta operación; no lo mandas tú, lo recibes en la respuesta.curl -X POST https://alibanca-api-production.up.railway.app/v2/beneficiaries \ -H "x-api-key: sk_test_…" \ -H "x-signature: …" # firma RSA-SHA256 del envelope canónico -H "idempotency-key: benef-maria-pm-01" \ -H "Content-Type: application/json" \ -d '{ "rail": "PM", "beneficiary": "04141234567", "documento": "V-12345678", "alias": "María — Nómina" }'
{ "status": "success", "traceId": "trc_9f2a7c1b", "payload": { "id": "ben_3KQ8vXr2", "alias": "María — Nómina", "rail": "PM", "beneficiary": "04141234567", "documento": "V-12345678", "estado": "active", "createdAt": "2026-07-22T14:03:11Z" } }
El campo que te importa guardar de tu lado es payload.id: ese ben_… es el beneficiaryId. Nota que estado nace en active y que el destino ya viene congelado —lo verás idéntico cada vez que lo consultes—.
sk_test_…) esta llamada crea un beneficiario real dentro de tu entorno de pruebas, pero el proveedor es simulado: cuando después le pagues, no se mueve ni un céntimo real. Es el lugar perfecto para probar el flujo completo crear → pagar → consultar sin riesgo.Usar el beneficiario en un pago
Este es el pago del ejemplo anterior visto en acción. Ya tienes el beneficiaryId; ahora emites el pago citándolo, sin repetir rail ni cuenta ni documento. Alibanca los resuelve desde el destino congelado.
curl -X POST https://alibanca-api-production.up.railway.app/v2/payments \ -H "x-api-key: sk_test_…" \ -H "x-signature: …" \ -H "idempotency-key: pago-nomina-maria-2026-07" \ -H "Content-Type: application/json" \ -d '{ "amountMinor": "150000", "currency": "VES", "beneficiaryId": "ben_3KQ8vXr2" }'
Fíjate en lo que no está en ese cuerpo: no hay rail ni beneficiary. Con un beneficiario guardado, el destino sobra porque ya vive congelado bajo ese id. El monto va en amountMinor como string en céntimos ("150000" = 1.500,00 VES), nunca como número decimal.
beneficiaryId es excluyente con rail+beneficiary. Si mandas ambos en el mismo pago, Alibanca lo rechaza. Elige uno: id guardado, o destino en línea.Listar beneficiarios
Devuelve tus beneficiarios en páginas usando paginación keyset. Vale la pena entender qué es, porque no es la paginación por número de página a la que quizás estás acostumbrado.
La paginación clásica por offset dice "dame la página 3, saltando las primeras 40 filas". Es cómoda pero frágil: si alguien crea un beneficiario mientras paginas, las filas se corren y puedes ver un registro dos veces o saltarte otro. La paginación keyset resuelve esto usando un ancla estable: en vez de un número de página, avanzas desde el último id que viste. Como los ids se ordenan de forma descendente y no se reordenan, nunca hay corrimiento.
Cómo iterar
Pide la primera página
Llama GET /v2/beneficiaries sin cursor. Recibes un lote de beneficiarios ordenado por id descendente (los más nuevos primero).
Toma el id más bajo del lote
El último elemento de la página que recibiste tiene el id más bajo. Ese id es tu cursor para la siguiente página.
Pide la siguiente página desde ese id
Vuelve a llamar pasando ese id como cursor. Recibes los beneficiarios que siguen, más viejos que el último visto.
Repite hasta que venga vacío
Cuando una página vuelve sin elementos, ya recorriste todo. Ahí paras.
# primera página curl "https://alibanca-api-production.up.railway.app/v2/beneficiaries?limit=20" \ -H "x-api-key: sk_test_…" -H "x-signature: …" # siguiente página: cursor = id más bajo de la página anterior curl "https://alibanca-api-production.up.railway.app/v2/beneficiaries?limit=20&cursor=ben_3KQ8vXr2" \ -H "x-api-key: sk_test_…" -H "x-signature: …"
{ "status": "success", "traceId": "trc_5b1e…", "payload": [ { "id": "ben_7Zc…", "alias": "Proveedor CCE", "rail": "CCE", "estado": "active" }, { "id": "ben_3KQ8vXr2", "alias": "María — Nómina", "rail": "PM", "estado": "active" } ] }
/v2/openapi.json →, que es público. Úsalo como fuente de verdad para los detalles finos; la mecánica keyset —avanzar desde el último id— es la misma que en el listado de Pagos →.Ver un beneficiario
Recupera un beneficiario puntual por su id. Te sirve para confirmar un destino antes de pagarle, para mostrarlo en tu interfaz o para verificar en qué estado quedó tras un archivado. Devuelve el objeto completo, con el destino congelado tal cual lo creaste.
curl "https://alibanca-api-production.up.railway.app/v2/beneficiaries/ben_3KQ8vXr2" \ -H "x-api-key: sk_test_…" -H "x-signature: …"
{ "status": "success", "traceId": "trc_a12f…", "payload": { "id": "ben_3KQ8vXr2", "alias": "María — Nómina", "rail": "PM", "beneficiary": "04141234567", "documento": "V-12345678", "estado": "active" } }
Si el id no existe (o no pertenece a tu llave) recibes un 404 con el cuerpo de error { "error": "…" }. Un beneficiario archivado sí responde aquí: por eso archivamos en vez de borrar —la lectura histórica sigue viva—, solo que su estado vendrá como archived.
Editar alias o estado
PATCH es la única puerta de edición, y a propósito es angosta: solo toca dos campos, alias y estado. Nada del destino congelado es alcanzable desde aquí. Pasas únicamente los campos que quieras cambiar (por eso es PATCH y no PUT: es una edición parcial).
| Campo | Tipo | Descripción |
|---|---|---|
| alias | string | Nueva etiqueta legible. No afecta el destino; solo cambia cómo lo llamas tú. |
| estado | string | Nuevo estado del beneficiario: "active" (disponible para pagos) o "archived" (fuera de circulación). Poner archived por aquí equivale a archivarlo; ponerlo de vuelta en active lo reactiva. |
curl -X PATCH https://alibanca-api-production.up.railway.app/v2/beneficiaries/ben_3KQ8vXr2 \ -H "x-api-key: sk_test_…" -H "x-signature: …" \ -H "idempotency-key: patch-alias-maria-01" \ -H "Content-Type: application/json" \ -d '{ "alias": "María (nómina quincenal)" }'
rail, beneficiary o documento en un PATCH no cambia nada: esos campos son inmutables por diseño. ¿Necesitas otra cuenta? Archiva este beneficiario y crea uno nuevo con el destino correcto.Archivar un beneficiario
Saca el beneficiario de circulación. Recuerda: es un soft-delete. El registro se conserva —lo puedes seguir consultando por id— pero su estado pasa a archived y deja de estar disponible para pagos nuevos. Equivale a un PATCH que pone estado: "archived", con la ventaja de que es la intención explícita "archívalo".
curl -X DELETE https://alibanca-api-production.up.railway.app/v2/beneficiaries/ben_3KQ8vXr2 \ -H "x-api-key: sk_test_…" -H "x-signature: …" \ -H "idempotency-key: archivar-maria-01"
{ "status": "success", "traceId": "trc_c88d…", "payload": { "id": "ben_3KQ8vXr2", "estado": "archived" } }
Después de archivar, un pago que intente usar ese beneficiaryId será rechazado: el destino existe en la historia pero ya no está activo para mover dinero. Si te arrepientes, un PATCH con estado: "active" lo revive con su destino intacto.
Errores comunes y cómo evitarlos
| Situación | Qué pasa | Cómo resolverlo |
|---|---|---|
| Destino doble | 400 | Mandaste beneficiaryId junto con rail+beneficiary en un pago. Son excluyentes: deja solo uno. |
| Editar el destino | sin efecto | Intentaste cambiar rail/beneficiary/documento vía PATCH. Están congelados: crea un beneficiario nuevo. |
| Id inexistente | 404 | El :id no existe o no es de tu llave. Verifica que guardaste el payload.id correcto al crear. |
| Pagar a un archivado | rechazado | Reactiva con PATCH estado: "active", o crea uno nuevo si el destino cambió. |
| Paginar por offset | registros repetidos | No uses número de página. Avanza siempre con el cursor = último id visto. |
Buenas prácticas
Un beneficiario por destino real, no por persona. Si un mismo titular te da dos cuentas, son dos beneficiarios. Como el destino se congela, cada cuenta necesita su propio registro. El alias es donde pones el nombre humano para reconocerlos.
Usa idempotency-key determinística al crear. Si tu proceso reintenta la creación (por un timeout, por ejemplo), la misma idempotency-key te devuelve el mismo beneficiario en vez de crear un duplicado. Deriva la clave de algo estable de tu lado —un id interno del destino—, no de un aleatorio nuevo por intento.
Guarda el beneficiaryId de tu lado y trátalo como el ancla. Es el único campo que no puedes reconstruir tú: nace del POST. Persístelo junto a tu registro interno para que tus pagos futuros solo tengan que citarlo.
Prefiere beneficiarios guardados para destinos recurrentes. Menos campos en cada pago significa menos superficie de error humano, y el destino ya viene verificado y congelado. El destino en línea guárdalo para pagos de una sola vez.
Verifica antes de pagar en flujos críticos. Un GET /v2/beneficiaries/:id te confirma el estado y el destino congelado justo antes de emitir un pago grande. Barato, y te ahorra pagarle a un beneficiario que alguien archivó.