Target discovery
Find a beneficiary's Bre-B key from identity and bank-account data before sending money.
Use target discovery when you know the beneficiary's identity and destination account but do not know their exact Bre-B key. Mono tests a bounded set of keys derived from the data you provide and returns a usable target only when it can confirm the same person, bank, and account.
If you already know the exact key, call Resolve target instead. Discovery is for finding a key from beneficiary data, not for listing every key a person owns.
Testing in sandbox
Use the deterministic 101–104 document suffixes to exercise exact, alternative,
cached-empty, and unavailable outcomes. See target discovery in
sandbox.
Before you start
- Authenticate with OAuth 2.0 client credentials.
- Confirm that Mono has enabled target discovery for your tenant.
- Use
target_discoveriesforPOST /api/v1/targets/discover. - Use either
target_discoveriesortarget_discoveries:readonlyfor the bank catalog GET endpoints. - Have the
tenant_account_idthat will originate the outgoing transfer. It must belong to the authenticated tenant.
See Bre-B Participant authentication for the token flow.
1. Select the canonical bank code
Discovery accepts a three-digit Colombian ACH code in account.bank_code. Do
not derive that code from a bank name yourself. Search the catalog first:
GET /api/v1/banks?q=bancolombia&limit=5An exact ACH code, canonical name, or alias produces a confident match and no
suggestions:
{
"catalog_version": 1,
"match": {
"ach_code": "007",
"name": "BANCOLOMBIA"
},
"data": []
}A partial or approximate query produces suggestions instead:
GET /api/v1/banks?q=davi&limit=5{
"catalog_version": 1,
"match": null,
"data": [
{ "ach_code": "051", "name": "DAVIVIENDA" },
{ "ach_code": "551", "name": "DAVIPLATA" }
]
}Only a non-null match is safe to select automatically. Every item in data
is a suggestion—even when there is only one—so show the choices to the payer
and use the ach_code they select. A search with no results is still 200,
with match: null and data: [].
You can also list the entire catalog or look up an exact code. See List banks and Get bank.
2. Discover the target
Send the beneficiary data you already know. Names, phone, and email are optional hints; identity, bank, and account are required.
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"
}
}See Discover target for every field and enum.
3. Handle the result
Both normal outcomes return 200. Check state; do not treat every 200 as a
discovered target.
state | Meaning |
|---|---|
discovered | target and resolution_id are present. The target matches the requested person, bank, and account. |
not_discovered | target and resolution_id are null. state_reason is no_exact_target; this does not mean the person has no other key. |
Exact target found
{
"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
}
]
}The target is fresh and single-use: pass its id to exactly one outgoing
transfer. Calling discovery again creates another target rather than returning
a cached target.
No exact target found
{
"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 is always present and may be empty. It contains at most five
keys confirmed for the same identity, never data from a different person. It is
not exhaustive: candidates come only from the request data, and discovery stops
at the first exact target. Therefore, a discovered response includes only
same-person keys observed before that first exact target.
An item in same_person_keys is not a target. Before using one:
- Let the payer choose the alternative.
- Call Resolve target
with its
key_valueto obtain a fresh target. - Confirm that the fresh target's
participant_nitand the ending ofcreditor_account.numberstill match the alternative'sparticipant_nitandnumber_last_four. - Ask for confirmation before sending money.
The extra resolution is required because an alternative is not reserved and may point somewhere else later.
Cache behavior
Mono may cache only not_discovered results that have an empty
same_person_keys list, for up to one hour. On such a cache hit,
attempts_count is 0. Results containing a target or an alternative are not
served from cache, so their directory data and IDs come from the current
request.
Send the outgoing transfer
After the payer confirms the resolved beneficiary, create the outgoing transfer with the target ID:
{
"tenant_account_id": "bbtacc_5tgliBmzjZ6mpQPRbQjfKj",
"description": "Confirmed beneficiary payout",
"transfers": [
{
"target_id": "bbtgt_5tgliBmzjZ6mpQPRbQjfKj",
"amount": { "amount": 12000000, "currency": "COP" },
"external_id": "confirmed-transfer-1"
}
]
}See Create outgoing transfers for the complete request. A target can fund only one transfer; use a new discovery or resolution for another payment.
When discovery creates an exact target, the existing
target_resolution_created
and
target_resolution_resolved
webhooks apply. not_discovered results and alternatives do not emit
target-resolution webhooks. Consumers should deduplicate resolution webhooks by
resolution_id; delivery is asynchronous, so a target_resolution_created
event may already carry state=resolved and ordering is not guaranteed. Treat
the latest state and updated_at as authoritative.
Errors and retries
| Status | When it occurs | What to do |
|---|---|---|
400 | The document or account number cannot be compared safely. | Correct the beneficiary data; do not retry unchanged. |
401 | The token is missing, invalid, or expired. | Obtain a valid token and retry. |
403 | The credential lacks the required scope, or discovery is not enabled for the tenant. | Request the scope or contact Mono to enable target discovery. |
404 | The tenant account does not exist or does not belong to the tenant. | Verify tenant_account_id. An unknown exact bank lookup also returns bank_not_found. |
422 | The payload is invalid or bank_code is not accepted (unknown_bank). | Correct the request or select a bank from the public catalog. |
429 | The per-client or per-tenant discovery limit was exceeded (rate_limit_exceeded). | Wait for the Retry-After interval before retrying. |
503 | The Bre-B directory is temporarily unavailable. | Retry after Retry-After when present, using bounded backoff. |
500 | An unexpected server error occurred. | Retry safely; contact support with the response id if it persists. |
A valid search with no exact target is not an HTTP error: it returns 200 with
state=not_discovered.
Related reference
Next steps
- Target discovery in sandbox — exercise the deterministic
101–104scenarios before going live. - Outgoing transfer flow — pay the target you just discovered.
- Bre-B Participant authentication — the scopes and token flow discovery requires.