Referencia API

El API de BCH Instant se sirve bajo el prefijo /api/v1. Todas las peticiones y respuestas son JSON (Content-Type: application/json) y los importes son cadenas decimales en ehnl (Lempira digital, 2 decimales).

Los ejemplos de esta referencia usan datos de demostración: el banco Banco Demo con usuarios y pagos pre-cargados, y @alias resolubles en otros bancos participantes (@juanp, @sofiar, @pedroh).

Autenticación

Cada banco participante recibe una clave de API por entorno durante el onboarding. Envíala en todas las peticiones como bearer token:

Authorization: Bearer <tu_clave_de_api>

La clave identifica a tu banco (organización): los usuarios que registras y los pagos que envías quedan asociados a él, y los listados solo devuelven la actividad en la que tu banco participa.

Usuarios — /api/v1/users

Clientes de tu banco registrados en la red de pagos instantáneos.

Método y rutaDescripción
POST /usersRegistra un cliente en la red
GET /usersLista los usuarios de tu banco
GET /users/{userId}Obtiene un usuario
POST /users/{userId}/aliasRegistra o reemplaza el @alias del usuario
POST/api/v1/users

Registra un cliente. alias es opcional: puede reservarse en el alta o registrarse después con POST /users/{userId}/alias.

// Petición
{
  "firstName": "Laura",
  "lastName": "Castillo",
  "displayName": "Laura Castillo",   // opcional
  "alias": "laurac"                  // opcional
}

// 201 Created
{
  "id": "usr_5f3a9c1e8b2d4706",
  "organizationId": "org_2f7c1d8a9b3e4f50",
  "organizationName": "Banco Demo",
  "firstName": "Laura",
  "lastName": "Castillo",
  "displayName": "Laura Castillo",
  "alias": "laurac",
  "status": "ACTIVE",
  "createdAt": "2026-07-29T15:04:11.000Z"
}

Errores: 400 si faltan campos o el alias es inválido, 409 si el alias ya está registrado.

GET/api/v1/users

Lista paginada de los usuarios registrados por tu banco: { "items": [...], "total": 4, "page": 1, "pageSize": 50 }.

GET/api/v1/users/{userId}

Devuelve el usuario, incluido su status (ACTIVE · SUSPENDED · DELETED) y su @alias actual. 404 si no existe.

POST/api/v1/users/{userId}/alias

Registra (o reemplaza) el @alias del usuario. El alias se normaliza a minúsculas y sin la @ inicial.

// Petición
{ "alias": "laurac" }

// 200 OK → el usuario actualizado
{ "id": "usr_5f3a9c1e8b2d4706", "alias": "laurac", ... }

Errores: 409 si el alias está ocupado, 400 si no cumple el formato (3–30 caracteres: a-z, 0-9, ., _, -).

Alias — /api/v1/aliases

El directorio de @alias de toda la red, compartido por todos los bancos participantes.

Método y rutaDescripción
GET /aliases/{alias}/availabilityComprueba si un @alias está libre
GET /aliases/{alias}/resolveResuelve un @alias a su titular, en cualquier banco
GET/api/v1/aliases/{alias}/availability

Pensado para validar en vivo mientras el cliente teclea. Devuelve el alias normalizado y si puede registrarse:

// 200 OK
{ "alias": "laurac", "available": true }
GET/api/v1/aliases/{alias}/resolve

Resuelve un @alias a su titular para confirmar el destinatario antes de pagar — funciona igual para alias de tu banco y de cualquier otro banco participante:

// 200 OK
{
  "alias": "juanp",
  "displayName": "Juan Pérez",
  "organizationId": "org_8a1b2c3d4e5f6071",
  "organizationName": "Banco Atlántida"
}

404 si el alias no está registrado en la red.

Pagos — /api/v1/payments

Envío y consulta de pagos instantáneos. Los pagos dentro de tu banco (INTERNAL) liquidan internamente; entre bancos (CROSS_ORGANIZATION) liquidan on-chain en los rieles CBDC y la respuesta incluye el hash y la altura de bloque de la transacción de liquidación.

Método y rutaDescripción
POST /paymentsEnvía un pago instantáneo a un @alias
GET /paymentsLista los pagos de tu banco (paginado, filtrable)
GET /payments/{paymentId}Obtiene un pago por id o por id público ip_…
POST/api/v1/payments

Envía un pago desde uno de tus usuarios a cualquier @alias de la red. Envía siempre un idempotencyKey: si la petición se repite, devuelve el pago original en lugar de crear un duplicado.

// Petición
{
  "senderUserId": "usr_5f3a9c1e8b2d4706",
  "recipientAlias": "juanp",
  "amount": "150.00",
  "denom": "ehnl",                   // opcional, por defecto ehnl
  "reference": "Almuerzo",           // opcional, concepto libre
  "idempotencyKey": "9c2e6a4f-…"     // recomendado
}

// 201 Created
{
  "id": "pay_1c9e5b7a3f2d8064",
  "publicId": "ip_4e8a9f702c5d8b1a",
  "status": "FINALIZED",
  "kind": "CROSS_ORGANIZATION",
  "reference": "Almuerzo",
  "sender":    { "alias": "laurac", "name": "Laura Castillo",
                 "organizationName": "Banco Demo", ... },
  "recipient": { "alias": "juanp", "name": "Juan Pérez",
                 "organizationName": "Banco Atlántida", ... },
  "amount": { "denom": "ehnl", "amount": "150.00" },
  "chainTxHash": "8F4A…C21D",
  "chainHeight": "1851204",
  "settlement": {
    "type": "ON_CHAIN",
    "fromBank": "Banco Demo",
    "toBank": "Banco Atlántida",
    "chainTxHash": "8F4A…C21D",
    "chainHeight": "1851204"
  },
  "timings": { "totalMs": 3120, "settlementMs": 2720 },
  "failureCode": null,
  "failureMessage": null,
  "createdAt": "2026-07-29T15:06:02.000Z",
  "completedAt": "2026-07-29T15:06:05.120Z"
}

El ciclo de vida del pago es RECEIVED → PREPARED → SIGNED → SUBMITTED → FINALIZED (o FAILED con failureCode). La respuesta se devuelve con el pago ya finalizado.

Errores: 404 si el emisor o el alias destino no existen, 422 si el emisor no tiene @alias o coincide con el destino, 400 si el importe es inválido.

GET/api/v1/payments

Lista los pagos en los que participa tu banco, del más reciente al más antiguo.

ParámetroDescripción
directionINBOUND · OUTBOUND · INTERNAL, relativo a tu banco
aliasSolo pagos enviados o recibidos por ese @alias (historial de un cliente)
page, pageSizePaginación (por defecto 1 y 20, máx. 100)
// 200 OK
{
  "items": [ { "publicId": "ip_9f8e7d6c5b4a3921", "direction": "OUTBOUND", ... } ],
  "total": 6,
  "page": 1,
  "pageSize": 20
}
GET/api/v1/payments/{paymentId}

Devuelve el pago completo por su id interno o su publicId (familia ip_…, apto para mostrarse y copiarse en tu app). 404 si no existe.

Errores

Todos los errores comparten el mismo cuerpo:

{
  "statusCode": 409,
  "error": "Conflict",
  "message": "Alias @laurac is already registered."
}
CódigoCuándo
400 Bad RequestCuerpo o parámetros inválidos (importe mal formado, alias con formato incorrecto…)
401 UnauthorizedClave de API ausente o inválida
404 Not FoundUsuario, pago o @alias inexistente
409 Conflict@alias ya registrado por otro usuario
422 Unprocessable EntityPago no procesable (emisor sin @alias, emisor y destino iguales…)