Mono Colombia

Payment tokens

What the payer pays to — each method issues its own kind of token.

A payment token is the thing you put in front of the payer: the address the money is sent to. Each payment method defines its own kind of token — and some methods need none at all, because the payer is sent to the provider's own flow instead of paying to an address. That is why payment_tokens is a per-method map: one entry per accepted method that issues a token, and no entry for methods that do not.

Today, with Bre-B as the only live method, tokens come in two forms: a key (in Colombia, a llave: a short alias like a cellphone number or a code, registered in the Bre-B directory) and an optional QR code that encodes the same destination so the payer can scan instead of type.

Templates and intents both carry tokens, and the difference between them is the difference between a poster on a wall and a ticket with your name on it: a template's token is shared by every payer; an intent's token identifies one expected payment.

The Bre-B token

payment_tokens.co_breb has three parts:

FieldWhat it is
key_typeThe kind of key: cellphone, email, alphanumeric, identification, or merchant_code. Assigned by the network when the key is registered — it is not known at creation time.
key_valueThe key itself — what the payer enters in their bank's app to address the transfer.
qrThe QR generated for the key, when one was requested (create_qr: true).

The QR object carries everything needed to display or embed it: the EMV payload in plain text (emvco), a rendered image in base64 (image, with image_width and error_correction_level), the provider's payment_id, its usage_mode, and — for dynamic QRs — the fixed amount and expires_at.

You can request a custom key alias with method_params.co_breb.custom_key_value, and override the QR's merchant data (merchant_category_code, receiver_city, receiver_postal_code) with qr_code_data. If omitted, Mono generates the key and uses your program's configuration.

Key per template or key per intent

method_params.co_breb.key_per decides at which level the Bre-B key is minted, and it shapes the whole collection model:

key_perToken lives onQR kindPayments are…
template (default)The templateStatic — multiple use, no amountAnonymous until they arrive: any payer, any number of payments.
intentEach intentDynamic — single use, fixed amount, expiresReferenced: each payment maps back to the intent that expected it.

A template with key_per: "template" receives payments directly — it cannot host intents, because a shared key cannot tell which intent a payment belongs to. A template with key_per: "intent" has no key of its own (payment_tokens stays null): every key is minted when an intent is created. A templateless intent gets its own dedicated key too.

Token setup is asynchronous

Registering a token with the method's network takes a callback round-trip, which is why templates and intents are born in created — neither is payable until the token is confirmed:

  • The template moves to ready and fills payment_tokens when every pending token is confirmed — announced by payin_template_ready.
  • The intent moves to ready_to_pay and fills payment_tokens — announced by payin_intent_ready_to_pay.

If registration exhausts its retries, the template ends failed (key_registration_failed, key_already_registered) or the intent ends failed (key_registration_failed, payment_token_registration_failed).

Tokens are torn down

A token only lives while its owner can be paid. When a template is pruned or deleted, or an intent reaches a final state (successful, failed, or expired), Mono deregisters its tokens with the method's provider. The owner's prune_state / prune_reason fields track that teardown.

Next steps

  • Bre-B — the rail behind the keys and QRs.
  • Templates — where static tokens live.
  • Intents — where dynamic tokens live.

On this page