Authenticate
Exchange API credentials for a short-lived Bearer token (~20 minutes). Reuse the same token string on every later call in this flow.
| Content-Type | application/json |
{ "user_id": "cli_demo_co_payin01",User IDiAPI user id issued by Cobre (cli_…). "secret": "sk_live_2Hg8nP4qR7"SecretiAPI secret from key creation — treat like a password.}{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfZGVtb19jb19wYXlpbjAxIn0.R2pP9xK2vN7cL4wT8aH1gF6yJ0bZ5eQ",Access TokeniShort-lived bearer token. Attach as Authorization: Bearer on later calls. "type": "Bearer",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins). "expiration_time": 1200Expiration TimeiToken lifetime in seconds.}Subscribe to Payin Events
Register webhooks for Money Movement payin status and Cobre Balance credits. Direct Link creates a Money Movement — subscribe to both MM events and accounts.balance.credit (r2p_credit on completion). Verify deliveries with HMAC-SHA256.
| Authorization | Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfZGVtb19jb19wYXlpbjAxIn0.R2pP9xK2vN7cL4wT8aH1gF6yJ0bZ5eQ |
| Content-Type | application/json |
{ "url": "https://yourplatform.co/webhooks/cobre",Notification URLiHTTPS endpoint that receives Cobre POST notifications. "description": "Direct Link payin lifecycle",DescriptioniLabel for this subscription in the Cobre portal. "events": [EventsiList of webhook event types this subscription listens to. "money_movements.status.initiated", "money_movements.status.processing", "money_movements.status.completed", "money_movements.status.failed", "money_movements.status.rejected", "accounts.balance.credit" ], "event_signature_key": "WHr2pCo9xZ"Signature keyiSecret you provide; Cobre HMAC-signs each delivery.}{ "id": "sub_R2pPayin01",IdiUnique Cobre identifier for this resource. "url": "https://yourplatform.co/webhooks/cobre",Notification URLiHTTPS endpoint that receives Cobre POST notifications. "description": "Direct Link payin lifecycle",DescriptioniLabel for this subscription in the Cobre portal. "events": [EventsiList of webhook event types this subscription listens to. "money_movements.status.initiated", "money_movements.status.processing", "money_movements.status.completed", "money_movements.status.failed", "money_movements.status.rejected", "accounts.balance.credit" ], "event_signature_key": "******9xZ",Signature keyiSecret you provide; Cobre HMAC-signs each delivery. "created_at": "2026-07-02T10:00:00Z"Created AtiTimestamp when the resource was created (ISO 8601, UTC).}Register the Payer (r2p Counterparty)
Direct Link payins require an r2p counterparty representing the payer. Register once per customer — the same cp_… can be reused across sessions. Email and phone are required for PSE and other rails.
| Authorization | Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfZGVtb19jb19wYXlpbjAxIn0.R2pP9xK2vN7cL4wT8aH1gF6yJ0bZ5eQ |
| Content-Type | application/json |
{ "geo": "col",Geographyicol = Colombia. "type": "r2p",Typeir2p = Direct Link payer (PSE, Nequi, Bancolombia, Bre-B QR). "alias": "PSE payer - payin_ref_001",AliasiDisplay name that helps identify it and clarify its purpose. "metadata": {MetadataiCustom key-value metadata attached to the resource. "counterparty_fullname": "Juliana Restrepo",Full nameiPayer's full legal name. "counterparty_email": "payer@example.co",EmailiRequired for PSE bank-authentication redirect — must be valid. "counterparty_id_type": "cc",ID typeiColombian identification type. "counterparty_id_number": "5334623427",ID numberiPayer identification number. "counterparty_phone": "+573123927834"PhoneiPayer phone with country code (e.g. +57…). }}{ "id": "cp_PayerR2P001",IdiUnique Cobre identifier for this resource. "geo": "col",Geographyicol = Colombia. "type": "r2p",Typeir2p = Direct Link payer (PSE, Nequi, Bancolombia, Bre-B QR). "alias": "PSE payer - payin_ref_001",AliasiDisplay name that helps identify it and clarify its purpose. "metadata": {MetadataiCustom key-value metadata attached to the resource. "counterparty_email": "payer@example.co",EmailiRequired for PSE bank-authentication redirect — must be valid. "counterparty_fullname": "Juliana Restrepo",Full nameiPayer's full legal name. "counterparty_id_number": "5334623427",ID numberiPayer identification number. "counterparty_id_type": "cc",ID typeiColombian identification type. "counterparty_phone": "+573123927834"PhoneiPayer phone with country code (e.g. +57…). }, "created_at": "2026-07-02T10:05:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "updated_at": "2026-07-02T10:05:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).}Collect via PSE (Direct Link)
Create a Direct Link Money Movement: source = r2p payer counterparty, destination = your COP Cobre Balance. Set metadata.r2p_rail to pse and redirect the customer to metadata.payment_link from the response. Amount is integer cents (500000 = COP 5,000.00). Reuse idempotency on retries — valid 24h.
| Authorization | Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfZGVtb19jb19wYXlpbjAxIn0.R2pP9xK2vN7cL4wT8aH1gF6yJ0bZ5eQ |
| Content-Type | application/json |
| idempotency | payin-pse-001 |
{ "amount": 500000,Amount (cents)i500000 cents = COP 5,000.00. "source_id": "cp_PayerR2P001",Payer counterpartyicp_… of the registered r2p payer. "destination_id": "acc_FundingCOP01",Destination balanceiYour COP Cobre Balance that receives the payin. "metadata": {MetadataiCustom key-value metadata attached to the resource. "r2p_rail": "pse",R2P railipse for this demo — other Direct Link rails use the same pattern. "financial_institution_code": "1070",Payer bank (PSE code)iPSE financial-institution code for the payer's bank. "description_to_payer": "Platform payin",Description To PayeriCobre field at "metadata.description_to_payer" in this payload. "description_to_payee": "Platform payin",Description To PayeeiCobre field at "metadata.description_to_payee" in this payload. "redirect_url": "https://yourplatform.co/payin/return"Return URLiWhere to send the customer after PSE authentication. }, "external_id": "payin_ref_001"External IDiYour payin reference — primary reconciliation join key.}{ "id": "mm_PsePayin001",IdiUnique Cobre identifier for this resource. "status": {StatusiLifecycle status object for the resource or movement. "state": "initiated",StateiCurrent lifecycle state (e.g. completed, failed, rejected). "code": "",CodeiProvider or Cobre status code when the state is failed or rejected. "description": ""DescriptioniHuman-readable detail for the current status. }, "metadata": {MetadataiCustom key-value metadata attached to the resource. "financial_institution_code": "1070",Payer bank (PSE code)iPSE financial-institution code for the payer's bank. "payment_link": "https://registro.pse.com.co/PSENF/index.html?enc=r2pdemo001",Payment LinkiCobre field at "metadata.payment_link" in this payload. "description_to_payee": "Platform payin",Description To PayeeiCobre field at "metadata.description_to_payee" in this payload. "description_to_payer": "Platform payin",Description To PayeriCobre field at "metadata.description_to_payer" in this payload. "r2p_rail": "pse",R2P railipse for this demo — other Direct Link rails use the same pattern. "redirect_url": "https://yourplatform.co/payin/return"Return URLiWhere to send the customer after PSE authentication. }, "creator": "cli_demo_co_payin01",CreatoriAPI client id that created this resource. "external_id": "payin_ref_001",External IDiYour payin reference — primary reconciliation join key. "checker_approval": false,Checker ApprovaliWhen true, Cobre pauses at pending_approval and locks source funds until an approval/denial decision via Money Movement Approvals API. "mm_approval_id": "",Mm Approval IdiMoney Movement Approval id (mma_…) when checker_approval is true — used for the decision endpoint. "type": "r2p_pse",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins). "geo": "col",GeoiGeography code (e.g. col = Colombia, mex = Mexico). "source_id": "cp_PayerR2P001",Payer counterpartyicp_… of the registered r2p payer. "destination_id": "acc_FundingCOP01",Destination balanceiYour COP Cobre Balance that receives the payin. "currency": "cop",CurrencyiISO currency code (e.g. cop, mxn). "amount": 500000,Amount (cents)i500000 cents = COP 5,000.00. "created_at": "2026-07-02T10:10:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "updated_at": "2026-07-02T10:10:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).}Webhook outcomes — Money movement
After the payer completes PSE authentication and funds settle, Cobre delivers this webhook. Mark the payin as received using external_id. Cobre also credits your Cobre Balance (r2p_credit) — see the Transaction tab.
Handle each terminal state in your webhook listener. Status codes reference the <a href="https://docs.cobre.com/money-movement-statuses-2032280m0" target="_blank" rel="noopener">Money Movement Statuses</a> guide. Cobre Balance transactions are covered in the <b>Transaction</b> tab.
Funds settled successfully. No error code is set (NA in the status guide). Use this webhook to mark the payment as paid in your system.
money_movements.status.completed| Content-Type | application/json |
{ "id": "ev_PsePayin001Cmp",IdiUnique Cobre identifier for this resource. "event_key": "money_movements.status.completed",Event KeyiWebhook subscription key (e.g. money_movements.status.completed). "created_at": "2026-07-02T10:15:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "content": {ContentiEvent-specific payload — same layout as the GET response for that resource. "id": "mm_PsePayin001",IdiUnique Cobre identifier for this resource. "status": {StatusiLifecycle status object for the resource or movement. "state": "completed",StateiCurrent lifecycle state (e.g. completed, failed, rejected). "code": "",CodeiProvider or Cobre status code when the state is failed or rejected. "description": ""DescriptioniHuman-readable label or note. }, "metadata": {MetadataiCustom key-value metadata attached to the resource. "financial_institution_code": "1070",Financial Institution CodeiMetadata field "financial_institution_code" attached to the resource. "payment_link": "https://registro.pse.com.co/PSENF/index.html?enc=r2pdemo001",Payment LinkiMetadata field "payment_link" attached to the resource. "description_to_payee": "Platform payin",Description To PayeeiMetadata field "description_to_payee" attached to the resource. "description_to_payer": "Platform payin",Description To PayeriMetadata field "description_to_payer" attached to the resource. "r2p_rail": "pse",R2p RailiMetadata field "r2p_rail" attached to the resource. "redirect_url": "https://yourplatform.co/payin/return"Redirect UrliMetadata field "redirect_url" attached to the resource. }, "creator": "cli_demo_co_payin01",CreatoriAPI client id that created this resource. "external_id": "payin_ref_001",External IdiYour own reference echoed by Cobre for reconciliation. "checker_approval": false,Checker ApprovaliWhen true, Cobre pauses at pending_approval and locks source funds until an approval/denial decision via Money Movement Approvals API. "mm_approval_id": "",Mm Approval IdiMoney Movement Approval id (mma_…) when checker_approval is true — used for the decision endpoint. "type": "r2p_pse",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins). "geo": "col",GeoiGeography code (e.g. col = Colombia, mex = Mexico). "source_id": "cp_PayerR2P001",Source IdiCobre id of the source account or counterparty. "destination_id": "acc_FundingCOP01",Destination IdiCobre id of the destination account or counterparty. "currency": "cop",CurrencyiISO currency code (e.g. cop, mxn). "amount": 500000,AmountiAmount in cents — the last two digits are decimals. "created_at": "2026-07-02T10:10:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "updated_at": "2026-07-02T10:15:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC). }}Cobre or the rail could not process the movement. Inspect status.code and status.description — common failed codes include:
F001 | Payment processing failed — please try again. |
F002 | NSF — not sufficient funds in the designated account. |
F003 | R2P payment link expired (payins). |
F004 | Daily transaction amount limit has been reached. |
F005 | Amount exceeds the maximum allowed transaction limit. |
F098 | Could not process the money movement at this time. |
F099 | Could not process the money movement at this time. |
money_movements.status.failed| Content-Type | application/json |
{ "id": "ev_PsePayin001Cmp",IdiUnique Cobre identifier for this resource. "event_key": "money_movements.status.failed",Event KeyiWebhook subscription key (e.g. money_movements.status.completed). "created_at": "2026-07-02T10:15:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "content": {ContentiEvent-specific payload — same layout as the GET response for that resource. "id": "mm_PsePayin001",IdiUnique Cobre identifier for this resource. "status": {StatusiLifecycle status object for the resource or movement. "state": "failed",StateiCurrent lifecycle state (e.g. completed, failed, rejected). "code": "F002",CodeiProvider or Cobre status code when the state is failed or rejected. "description": "NSF — not sufficient funds in the designated account."DescriptioniHuman-readable label or note. }, "metadata": {MetadataiCustom key-value metadata attached to the resource. "financial_institution_code": "1070",Financial Institution CodeiMetadata field "financial_institution_code" attached to the resource. "payment_link": "https://registro.pse.com.co/PSENF/index.html?enc=r2pdemo001",Payment LinkiMetadata field "payment_link" attached to the resource. "description_to_payee": "Platform payin",Description To PayeeiMetadata field "description_to_payee" attached to the resource. "description_to_payer": "Platform payin",Description To PayeriMetadata field "description_to_payer" attached to the resource. "r2p_rail": "pse",R2p RailiMetadata field "r2p_rail" attached to the resource. "redirect_url": "https://yourplatform.co/payin/return"Redirect UrliMetadata field "redirect_url" attached to the resource. }, "creator": "cli_demo_co_payin01",CreatoriAPI client id that created this resource. "external_id": "payin_ref_001",External IdiYour own reference echoed by Cobre for reconciliation. "checker_approval": false,Checker ApprovaliWhen true, Cobre pauses at pending_approval and locks source funds until an approval/denial decision via Money Movement Approvals API. "mm_approval_id": "",Mm Approval IdiMoney Movement Approval id (mma_…) when checker_approval is true — used for the decision endpoint. "type": "r2p_pse",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins). "geo": "col",GeoiGeography code (e.g. col = Colombia, mex = Mexico). "source_id": "cp_PayerR2P001",Source IdiCobre id of the source account or counterparty. "destination_id": "acc_FundingCOP01",Destination IdiCobre id of the destination account or counterparty. "currency": "cop",CurrencyiISO currency code (e.g. cop, mxn). "amount": 500000,AmountiAmount in cents — the last two digits are decimals. "created_at": "2026-07-02T10:10:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "updated_at": "2026-07-02T10:15:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC). }}The bank or payment network rejected the transaction. Inspect status.code — common rejected codes include:
R000 | Transaction rejected. |
R001 | Inactive or blocked account. |
R002 | Account and identification provided do not coincide. |
R005 | Account does not exist. |
R006 | Invalid account number. |
R009 | Exceeds maximum allowed amount. |
R018 | Payment rejected due to invalid key (payouts). |
R023 | Payment cancelled by the user. |
R026 | Payment rejected due to unavailable bank services. |
R034 | Account closed. |
R085 | Bank processing error (payouts). |
money_movements.status.rejected| Content-Type | application/json |
{ "id": "ev_PsePayin001Cmp",IdiUnique Cobre identifier for this resource. "event_key": "money_movements.status.rejected",Event KeyiWebhook subscription key (e.g. money_movements.status.completed). "created_at": "2026-07-02T10:15:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "content": {ContentiEvent-specific payload — same layout as the GET response for that resource. "id": "mm_PsePayin001",IdiUnique Cobre identifier for this resource. "status": {StatusiLifecycle status object for the resource or movement. "state": "rejected",StateiCurrent lifecycle state (e.g. completed, failed, rejected). "code": "R001",CodeiProvider or Cobre status code when the state is failed or rejected. "description": "Inactive or blocked account."DescriptioniHuman-readable label or note. }, "metadata": {MetadataiCustom key-value metadata attached to the resource. "financial_institution_code": "1070",Financial Institution CodeiMetadata field "financial_institution_code" attached to the resource. "payment_link": "https://registro.pse.com.co/PSENF/index.html?enc=r2pdemo001",Payment LinkiMetadata field "payment_link" attached to the resource. "description_to_payee": "Platform payin",Description To PayeeiMetadata field "description_to_payee" attached to the resource. "description_to_payer": "Platform payin",Description To PayeriMetadata field "description_to_payer" attached to the resource. "r2p_rail": "pse",R2p RailiMetadata field "r2p_rail" attached to the resource. "redirect_url": "https://yourplatform.co/payin/return"Redirect UrliMetadata field "redirect_url" attached to the resource. }, "creator": "cli_demo_co_payin01",CreatoriAPI client id that created this resource. "external_id": "payin_ref_001",External IdiYour own reference echoed by Cobre for reconciliation. "checker_approval": false,Checker ApprovaliWhen true, Cobre pauses at pending_approval and locks source funds until an approval/denial decision via Money Movement Approvals API. "mm_approval_id": "",Mm Approval IdiMoney Movement Approval id (mma_…) when checker_approval is true — used for the decision endpoint. "type": "r2p_pse",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins). "geo": "col",GeoiGeography code (e.g. col = Colombia, mex = Mexico). "source_id": "cp_PayerR2P001",Source IdiCobre id of the source account or counterparty. "destination_id": "acc_FundingCOP01",Destination IdiCobre id of the destination account or counterparty. "currency": "cop",CurrencyiISO currency code (e.g. cop, mxn). "amount": 500000,AmountiAmount in cents — the last two digits are decimals. "created_at": "2026-07-02T10:10:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "updated_at": "2026-07-02T10:15:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC). }}When a payin Money Movement completes, Cobre credits the destination Cobre Balance and delivers accounts.balance.credit. Transaction type matches the movement type — see GET /accounts/{id}/transactions OAS examples.
When the payin settles, Cobre credits the destination Cobre Balance.
accounts.balance.credit| Content-Type | application/json |
{ "id": "ev_PsePayin00Cr",IdiUnique Cobre identifier for this resource. "event_key": "accounts.balance.credit",Event KeyiWebhook subscription key (e.g. money_movements.status.completed). "created_at": "2026-07-02T10:15:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "content": {ContentiEvent-specific payload — same layout as the GET response for that resource. "id": "trx_PsePayin001Cr",IdiUnique Cobre identifier for this resource. "type": "r2p_credit",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins). "account_id": "acc_FundingCOP01",Account IdiCobre Balance account id affected by the event. "amount": 500000,AmountiAmount in cents — the last two digits are decimals. "previous_balance": 0,Previous BalanceiCobre field at "content.previous_balance" in this payload. "current_balance": 500000,Current BalanceiCobre field at "content.current_balance" in this payload. "currency": "COP",CurrencyiISO currency code (e.g. cop, mxn). "credit_debit_type": "credit",Credit Debit Typeicredit = funds in; debit = funds out. "transaction_date": "2026-07-02T10:15:00Z",Transaction DateiTimestamp when the transaction was posted (ISO 8601, UTC). "created_at": "2026-07-02T10:15:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC). "metadata": {MetadataiCustom key-value metadata attached to the resource. "sender_bank_code": "1070",Sender Bank CodeiMetadata field "sender_bank_code" attached to the resource. "money_movement_id": "mm_PsePayin001",Money Movement IdiMoney Movement that generated this balance transaction. "description": "Platform payin",DescriptioniHuman-readable label or note. "sender_name": "",Sender NameiMetadata field "sender_name" attached to the resource. "r2p_method": "pse",R2p MethodiR2P channel for r2p_credit transactions (e.g. pse). "tracking_key": "",Tracking KeyiBre-B tracking key for the payment. "sender_id": ""Sender IdiMetadata field "sender_id" attached to the resource. } }}Reconcile the Direct Link Payin
Match the completion webhook to your platform ledger on external_id and mm_id. Cross-check the COP balance credit (r2p_credit) via GET /accounts/{acct_id}/transactions. For D+1 close, export payins with POST /reports.
Mapping the webhook payload from an earlier step onto Platform ledger. No API call is made — this step closes the loop in your own system.
| Cobre field & value | Platform ledger field | |
content.external_id payin_ref_001 |
→ | payin_reference Primary join key — your payin or order id. |
content.id mm_PsePayin001 |
→ | cobre_mm_id |
content.amount 500000 |
→ | received_amount_cents |
content.status.state completed |
→ | payin_status Map completed → RECEIVED; failed/rejected → review or retry. |
content.metadata.r2p_rail pse |
→ | payin_rail |