Cómo hacer una transferencia a una llave


En esta guía, aprenderás cómo iniciar una intent de dispersión a través de Bre-B usando Kamin Ledger. Una vez configurado tu entorno, el proceso consta de dos pasos simples, la resolución de la llave y la creación de la intent. Es importante tener en cuenta que las transacciones en Bre-B son de cuenta a cuenta, las llaves son un alias de facil recordación las cuales tienen asociadas una cuenta bancaria y la información de la identidad del dueño de la llave


Requisitos previos

Antes de comenzar:

  • Has resuleto una llave de Bre-B, la llave puede ser tipo:
    • Documento de identidad
    • Número de celular
    • Corre electrónico
    • Alfanúmerica
  • Puedes usar alguan de estas llaves de prueba
  • Tienes un par de llaves válidas para firmar las transacciones.
  • Has leído la guía de Primeros pasos y tienes configurados tu Wallet, Dominio y Autenticación.

Flujo


Objetivo

Envía fondos a un destinatario usando Bre-B mediante la resolución de la llave.


Paso 1: Obtener la dirección de destino

Para resolver una llave en Bre-B debes usar el flujo de Resolución de Llaves. Esta resolucíon devolver la informacion del destinatario, la cual contiene tanto la informacion de la cuenta, como la información de la identidad del dueño de la llave, por ejemplo:

Tenemos la llave @kaminTestKey

GET <baseURL>/v2/anchors/{@kaminTestKey};

Respuesta:

{
  "data": {
    "handle": "wcDHYmSJP8uJF5dVGXBEKNA3e5hBm1eQEn",
    "wallet": "breb",
    "target": "signer:wcDHYmSJP8uJF5dVGXBEKNA3e5hBm1eQEn@breb",
    "schema": "breb",
    "custom": {
      "bankId": "901830825",
      "status": "ACTIVE",
      "firstName": "Alphanum",
      "lastName": "Key",
      "keyType": "ALPHANUM",
      "keyValue": "@kaminTestKey",
      "idType": "CC",
      "idValue": "1088432333",
      "bankAccountType": "SVGS",
      "bankAccountNumber": "000202020"
    },
    "access": [
      {...}
    ]
  },
  "hash": "52bf5317248ca9d59d71c7d023803be40a9ae4168c8c3cf979423187f21ec548",
  "meta": {
    "proofs": [...]
  }
}

De la respuesta se obtiene todo lo necesario para validar los datos del destinatario y para generar la transfrencia de fondos, en este caso, el campo data.target contiene la información de la cuenta destino, la cual debe ser usada en el campo target del Intent. Por otro lado toda la data del usuario esta contenida en el objeto data.custom y puede ser usada para validar los datos del destinatario.

Es importante no hacer ningun tipo de validacion sobre este campo data.target ya que puede cambiar en el futuro.

Una vez obtenido el destino, se puede proceder a crear el intent de dispersión.


Paso 2: Crear el intent de dispersión

Puedes usar el SDK del ledger, la CLI o código para enviar una intent de transferencia de dinero. El ejemplo proporcionado primero resuelve el destino usando Get Anchor, luego procede a crear la intent SEND.

El origen es de donde se debitarán los fondos, en este caso, tu billetera, y el destino es la cuenta del usuario en registrado en Bre-B.

Definición de campos

NombreTipoDescripción
handle*String (64)Identificador unico del intent, usado para garantizar idempotencia
source.handle*String (64)Billetera origen de la transferencia. En una intent SEND, el origen es tu billetera
target.handle*String (64)Billetera destino. En una intent SEND, el destino es el el data.target obtenido en la resolución de la llave
amount*integerMonto de la transferencia
symbol.handle*String (16)Moneda.
Por defecto bcop
custom.received*String (255)String de una fecha en formato ISO 8601 que representa el instante en que se genero la solicitud

Ejemplo de solicitud

Hashea, firma y envía al endpoint Create Intent. Consulta Hashing y firmado de solicitudes para detalles.

POST https://<ledger-url>/api/v2/intents
Accept: application/json, text/plain, */*
Content-Type: application/json
x-ledger: <ledger-handle>
{
    "data": {
        "handle": "<unique-intent-id>",
        "claims": [
            {
                "action": "transfer",
                "source": { "handle": "<source-wallet-handle>" },
                "target": { "handle": "<target-breb-key-handle>" },
                "symbol": { "handle": "bcop" },
                "amount": <amount-in-cents>
            }
        ],
        "schema": "transfer",
        "access": [
            { "action": "any", "signer": { "public": "<public-key>" } }
        ],
        "custom": {
            "received": "<iso-8601-timestamp>"
        }
    },
    "hash": "<sha256-hash-of-data>",
    "meta": {
        "proofs": [
            {
                "method": "ed25519-v2",
                "public": "<public-key>",
                "digest": "<digest-del-proof>",
                "result": "<signature-of-digest>",
                "custom": { "moment": "<iso-8601-timestamp>" }
            }
        ]
    }
}

Todas las solicitudes de mutación (como POST) deben ser firmadas con tu llave privada.

El monto enviado fue COP 1000 debido al factor de 100 que tiene el símbolo bcop

Cuerpo de la respuesta:

{
    "hash": "559a7324f3f5f01a9ce23e1f1e8a6f06c68ccd4c510ecc3a025deafee781d85c",
    "data": {
        "handle": "cvS7ioG5k9U65GosbwDsy",
        "claims": [
            {
                "action": "transfer",
                "amount": 100000,
                "source": {
                    "handle": "kamin.one"
                },
                "symbol": {
                    "handle": "bcop"
                },
                "target": {
                    "handle": "signer:wbX9V3UnXie7zz6wSpKkZHUrdjA31rowcp@brebe"
                }
            }
        ],
        "schema": "transfer",
        "custom": {
            "received": "2025-10-10T11:59:22.241-05:00"
        },
        "access": [
            {
                "action": "any",
                "signer": {
                    "public": "Oh3xliLHnYelAZbQyTEZv5jo3JNrsBiea+/6X6AxUK0="
                }
            }
        ]
    },
    "luid": "$int.-0XJXjBbpzYN67lwM",
    "meta": {
        "proofs": [
            {
                "custom": {
                    "moment": "2025-06-17T19:09:33.299Z",
                    "status": "created"
                },
                "digest": "804c90a2b9c053976040791c7efdd7ee0b59fe1463091db68c99aa67e4912227",
                "method": "ed25519-v2",
                "public": "Oh3xliLHnYelAZbQyTEZv5jo3JNrsBiea+/6X6AxUK0=",
                "result": "d5KZ647Gqkv85H6pqe132Hy2jprDKIWEhCjgrJTXr393Ku9OxI8yrmzfzO8YstiF5JrJOUNCXiZGQ1DDy8YMDA=="
            },
            {
                "custom": {
                    "moment": "2025-06-17T19:09:33.878Z",
                    "status": "pending"
                },
                "digest": "3bf7894bf40967ef7c677b04118a9b7d34557c7152c84ac9fe752e4ff0038456",
                "method": "ed25519-v2",
                "public": "aSRs/3ni0v/zcLSQetGDAy1DunN9VcBPoeUK+UyzOJA=",
                "result": "Fb15jWB2PQ6Z+QgDDXZoWwsG3H4WodMRxvNW6lldEfi56Vd11QRCHcNwt8D1QSOE7zuEkcVC4XISFX9/vw5ADQ=="
            },
            {
                "custom": {
                    "luid": "$int.-0XJXjBbpzYN67lwM",
                    "moment": "2025-06-17T19:09:33.898Z",
                    "status": "pending"
                },
                "digest": "31c0ba4d36ce86f89c095830b4282d000f63a0a0b9641f0e1b290c89b733a831",
                "method": "ed25519-v2",
                "public": "aSRs/3ni0v/zcLSQetGDAy1DunN9VcBPoeUK+UyzOJA=",
                "result": "4tfeYwp/d26g2MwBhPDoPOjZ6HD4dMrZyAighIfZvn3j/FfRWuTk/jDYgft4yPZnW1FqgcMsalhSLGt+VgdKBw=="
            }
        ],
        "status": "pending",
        "thread": "-0XJXjh6_AjFUGHNz",
        "moment": "2025-06-17T19:09:33.877Z",
        "owners": ["Oh3xliLHnYelAZbQyTEZv5jo3JNrsBiea+/6X6AxUK0="]
    }
}

Al recibir el 200 OK en la creación del intent este procedera a ser procesado por el nodo de Bre-B y tendrá un máximo de 20 segundos para quedar en un estado final desde la solicitud de la creación, la fecha del campo received


Verificación de la Transacción


Validación de la información del destino

Después de que el intent alcanza su estado de completado, la información del destino se almacena como una proof dentro del intent.
Esto permite que el negocio realice verificaciones o validaciones futuras en sus procesos internos.
La información queda almacenada y puede ser consultada en cualquier momento, ya sea a través del webhook o realizando una
llamada GET al intent.

{
    "custom": {
        "moment": "2026-01-27T15:15:29.023Z",
        "snapshot": {
            "idType": "CC",
            "idValue": "1088432333",
            "bankName": "bancoRojo",
            "lastName": "Key",
            "firstName": "Alphanum"
        }
    },
    "digest": "4163df852128ab47e39f5d4504ded8dfdcdf39f3985073e3eaaddd6a0591ef39",
    "method": "ed25519-v2",
    "public": "oNlpTnHtyTNkpdWxZ2a0twcUmziYgGCNUEqHNEQXsA0=",
    "result": "MEMIDv4DMw9D4ewsufftEHyhxGdWtEISWc5PUbljmYKxt4Z/X1jevcL8bEj6eYMB4AWYuU3S8SaGLGYDXHg1Bw=="
},
{
    "custom": {
        "moment": "2026-01-24T13:32:21.763Z",
        "status": "committed"
    }, {...}

},
{
    "custom": {
        "moment": "2026-01-24T13:32:22.213Z",
        "status": "completed"
    }, {...}

}

Esta proof aparece antes de la proof con estado completed y antes de la proof final committed.

Actualmente, el campo bankName no devuelve el nombre correcto del banco debido a una limitación del nodo. Estamos trabajando con el equipo del nodo para resolverlo. En la mayoría de los casos, el valor se devolverá como BanRep.


¿Qué sigue?

Una vez que tu transferencia ha sido enviada, puedes:

  • Monitorear el estado de la intent para confirmar su entrega
  • Notificar al usuario cuando el pago se haya completado o fallado
  • Registrar o conciliar la transacción en tu sistema interno

Historial de cambios
1.2.2
  • Corregido Se corrigieron enlaces que llevaban a la versión en español
1.2.1
  • Agregado Se agregó el ejemplo de la solicitud HTTP cruda (endpoint, headers y cuerpo JSON) junto a los ejemplos en TypeScript, SDK y CLI.
1.2.0
  • Cambiado Se actualizó el símbolo del rail BREB de `cop` a `bcop`.
1.1.0
  • Agregado Se agrego la sección de Validación de la información del destino
1.0.1
  • Corregido Se le agregó .handle a los campos source, target y symbol en la tabla de definición de campos
1.0.0
  • Agregado Versión inicial