Mono Colombia

Descubrimiento de llaves

Encuentra la llave Bre-B de un beneficiario a partir de su identidad y cuenta bancaria antes de enviar dinero.

Usa el descubrimiento de llaves cuando conoces la identidad del beneficiario y su cuenta destino, pero no su llave Bre-B exacta. Mono prueba un conjunto acotado de llaves derivadas de los datos enviados y solo devuelve una llave utilizable cuando confirma la misma persona, banco y cuenta.

Si ya conoces la llave exacta, llama a Resolver llave. Discovery sirve para encontrar una llave desde los datos del beneficiario, no para listar todas las llaves que posee una persona.

Pruebas en sandbox

Usa los sufijos determinísticos de documento 101–104 para probar los resultados exacto, alternativo, vacío cacheado y no disponible. Consulta descubrimiento de llaves en sandbox.

Antes de empezar

  • Autentícate con OAuth 2.0 client credentials.
  • Confirma que Mono haya habilitado el descubrimiento de llaves para tu tenant.
  • Usa target_discoveries para POST /api/v1/targets/discover.
  • Usa target_discoveries o target_discoveries:readonly para los GET del catálogo bancario.
  • Ten el tenant_account_id que originará la transferencia saliente. Debe pertenecer al tenant autenticado.

Consulta Autenticación de Bre-B Participant para el flujo de tokens.

1. Selecciona el código bancario canónico

Discovery recibe un código ACH colombiano de tres dígitos en account.bank_code. No derives ese código por tu cuenta desde el nombre del banco. Primero busca en el catálogo:

GET /api/v1/banks?q=bancolombia&limit=5

Un código ACH, nombre canónico o alias exacto produce un match confiable y ninguna sugerencia:

{
  "catalog_version": 1,
  "match": {
    "ach_code": "007",
    "name": "BANCOLOMBIA"
  },
  "data": []
}

Una búsqueda parcial o aproximada produce sugerencias:

GET /api/v1/banks?q=davi&limit=5
{
  "catalog_version": 1,
  "match": null,
  "data": [
    { "ach_code": "051", "name": "DAVIVIENDA" },
    { "ach_code": "551", "name": "DAVIPLATA" }
  ]
}

Solo un match no nulo se puede seleccionar automáticamente. Cada elemento de data es una sugerencia —incluso si solo hay uno—, así que muéstrale las opciones al pagador y usa el ach_code que seleccione. Una búsqueda sin resultados también devuelve 200, con match: null y data: [].

También puedes listar el catálogo completo o consultar un código exacto. Ver Listar bancos y Consultar banco.

2. Descubre la llave

Envía los datos que ya conoces del beneficiario. Los nombres, celular y correo son pistas opcionales; la identidad, banco y cuenta son obligatorios.

POST /api/v1/targets/discover
Content-Type: application/json
Authorization: Bearer <access_token>
{
  "tenant_account_id": "bbtacc_5tgliBmzjZ6mpQPRbQjfKj",
  "person": {
    "document_type": "CC",
    "document_number": "1192793827",
    "first_name": "Diego",
    "middle_name": null,
    "first_surname": "Sánchez",
    "second_surname": null,
    "phone": "+573104838791",
    "email": "diego@example.com"
  },
  "account": {
    "bank_code": "013",
    "number": "0013123456789",
    "type": "savings_account"
  }
}

Consulta Descubrir llave para ver todos los campos y enums.

3. Maneja el resultado

Los dos resultados normales devuelven 200. Revisa state; no trates todo 200 como una llave descubierta.

stateSignificado
discoveredtarget y resolution_id están presentes. La llave coincide con la persona, banco y cuenta solicitados.
not_discoveredtarget y resolution_id son null. state_reason es no_exact_target; esto no significa que la persona no tenga otra llave.

Llave exacta encontrada

{
  "state": "discovered",
  "state_reason": null,
  "attempts_count": 2,
  "resolution_id": "bbtgr_5tgliBmzjZ6mpQPRbQjfKj",
  "target": {
    "id": "bbtgt_5tgliBmzjZ6mpQPRbQjfKj",
    "key_type": "identification",
    "key_value": "1192793827",
    "resolution_type": "plain_key",
    "spbvi": "CRB",
    "participant_nit": "860003020",
    "creditor": {
      "type": "natural",
      "document_type": "CC",
      "document_number": "1192793827",
      "full_name": "Diego Sánchez"
    },
    "creditor_account": {
      "type": "savings_account",
      "number": "0013123456789",
      "currency_code": "COP"
    },
    "transaction_amount": null,
    "payment_id": null
  },
  "same_person_keys": [
    {
      "key_type": "alphanumeric",
      "key_value": "@BBVA3104838791",
      "bank_code": "007",
      "participant_nit": "890903938",
      "creditor_account": {
        "type": "savings_account",
        "number_last_four": "4321",
        "currency_code": "COP"
      },
      "resolution_required": true
    }
  ]
}

La llave resuelta es fresca y de un solo uso: pasa su target.id a una sola transferencia saliente. Llamar discovery otra vez crea otra resolución de la llave en lugar de devolver una guardada en cache.

No se encontró una llave exacta

{
  "state": "not_discovered",
  "state_reason": "no_exact_target",
  "attempts_count": 4,
  "resolution_id": null,
  "target": null,
  "same_person_keys": [
    {
      "key_type": "email",
      "key_value": "diego@example.com",
      "bank_code": "007",
      "participant_nit": "890903938",
      "creditor_account": {
        "type": "savings_account",
        "number_last_four": "4321",
        "currency_code": "COP"
      },
      "resolution_required": true
    }
  ]
}

same_person_keys siempre está presente y puede ser []. Contiene máximo cinco llaves confirmadas para la misma identidad y nunca datos de otra persona. No es exhaustivo: las candidatas solo provienen de los datos del request y discovery se detiene en la primera llave exacta. Por eso una respuesta discovered solo incluye llaves de la misma persona observadas antes de esa primera llave exacta.

Un elemento de same_person_keys es una llave alternativa, pero todavía no puede usarse para transferir. Antes de usarlo:

  1. Deja que el pagador elija la alternativa.
  2. Llama a Resolver llave con su key_value para obtener una llave fresca y utilizable.
  3. Confirma que el participant_nit y la terminación de creditor_account.number de la llave recién resuelta todavía coincidan con el participant_nit y number_last_four de la alternativa.
  4. Pide confirmación antes de enviar dinero.

La resolución adicional es obligatoria porque una alternativa no queda reservada y después podría apuntar a otro destino.

Comportamiento del cache

Mono puede cachear por máximo una hora únicamente resultados not_discovered con same_person_keys vacío. En ese cache hit, attempts_count es 0. Los resultados que contienen una llave exacta o una alternativa no se sirven desde cache, por lo que sus datos del directorio e IDs provienen del request actual.

Envía la transferencia saliente

Cuando el pagador confirme al beneficiario resuelto, crea la transferencia saliente con el target.id de la llave:

{
  "tenant_account_id": "bbtacc_5tgliBmzjZ6mpQPRbQjfKj",
  "description": "Pago a beneficiario confirmado",
  "transfers": [
    {
      "target_id": "bbtgt_5tgliBmzjZ6mpQPRbQjfKj",
      "amount": { "amount": 12000000, "currency": "COP" },
      "external_id": "transferencia-confirmada-1"
    }
  ]
}

Consulta Crear transferencias salientes para el request completo. Cada target.id solo puede financiar una transferencia; haz otro discovery o resolución para otro pago.

Cuando discovery crea una llave exacta, aplican los webhooks existentes target_resolution_created y target_resolution_resolved. Los resultados not_discovered y las alternativas no emiten webhooks de resolución. Los consumidores deben deduplicar esos webhooks por resolution_id; la entrega es asíncrona, por lo que un evento target_resolution_created puede traer state=resolved y el orden no está garantizado. Trata el state y updated_at más recientes como autoridad.

Errores y reintentos

EstadoCuándo ocurreQué hacer
400El documento o número de cuenta no se puede comparar de forma segura.Corrige los datos; no reintentes sin cambios.
401Falta el token, es inválido o expiró.Obtén un token válido y reintenta.
403La credencial no tiene el scope requerido o discovery no está habilitado para el tenant.Solicita el scope o contacta a Mono para habilitar el descubrimiento de llaves.
404La cuenta tenant no existe o no pertenece al tenant.Verifica tenant_account_id. Un lookup de banco exacto desconocido también devuelve bank_not_found.
422El payload es inválido o bank_code no es aceptado (unknown_bank).Corrige el request o selecciona un banco del catálogo público.
429Se superó el límite de discovery por cliente o tenant (rate_limit_exceeded).Espera el intervalo Retry-After antes de reintentar.
503El directorio Bre-B no está disponible temporalmente.Reintenta después de Retry-After, cuando esté presente, con backoff acotado.
500Ocurrió un error inesperado del servidor.Reintenta de forma segura; contacta a soporte con el id de la respuesta si persiste.

Una búsqueda válida sin llave exacta no es un error HTTP: devuelve 200 con state=not_discovered.

Referencia relacionada

Siguientes pasos

En esta página