API
Solicita acceso →
Referencia / Beneficiarios

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, banco 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.

i
El beneficiario no es obligatorio para pagar. Puedes emitir pagos con destino en línea sin guardar nada. Guardar beneficiarios es una capa de comodidad y de money-safety para destinos recurrentes: menos campos que repetir en cada pago y un destino ya verificado y congelado.

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.

!
Lo único editable es la etiqueta, no el destino. 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, x-nonce y x-signature— igual que el resto del API. Los que modifican datos (POST, PATCH, DELETE) llevan además idempotency-key.

POST/v2/beneficiariesGuarda un destino nuevo y congela sus datos
GET/v2/beneficiariesLista tus beneficiarios (paginación keyset)
GET/v2/beneficiaries/:idRecupera un beneficiario por su id
PATCH/v2/beneficiaries/:idEdita solo el alias o el estado
DELETE/v2/beneficiaries/:idArchiva el beneficiario (soft-delete)

Crear un beneficiario

POST/v2/beneficiaries

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

CampoTipoDescripción
railreqstringEl 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.
accountreqstringEl destino en sí. El formato depende del riel: con "PM" es el móvil de 11 dígitos incluyendo el 0 inicial (04141234567); con "CCE" es la cuenta bancaria de 20 dígitos (01020304050600070809). Queda congelado: cambiar a dónde va el dinero es crear otro beneficiario, nunca editar este — y el orden importa, mira «Cómo reemplazar un beneficiario» más abajo. No lo validamos por formato acá — un destino mal formado lo rechaza el riel y te llega como invalid_phone_number.
bankCodereq PM · CCEstringEl banco del beneficiario, como código BCV de 4 dígitos (Banco Plaza es "0138"). Obligatorio con rail: "PM": el riel rechaza un pago móvil sin él, y no lo podemos derivar — un prefijo como 0414 identifica a la operadora móvil, no al banco. Obligatorio también con rail: "CCE": ahí es el banco acreedor del mensaje interbancario, y tiene que coincidir con los 4 primeros dígitos de la cuenta destino — si no coinciden te devolvemos 400 al crear el beneficiario, donde lo puedes arreglar, y no al pagar, donde ya no. Queda congelado igual que el resto del destino. El catálogo completo de códigos está en Códigos de banco.
docTypereq PM · CCEstringTipo de documento del titular: "V", "E", "J", "P" o "G". Obligatorio con rail: "PM": el pago móvil de Venezuela identifica a quien cobra. Obligatorio también con rail: "CCE": junto con docNumber arma la identificación del beneficiario que viaja en el mensaje interbancario. Va pareado con docNumber.
docNumberreq PM · CCEstringNúmero del documento, sólo dígitos y sin el prefijo (el prefijo es docType), hasta 15. Obligatorio con rail: "PM" y con rail: "CCE". Ejemplo: con docType: "V" y docNumber: "12345678", al banco le llega V12345678.
beneficiaryNamereq CCEstringEl nombre del beneficiario tal como tiene que aparecer en el mensaje interbancario, máximo 35 caracteres. Obligatorio con rail: "CCE": ese nombre viaja a la cámara de compensación y no lo podemos derivar. No es el alias — el alias es tu etiqueta interna y lo puedes editar; esto es el nombre de quien cobra y queda congelado con el resto del destino. Con "PM" no se usa: ese riel identifica a quien cobra por documento. No lo recortamos: si no cabe en 35 te devolvemos 400 al crearlo, donde lo puedes arreglar, y no al pagar, donde ya no.
aliasreqstringEtiqueta 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. Es obligatorio: sin él la creación devuelve 400.
i
El destino es solo inline aquí. Al crear un beneficiario describes el destino con rail+beneficiary. El beneficiaryId nace de esta operación; no lo mandas tú, lo recibes en la respuesta.
cURLNodeCopiar
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 "x-nonce: 1721683200123456" \
  -H "idempotency-key: benef-maria-pm-01" \
  -H "Content-Type: application/json" \
  -d '{
    "rail": "PM",
    "account": "04141234567",
    "bankCode": "0138",
    "docType": "V",
    "docNumber": "12345678",
    "alias": "María — Nómina"
  }'
RESPUESTA 201 application/json
{
  "status": "success",
  "traceId": "trc_9f2a7c1b",
  "payload": {
    "id": "312",
    "alias": "María — Nómina",
    "rail": "PM",
    "account": "04141234567",
    "docType": "V",
    "docNumber": "12345678",
    "status": "ACTIVE",
    "createdAt": "2026-08-18T14:03:11.482Z"
  }
}

El mismo beneficiario, pero por CCE. El riel interbancario pide dos campos más que el pago móvil: el bankCode del banco acreedor —que tiene que coincidir con los 4 primeros dígitos de la cuenta— y el beneficiaryName, el nombre que viaja a la cámara de compensación. El documento va igual que en "PM".

cURLCopiar
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 "x-nonce: 1721683200123457" \
  -H "idempotency-key: benef-distribuidora-cce-01" \
  -H "Content-Type: application/json" \
  -d '{
    "rail": "CCE",
    "account": "01020304050600070809",
    "bankCode": "0102",
    "docType": "J",
    "docNumber": "402556677",
    "beneficiaryName": "DISTRIBUIDORA CENTRAL C.A.",
    "alias": "Proveedor CCE"
  }'

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—.

Pruébalo. En sandbox (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.

cURLNodeCopiar
curl -X POST https://alibanca-api-production.up.railway.app/v2/payments \
  -H "x-api-key: sk_test_…" \
  -H "x-signature: …" \
  -H "x-nonce: 1721683200123456" \
  -H "idempotency-key: pago-nomina-maria-2026-07" \
  -H "Content-Type: application/json" \
  -d '{
    "amountMinor": "150000",
    "currency": "VES",
    "beneficiaryId": "312"
  }'

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.

!
Nunca mezcles las dos formas de destino. 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

GET/v2/beneficiaries

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

1

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).

2

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.

3

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.

4

Repite hasta que venga vacío

Cuando una página vuelve sin elementos, ya recorriste todo. Ahí paras.

cURLNodeCopiar
# primera página
curl "https://alibanca-api-production.up.railway.app/v2/beneficiaries?limit=20" \
  -H "x-api-key: sk_test_…" -H "x-signature: …" \
  -H "x-nonce: 1721683200123456"

# 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=312" \
  -H "x-api-key: sk_test_…" -H "x-signature: …"
RESPUESTA 200 application/json
{
  "status": "success",
  "traceId": "trc_5b1e6a90c4d2",
  "payload": {
    "data": [
      {
        "id": "318",
        "alias": "Proveedor CCE",
        "rail": "CCE",
        "account": "01020304050600070809",
        "bankCode": "0102",
        "docType": "J",
        "docNumber": "402556677",
        "beneficiaryName": "DISTRIBUIDORA CENTRAL C.A.",
        "status": "ACTIVE",
        "createdAt": "2026-08-18T15:20:04.001Z"
      },
      {
        "id": "312",
        "alias": "María — Nómina",
        "rail": "PM",
        "account": "04141234567",
        "docType": "V",
        "docNumber": "12345678",
        "status": "ACTIVE",
        "createdAt": "2026-08-18T14:03:11.482Z"
      }
    ],
    "hasMore": false,
    "nextCursor": null
  }
}
i
Los nombres exactos de los parámetros de página (por ejemplo el nombre del cursor y del tamaño de lote) están en el contrato /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

GET/v2/beneficiaries/:id

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.

cURLNodeCopiar
curl "https://alibanca-api-production.up.railway.app/v2/beneficiaries/312" \
  -H "x-api-key: sk_test_…" -H "x-signature: …" \
  -H "x-nonce: 1721683200123456"
RESPUESTA 200 application/json
{
  "status": "success",
  "traceId": "trc_a12f5c7b3e91",
  "payload": {
    "id": "312",
    "alias": "María — Nómina",
    "rail": "PM",
    "account": "04141234567",
    "docType": "V",
    "docNumber": "12345678",
    "status": "ACTIVE",
    "createdAt": "2026-08-18T14:03:11.482Z"
  }
}

Si el id no existe (o no pertenece a tu llave) recibes un 404 con el cuerpo de error { "error": "…" }. Un beneficiario archivado 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/v2/beneficiaries/:id

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).

CampoTipoDescripción
aliasreqstringNueva etiqueta legible. No afecta el destino; solo cambia cómo lo llamas tú.
cURLNodeCopiar
curl -X PATCH https://alibanca-api-production.up.railway.app/v2/beneficiaries/312 \
  -H "x-api-key: sk_test_…" -H "x-signature: …" \
  -H "x-nonce: 1721683200123456" \
  -H "idempotency-key: patch-alias-maria-01" \
  -H "Content-Type: application/json" \
  -d '{ "alias": "María (nómina quincenal)" }'
!
Si intentas editar el destino, no pasa. Mandar 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

DELETE/v2/beneficiaries/:id

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. Es la única forma de archivarlo: el PATCH solo mueve el alias, nunca el estado.

cURLNodeCopiar
curl -X DELETE https://alibanca-api-production.up.railway.app/v2/beneficiaries/312 \
  -H "x-api-key: sk_test_…" -H "x-signature: …" \
  -H "x-nonce: 1721683200123456" \
  -H "idempotency-key: archivar-maria-01"
RESPUESTA 200 application/json
{
  "status": "success",
  "traceId": "trc_c88d41f0a2b7",
  "payload": {
    "id": "312",
    "status": "INACTIVE"
  }
}

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. Y no se revive: un beneficiario INACTIVE ya no admite PATCH (responde 404). Si vuelves a necesitar ese destino, regístralo de nuevo — archivar libera el duplicado, así que la misma cuenta se puede crear otra vez.

Cómo reemplazar un beneficiario

El destino es inmutable, así que reemplazarlo es archivar el viejo y crear uno nuevo. El orden importa: mientras el viejo siga ACTIVE, crear otro con el mismo rail y la misma account te devuelve 409 — es el mismo guard que impide que un reintento de red te acuñe dos destinos activos hacia el mismo lugar.

1. DELETE /v2/beneficiaries/{id}     ← archiva el viejo (queda INACTIVE)
2. POST   /v2/beneficiaries          ← crea el nuevo, con los datos completos

Al revés no funciona. Si intentas crear primero, el 409 te dice exactamente eso.

Si guardaste beneficiarios antes de agosto de 2026, es probable que no tengan bankCode: ese campo no existía y no se puede agregar después, porque el destino está congelado. Un pago móvil hacia uno de ellos no puede salir — te llega failed con subStatus: "rejected_by_us". Para encontrarlos, lista tus beneficiarios y filtra los que traen bankCode: null; después reemplázalos con los dos pasos de arriba. Lo mismo aplica a los beneficiarios rail: "CCE" guardados antes de septiembre de 2026, que no tienen beneficiaryName: ese nombre viaja a la cámara de compensación y tampoco se puede agregar después. Fíltralos por beneficiaryName: null y reemplázalos igual.

Errores comunes y cómo evitarlos

SituaciónQué pasaCómo resolverlo
Destino doble400Mandaste beneficiaryId junto con rail+beneficiary en un pago. Son excluyentes: deja solo uno.
Editar el destinosin efectoIntentaste cambiar rail/account/bankCode/documento vía PATCH. Están congelados: archiva este y crea uno nuevo, en ese orden.
Crear antes de archivar409Creaste el reemplazo con el viejo todavía ACTIVE. Archiva primero (DELETE), después crea.
Id inexistente404El :id no existe o no es de tu llave. Verifica que guardaste el payload.id correcto al crear.
Pagar a un archivadorechazadoNo se reactiva: un beneficiario INACTIVE tampoco se puede editar (el PATCH solo alcanza filas ACTIVE, así que responde 404). Para volver a pagar a ese destino, créalo de nuevo con POST /v2/beneficiaries: retirarlo libera el duplicado, así que la misma cuenta se puede registrar otra vez.
Paginar por offsetregistros repetidosNo 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ó.

i
Siguiente lectura. Para emitir el pago en sí y entender los estados completed unknown failed revisa Pagos →. Para firmar tus peticiones y entender el envelope canónico, Autenticación →. El contrato campo-por-campo siempre está en /v2/openapi.json →.