Mono Colombia

Intents

A single expected payment, declared before the funds arrive.

An intent is one expected payment, declared before the money moves. Where a template says "I accept payments under these rules", an intent says "I am expecting this payment": one payer, one amount, one window of time, one payment token of its own. When the payment arrives, Mono links it back to the intent — so you know exactly which order, invoice, or checkout session was paid, before reading a single payin field.

Use intents when each payment must be pre-identified: e-commerce checkout, invoice payment, or any flow where "who is paying what" matters more than "money arrived".

With or without a template

An intent is created in one of two ways — template_id and subaccount_id are mutually exclusive:

  • From a template — the intent inherits the template's rules (limits, expected payers, payin_data) and can override some for itself. For Bre-B, the template must mint its keys per intent (method_params.co_breb.key_per: "intent"); a template with a shared key cannot link payments back to individual intents.
  • Templateless — the intent is created directly against a subaccount and carries its own configuration. Mono provisions a dedicated single-use payment token for it.

Creation is idempotent on external_id: repeating the request returns the existing intent. When an intent expires, its external_id is freed for a new one — which is what makes the retry loop of a checkout safe.

Amounts

Provide exactly one of merchant_amount or payer_amount; the other is derived. With the only method available today (Bre-B, COP) both amounts are equal — the two fields exist so that cross-currency collection can land later without changing the contract. The amount is enforced: a Bre-B payment for a different amount is rejected (intent_amount_mismatch) and the intent re-arms for a retry.

Lifecycle

  • created — accepted and persisted; the payment token is still being prepared, so payment_tokens is null and the payer cannot pay yet.
  • ready_to_pay — the intent is payable: payment_tokens carries the Bre-B key (and single-use QR, when requested) and expires_at is set. For Bre-B the window is 30 minutes.
  • awaiting_payment — a payment for the intent was authorized and is in flight.
  • successful — the payment was confirmed; the intent is spent, its tokens are torn down, and it can never be paid again.
  • failed — nothing left to pay: the payment token never made it (key_registration_failed, payment_token_registration_failed) or a payment failed on a method that does not re-arm (payment_failed).
  • expired — the window closed with nobody paying. state_reason is expired.

Every reason an intent can end on, and what to do about each, is in Intent errors.

Re-arming: when a payment attempt fails after authorization but the intent is still alive, the intent returns to ready_to_pay — the payer can retry against the same key while the window lasts. The failed attempt itself is reported by the payin's own payin_rejected or payin_failed webhook; the intent emits payin_intent_attempt_failed.

Answering "was this paid?"

GET /v1/core/payins/intents/find_successful_by?external_id=... returns the single successful intent for a tenant-side identifier — at most one exists per client. It lets your reconciliation ask about your own order ID without storing Mono IDs.

Not active yet

  • url is documented as the hosted page where the payer completes the intent. Today it is always null: the hosted checkout is still in development — see Hosted checkout or API-only.
  • calculated_fees is the per-fee-type breakdown of the intent. Today it arrives empty: the fees that would populate it come from the FX conversion legs, and multi-currency collection is not yet available. The fees actually charged appear on the payin.

Data model

The full schema lives in the Intents API reference.

Next steps

On this page