Step 1 of 11 Configuration API step

Authenticate

Exchange API credentials for a short-lived Bearer token (~20 minutes). Every later call in this flow reuses the same token string.

POST https://api.cobre.co/v1/auth
Headers
Content-Typeapplication/json
Request body
{
"user_id": "cli_mex_trust_lender_01",User IDRequirediAPI user id issued by Cobre (cli_…).
"secret": "sk_live_Tr5jN8wS3q"SecretRequirediAPI secret from key creation — never log or expose client-side.
}
Response 201
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT",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.
}
Documentation for this step
AuthenticationAuthentication Guide
Step 2 of 11 Configuration API step

Subscribe to Disbursement Events

Register your HTTPS listener for Money Movement lifecycle events and balance debits — the same subscription covers disbursements from either funding source. Prefer webhooks over polling; verify each delivery with HMAC-SHA256 using event-timestamp and event-signature.

POST https://api.cobre.co/v1/subscriptions
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Content-Typeapplication/json
Request body
{
"url": "https://trustlender.example.mx/webhooks/cobre",Notification URLRequirediYour backend endpoint that receives Cobre POST notifications.
"description": "Dual-source SPEI disbursement 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",
"money_movements.status.returned",
"accounts.balance.debit"
],
"event_signature_key": "WHmxTrust7pQ"Signature keyRequirediSecret you provide; Cobre HMAC-signs payloads for verification.
}
Response 201
{
"id": "sub_MxTrust01",IdiUnique Cobre identifier for this resource.
"url": "https://trustlender.example.mx/webhooks/cobre",Notification URLRequirediYour backend endpoint that receives Cobre POST notifications.
"description": "Dual-source SPEI disbursement 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",
"money_movements.status.returned",
"accounts.balance.debit"
],
"event_signature_key": "******7pQ",Signature keyRequirediSecret you provide; Cobre HMAC-signs payloads for verification.
"created_at": "2026-08-01T10:00:00Z"Created AtiTimestamp when the resource was created (ISO 8601, UTC).
}
Step 3 of 11 Account Verification API step

Verify CLABE Ownership

Before disbursing, confirm the borrower's 18-digit CLABE matches the declared RFC via mex_acc_ownership_1. The create call returns processing — never treat processing as authorization to pay.

POST https://api.cobre.co/v1/account_verifications
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Content-Typeapplication/json
Request body
{
"model": "mex_acc_ownership_1",ModelRequiredimex_acc_ownership_1 validates CLABE ownership in Mexico.
"verification_request": {Verification RequestiInput fields sent to the verification model.
"account_number": "021180012345678901",CLABERequiredi18-digit CLABE account number.
"account_type": "clabe",Account typeRequirediclabe for standard SPEI bank accounts.
"account_holder_id_number": "HEPL850315AB2",Holder IDRequirediBorrower's RFC as declared on the loan.
"account_holder_id_type": "rfc"ID typeRequiredirfc or curp — must match the id number format.
},
"external_id": "loan_000456_verify"External IDiYour loan/borrower reference for audit (traceability).
}
Response 201
{
"id": "av_MxTrust0001",IdiUnique Cobre identifier for this resource.
"creator_id": "cli_mex_trust_lender_01",Creator IdiCobre field at "creator_id" in this payload.
"model": "mex_acc_ownership_1",ModelRequiredimex_acc_ownership_1 validates CLABE ownership in Mexico.
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"verification_request": {Verification RequestiInput fields sent to the verification model.
"account_number": "021180012345678901",CLABERequiredi18-digit CLABE account number.
"account_type": "clabe",Account typeRequirediclabe for standard SPEI bank accounts.
"account_holder_id_number": "HEPL850315AB2",Holder IDRequirediBorrower's RFC as declared on the loan.
"account_holder_id_type": "rfc"ID typeRequiredirfc or curp — must match the id number format.
},
"status": {StatusiLifecycle status object for the resource or movement.
"state": "processing",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.
},
"external_id": "loan_000456_verify",External IDiYour loan/borrower reference for audit (traceability).
"created_at": "2026-08-01T10:05:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:05:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
Step 4 of 11 Account Verification API step

Retrieve Verification Result

Poll until status.state is completed. Only disburse when verification_result is matched; route failed or unmatched results to manual review.

GET https://api.cobre.co/v1/account_verifications/av_MxTrust0001
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Request body
{}
Response 200
{
"id": "av_MxTrust0001",Verification IDRequirediav_… from the create response.
"creator_id": "cli_mex_trust_lender_01",Creator IdiCobre field at "creator_id" in this payload.
"model": "mex_acc_ownership_1",ModeliVerification model identifier (region- and rail-specific).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"verification_request": {Verification RequestiInput fields sent to the verification model.
"account_number": "021180012345678901",Account NumberiBank account or CLABE number for the counterparty.
"account_type": "clabe",Account TypeiCobre field at "verification_request.account_type" in this payload.
"account_holder_id_number": "HEPL850315AB2",Account Holder Id NumberiCobre field at "verification_request.account_holder_id_number" in this payload.
"account_holder_id_type": "rfc"Account Holder Id TypeiCobre field at "verification_request.account_holder_id_type" in this payload.
},
"verification_response": {Verification ResponseiResult returned by the verification model.
"verification_result": "matched"Ownership resultRequiredimatched = safe to proceed; unmatched or unresolved = block payout.
},
"status": {StatusiLifecycle status object for the resource or movement.
"state": "completed",StatusRequirediMust be completed before disbursement.
"code": "",CodeiProvider or Cobre status code when the state is failed or rejected.
"description": ""DescriptioniHuman-readable detail for the current status.
},
"external_id": "loan_000456_verify",External IdiYour own reference echoed by Cobre for reconciliation.
"created_at": "2026-08-01T10:05:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:12:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
Step 5 of 11 Loan Disbursement API step

Create CLABE Counterparty

Register the verified borrower bank account as a Mexico CLABE counterparty. Normalize accents in counterparty_fullname — special characters are not allowed.

POST https://api.cobre.co/v1/counterparties
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Content-Typeapplication/json
Request body
{
"geo": "mex",GeographyRequirediGeography code (e.g. col = Colombia, mex = Mexico).
"type": "clabe",TypeRequirediclabe for standard SPEI loan disbursement to a bank account.
"alias": "Borrower loan_000456",AliasiDisplay name that helps identify it and clarify its purpose.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"account_number": "021180012345678901",CLABERequirediBank account or CLABE number for the counterparty.
"counterparty_fullname": "Luis Hernandez Paredes",Full nameRequirediLegal or display name of the counterparty beneficiary.
"counterparty_id_type": "rfc",ID typeRequirediType of identification document for the counterparty (e.g. nit, cc, rfc).
"counterparty_id_number": "HEPL850315AB2"ID numberRequirediIdentification number for the counterparty.
}
}
Response 201
{
"id": "cp_MxBorrowerA1",IdiUnique Cobre identifier for this resource.
"geo": "mex",GeographyRequirediGeography code (e.g. col = Colombia, mex = Mexico).
"type": "clabe",TypeRequirediclabe for standard SPEI loan disbursement to a bank account.
"alias": "Borrower loan_000456",AliasiDisplay name that helps identify it and clarify its purpose.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"account_number": "021180012345678901",CLABERequirediBank account or CLABE number for the counterparty.
"counterparty_fullname": "Luis Hernandez Paredes",Full nameRequirediLegal or display name of the counterparty beneficiary.
"counterparty_id_type": "rfc",ID typeRequirediType of identification document for the counterparty (e.g. nit, cc, rfc).
"counterparty_id_number": "HEPL850315AB2"ID numberRequirediIdentification number for the counterparty.
},
"created_at": "2026-08-01T10:15:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:15:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
Documentation for this step
Create a CounterpartyManaging Counterparties
Step 6 of 11 Loan Disbursement API step

Disburse Loan from the Trust's Cobre Balance

Send approved loan principal from the trust's MXN Cobre Balance to the borrower's CLABE counterparty. Amount is in cents (250000 = MXN 2,500.00). SPEI metadata requires a numeric reference (≤7 digits). Reuse the same idempotency header when retrying a timed-out POST — valid 24h.

POST https://api.cobre.co/v1/money_movements
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Content-Typeapplication/json
idempotency987654321
Request body
{
"amount": 250000,Amount (cents)Requiredi250000 cents = MXN 2,500.00.
"source_id": "acc_TrustBalanceMx01",Source balanceRequirediThe trust's Cobre Balance — one of two valid funding sources in this design.
"destination_id": "cp_MxBorrowerA1",Destination counterpartyRequirediCobre id of the destination account or counterparty.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"description": "Loan disbursement",DescriptioniOptional SPEI description, max 40 characters.
"reference": "2345678"SPEI referenceRequirediNumeric reference, 1–7 digits — required for SPEI payouts.
},
"external_id": "loan_000456"External ID (loan)iYour loan id — primary reconciliation join key.
}
Response 201
{
"id": "mm_TrustLoan456",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.
"description": "Loan disbursement",DescriptioniOptional SPEI description, max 40 characters.
"reference": "2345678"SPEI referenceRequirediNumeric reference, 1–7 digits — required for SPEI payouts.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000456",External ID (loan)iYour loan id — 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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_TrustBalanceMx01",Source balanceRequirediThe trust's Cobre Balance — one of two valid funding sources in this design.
"destination_id": "cp_MxBorrowerA1",Destination counterpartyRequirediCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 250000,Amount (cents)Requiredi250000 cents = MXN 2,500.00.
"created_at": "2026-08-01T10:20:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:20:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}

Webhook outcomesMoney movement

SPEI completed — mark the loan disbursed on your ledger using external_id. Persist tracking_key and cep_url from metadata for audit and SPEI receipt download.

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.

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.

Event money_movements.status.completed
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_TrustLoan456Cmp",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-08-01T10:22:30Z",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_TrustLoan456",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.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "2345678",ReferenceiPayment reference echoed in metadata for reconciliation.
"tracking_key": "20260801mmTr8gkQwofrb1a",Tracking KeyiNetwork tracking key for the payment (PSE ticket or Bre-B key).
"cep_url": "https://cep.banco.com/download"Cep UrliMetadata field "cep_url" attached to the resource.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000456",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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_TrustBalanceMx01",Source IdiCobre id of the source account or counterparty.
"destination_id": "cp_MxBorrowerA1",Destination IdiCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 250000,AmountiAmount in cents — the last two digits are decimals.
"created_at": "2026-08-01T10:20:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:22:30Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
}

Cobre or the rail could not process the movement. Inspect status.code and status.description. The list below is filtered to this Money Movement’s direction (payin, payout, or both):

Possible status codes
CodeDescriptionApplies to
F001Payment processing failed please try again.Payin and payout
F002NSF - Not Sufficient Funds in the designated account.Payin and payout
F004Daily transaction amount limit has been reached.Payin and payout
F005Amount exceeds the maximum allowed transaction limit.Payin and payout
F098Could not process the money movement at this time.Payin and payout
F099Could not process the money movement at this time.Payin and payout
Event money_movements.status.failed
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_TrustLoan456Cmp",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-08-01T10:22:30Z",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_TrustLoan456",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.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "2345678",ReferenceiPayment reference echoed in metadata for reconciliation.
"tracking_key": "20260801mmTr8gkQwofrb1a",Tracking KeyiNetwork tracking key for the payment (PSE ticket or Bre-B key).
"cep_url": "https://cep.banco.com/download"Cep UrliMetadata field "cep_url" attached to the resource.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000456",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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_TrustBalanceMx01",Source IdiCobre id of the source account or counterparty.
"destination_id": "cp_MxBorrowerA1",Destination IdiCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 250000,AmountiAmount in cents — the last two digits are decimals.
"created_at": "2026-08-01T10:20:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:22:30Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
}

The bank or payment network rejected the transaction. Inspect status.code. The list below is filtered to this Money Movement’s direction (payin, payout, or both):

Possible status codes
CodeDescriptionApplies to
R000Transaction rejected.Payin and payout
R001Inactive or blocked account.Payin and payout
R002Account and identification provided do not coincide.Payin and payout
R004ID not valid.Payout
R005Account does not exist.Payin and payout
R006Invalid account number.Payin and payout
R009Exceeds maximum allowed amount.Payin and payout
R010Account not authorized to debit.Payin and payout
R011Invalid Account type.Payout
R015Account not authorized to be credited.Payout
R018Payment rejected due invalid key.Payout
R023Payment cancelled by the user.Payin and payout
R024Exceeds maximum allowed number of transactions.Payout
R025Required information missing.Payout
R026Payment rejected due to unavailable bank services.Payin and payout
R027Account exceeds the maximum allowed transaction limit.Payin and payout
R034Account closed.Payin and payout
R085Bank processing error.Payout
Event money_movements.status.rejected
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_TrustLoan456Cmp",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-08-01T10:22:30Z",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_TrustLoan456",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": "R018",CodeiProvider or Cobre status code when the state is failed or rejected.
"description": "Payment rejected due invalid key."DescriptioniHuman-readable label or note.
},
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "2345678",ReferenceiPayment reference echoed in metadata for reconciliation.
"tracking_key": "20260801mmTr8gkQwofrb1a",Tracking KeyiNetwork tracking key for the payment (PSE ticket or Bre-B key).
"cep_url": "https://cep.banco.com/download"Cep UrliMetadata field "cep_url" attached to the resource.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000456",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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_TrustBalanceMx01",Source IdiCobre id of the source account or counterparty.
"destination_id": "cp_MxBorrowerA1",Destination IdiCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 250000,AmountiAmount in cents — the last two digits are decimals.
"created_at": "2026-08-01T10:20:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:22:30Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
}
Step 7 of 11 Loan Disbursement API step

Create SPEI Card Counterparty

Register a second borrower's debit card as a Mexico SPEI Card counterparty — an alternative disbursement rail to CLABE, useful when the borrower only shares a card number.

POST https://api.cobre.co/v1/counterparties
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Content-Typeapplication/json
Request body
{
"geo": "mex",GeographyRequirediGeography code (e.g. col = Colombia, mex = Mexico).
"type": "spei_card",TypeRequirediResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"alias": "Borrower loan_000789",AliasiDisplay name that helps identify it and clarify its purpose.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"card_number": "4152310000009876",Card numberRequiredi16-digit debit card number.
"beneficiary_institution": "40012",Beneficiary institutionRequirediSPEI participant institution code for the card issuer.
"counterparty_fullname": "Karla Sanchez Vidal",Full nameRequirediLegal or display name of the counterparty beneficiary.
"counterparty_id_type": "curp",ID typeRequirediType of identification document for the counterparty (e.g. nit, cc, rfc).
"counterparty_id_number": "SAVK900210MDFNDL05"ID numberRequirediIdentification number for the counterparty.
}
}
Response 201
{
"id": "cp_MxBorrowerB2",IdiUnique Cobre identifier for this resource.
"geo": "mex",GeographyRequirediGeography code (e.g. col = Colombia, mex = Mexico).
"type": "spei_card",TypeRequirediResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"alias": "Borrower loan_000789",AliasiDisplay name that helps identify it and clarify its purpose.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"card_number": "4152310000009876",Card numberRequiredi16-digit debit card number.
"beneficiary_institution": "40012",Beneficiary institutionRequirediSPEI participant institution code for the card issuer.
"counterparty_fullname": "Karla Sanchez Vidal",Full nameRequirediLegal or display name of the counterparty beneficiary.
"counterparty_id_type": "curp",ID typeRequirediType of identification document for the counterparty (e.g. nit, cc, rfc).
"counterparty_id_number": "SAVK900210MDFNDL05"ID numberRequirediIdentification number for the counterparty.
},
"created_at": "2026-08-01T10:30:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:30:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
Documentation for this step
Create a CounterpartyManaging Counterparties
Step 8 of 11 Loan Disbursement API step

Disburse Loan from a Connect Account

Identical /money_movements call as the trust-balance disbursement — only source_id changes. Cobre routes the SPEI payout from whichever account you name: the trust's Cobre Balance, or (as here) a bank account you've connected via Cobre Connect.

POST https://api.cobre.co/v1/money_movements
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Content-Typeapplication/json
idempotency123456790
Request body
{
"amount": 180000,Amount (cents)Requiredi180000 cents = MXN 1,800.00.
"source_id": "acc_ConnectBankMx02",Source accountRequirediA Connect account — the second valid funding source in this design.
"destination_id": "cp_MxBorrowerB2",Destination counterpartyRequirediCobre id of the destination account or counterparty.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "8765432"SPEI referenceRequirediNumeric reference, 1–7 digits — required for SPEI payouts.
},
"external_id": "loan_000789"External ID (loan)iYour loan id — primary reconciliation join key.
}
Response 201
{
"id": "mm_ConnectLoan789",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.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "8765432"SPEI referenceRequirediNumeric reference, 1–7 digits — required for SPEI payouts.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000789",External ID (loan)iYour loan id — 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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_ConnectBankMx02",Source accountRequirediA Connect account — the second valid funding source in this design.
"destination_id": "cp_MxBorrowerB2",Destination counterpartyRequirediCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 180000,Amount (cents)Requiredi180000 cents = MXN 1,800.00.
"created_at": "2026-08-01T10:35:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:35:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}

Webhook outcomesMoney movement

Same completion event as a trust-balance disbursement — reconcile on external_id and mm_id regardless of which account funded the payout.

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.

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.

Event money_movements.status.completed
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_ConnectLoan789Cmp",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-08-01T10:37:30Z",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_ConnectLoan789",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.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "8765432",ReferenceiPayment reference echoed in metadata for reconciliation.
"tracking_key": "20260801mmCn2hkRxpgsc2b",Tracking KeyiNetwork tracking key for the payment (PSE ticket or Bre-B key).
"cep_url": "https://cep.banco.com/download"Cep UrliMetadata field "cep_url" attached to the resource.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000789",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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_ConnectBankMx02",Source IdiCobre id of the source account or counterparty.
"destination_id": "cp_MxBorrowerB2",Destination IdiCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 180000,AmountiAmount in cents — the last two digits are decimals.
"created_at": "2026-08-01T10:35:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:37:30Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
}

Cobre or the rail could not process the movement. Inspect status.code and status.description. The list below is filtered to this Money Movement’s direction (payin, payout, or both):

Possible status codes
CodeDescriptionApplies to
F001Payment processing failed please try again.Payin and payout
F002NSF - Not Sufficient Funds in the designated account.Payin and payout
F004Daily transaction amount limit has been reached.Payin and payout
F005Amount exceeds the maximum allowed transaction limit.Payin and payout
F098Could not process the money movement at this time.Payin and payout
F099Could not process the money movement at this time.Payin and payout
Event money_movements.status.failed
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_ConnectLoan789Cmp",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-08-01T10:37:30Z",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_ConnectLoan789",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.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "8765432",ReferenceiPayment reference echoed in metadata for reconciliation.
"tracking_key": "20260801mmCn2hkRxpgsc2b",Tracking KeyiNetwork tracking key for the payment (PSE ticket or Bre-B key).
"cep_url": "https://cep.banco.com/download"Cep UrliMetadata field "cep_url" attached to the resource.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000789",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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_ConnectBankMx02",Source IdiCobre id of the source account or counterparty.
"destination_id": "cp_MxBorrowerB2",Destination IdiCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 180000,AmountiAmount in cents — the last two digits are decimals.
"created_at": "2026-08-01T10:35:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:37:30Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
}

The bank or payment network rejected the transaction. Inspect status.code. The list below is filtered to this Money Movement’s direction (payin, payout, or both):

Possible status codes
CodeDescriptionApplies to
R000Transaction rejected.Payin and payout
R001Inactive or blocked account.Payin and payout
R002Account and identification provided do not coincide.Payin and payout
R004ID not valid.Payout
R005Account does not exist.Payin and payout
R006Invalid account number.Payin and payout
R009Exceeds maximum allowed amount.Payin and payout
R010Account not authorized to debit.Payin and payout
R011Invalid Account type.Payout
R015Account not authorized to be credited.Payout
R018Payment rejected due invalid key.Payout
R023Payment cancelled by the user.Payin and payout
R024Exceeds maximum allowed number of transactions.Payout
R025Required information missing.Payout
R026Payment rejected due to unavailable bank services.Payin and payout
R027Account exceeds the maximum allowed transaction limit.Payin and payout
R034Account closed.Payin and payout
R085Bank processing error.Payout
Event money_movements.status.rejected
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_ConnectLoan789Cmp",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-08-01T10:37:30Z",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_ConnectLoan789",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": "R018",CodeiProvider or Cobre status code when the state is failed or rejected.
"description": "Payment rejected due invalid key."DescriptioniHuman-readable label or note.
},
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"description": "Loan disbursement",DescriptioniHuman-readable label or note.
"reference": "8765432",ReferenceiPayment reference echoed in metadata for reconciliation.
"tracking_key": "20260801mmCn2hkRxpgsc2b",Tracking KeyiNetwork tracking key for the payment (PSE ticket or Bre-B key).
"cep_url": "https://cep.banco.com/download"Cep UrliMetadata field "cep_url" attached to the resource.
},
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"external_id": "loan_000789",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": "spei",TypeiResource or movement type as defined by the Cobre API for this rail/product (e.g. breb_credit for Cobre Key payins).
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"source_id": "acc_ConnectBankMx02",Source IdiCobre id of the source account or counterparty.
"destination_id": "cp_MxBorrowerB2",Destination IdiCobre id of the destination account or counterparty.
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"amount": 180000,AmountiAmount in cents — the last two digits are decimals.
"created_at": "2026-08-01T10:35:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:37:30Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
}
Step 9 of 11 Loan Disbursement API step

Disburse a Batch of Loans (Bulk)

Upload a JSON array via multipart/form-data (field file) to disburse many approved loans in one call — useful for a scheduled daily or weekly disbursement run. Demo includes two lines: line 1 pays an existing counterparty (destination_id) from the trust's Cobre Balance; line 2 embeds a destination object to create a new CLABE counterparty inline, funded from a Connect account. The response id (bat_…) becomes batch_id on every child Money Movement. Max file size ~4.7 MB.

POST https://api.cobre.co/v1/bulk_money_movements
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Multipart upload
file@dispersion_2026-08-01.json
File content
[
{
"amount": 250000,
"source_id": "acc_TrustBalanceMx01",
"destination_id": "cp_MxBorrowerA1",
"metadata": {
"description": "Loan disbursement",
"reference": "2345678"
},
"external_id": "loan_000456"
},
{
"amount": 220000,
"source_id": "acc_ConnectBankMx02",
"destination": {
"geo": "mex",
"type": "clabe",
"alias": "Borrower loan_000901",
"metadata": {
"account_number": "032180000118359719",
"counterparty_fullname": "Roberto Diaz Salgado",
"counterparty_id_type": "rfc",
"counterparty_id_number": "DISR780622AB9"
}
},
"metadata": {
"description": "Loan disbursement",
"reference": "1122334"
},
"external_id": "loan_000901"
}
]
Response 201
{
"id": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"status": {StatusiLifecycle status object for the resource or movement.
"state": "validating",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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": ""Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}

Webhook outcomesBulk money movement

Bulk batch finished — every line reached a terminal Money Movement state. Reconcile the batch on content.id (bat_…); drill into each loan on money_movements.status.* webhooks using external_id (each child MM carries batch_id = bat_MxLoteAgo01).

Bulk statuses are validating, processing, pending_approval, completed, failed, and canceled — <b>rejected</b> is not a bulk status. The bulk completes when every Money Movement in the file reaches a terminal MM state (completed, failed, canceled, or rejected). See the <a href="https://docs.cobre.com/bulk-money-movements-1886564m0" target="_blank" rel="noopener">Bulk Money Movements</a> guide.

Initial bulk status while Cobre validates the uploaded JSON file format.

Event bulk_money_movements.status.validating
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_MxLoteAgo01Cmp",IdiUnique Cobre identifier for this resource.
"event_key": "bulk_money_movements.status.validating",Event KeyiWebhook subscription key (e.g. money_movements.status.completed).
"created_at": "2026-08-01T09:10: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": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"status": {StatusiLifecycle status object for the resource or movement.
"state": "validating",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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "2026-08-01T09:05:00Z",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": "2026-08-01T09:10:00Z"Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}
}

File validated — each Money Movement in the batch is being created and executed.

Event bulk_money_movements.status.processing
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_MxLoteAgo01Cmp",IdiUnique Cobre identifier for this resource.
"event_key": "bulk_money_movements.status.processing",Event KeyiWebhook subscription key (e.g. money_movements.status.completed).
"created_at": "2026-08-01T09:10: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": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"status": {StatusiLifecycle status object for the resource or movement.
"state": "processing",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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "2026-08-01T09:05:00Z",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": "2026-08-01T09:10:00Z"Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}
}

Bulk submitted with checker_approval; awaiting an approver decision before processing.

Event bulk_money_movements.status.pending_approval
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_MxLoteAgo01Cmp",IdiUnique Cobre identifier for this resource.
"event_key": "bulk_money_movements.status.pending_approval",Event KeyiWebhook subscription key (e.g. money_movements.status.completed).
"created_at": "2026-08-01T09:10: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": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"status": {StatusiLifecycle status object for the resource or movement.
"state": "pending_approval",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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "2026-08-01T09:05:00Z",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": "2026-08-01T09:10:00Z"Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}
}

Every Money Movement in the file reached a terminal state. Reconcile each line via its MM webhooks using external_id; child movements include batch_id matching the bulk id.

Event bulk_money_movements.status.completed
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_MxLoteAgo01Cmp",IdiUnique Cobre identifier for this resource.
"event_key": "bulk_money_movements.status.completed",Event KeyiWebhook subscription key (e.g. money_movements.status.completed).
"created_at": "2026-08-01T09:10: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": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "2026-08-01T09:05:00Z",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": "2026-08-01T09:10:00Z"Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}
}

Bulk validation failed — the file format could not be processed. Fix the JSON and re-upload.

Event bulk_money_movements.status.failed
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_MxLoteAgo01Cmp",IdiUnique Cobre identifier for this resource.
"event_key": "bulk_money_movements.status.failed",Event KeyiWebhook subscription key (e.g. money_movements.status.completed).
"created_at": "2026-08-01T09:10: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": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"status": {StatusiLifecycle status object for the resource or movement.
"state": "failed",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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "2026-08-01T09:05:00Z",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": "2026-08-01T09:10:00Z"Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}
}

Bulk process was canceled before completion.

Event bulk_money_movements.status.canceled
Headers
Content-Typeapplication/json
Example payload
{
"id": "ev_MxLoteAgo01Cmp",IdiUnique Cobre identifier for this resource.
"event_key": "bulk_money_movements.status.canceled",Event KeyiWebhook subscription key (e.g. money_movements.status.completed).
"created_at": "2026-08-01T09:10: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": "bat_MxLoteAgo01",IdiUnique Cobre identifier for this resource.
"input_filename": "dispersion_2026-08-01.json",Input FilenameiOriginal filename of the uploaded bulk JSON file.
"status": {StatusiLifecycle status object for the resource or movement.
"state": "canceled",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.
},
"total_money_movements": 2,Total Money MovementsiNumber of Money Movement entries in the bulk file.
"total_amount": "470000",Total AmountiSum of all amounts in the bulk file, in cents.
"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.
"creator": "cli_mex_trust_lender_01",CreatoriActor that created the resource. On a Checkout-created Money Movement this is the r2p source counterparty (cp_…), not the API user.
"created_at": "2026-08-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"executed_at": "2026-08-01T09:05:00Z",Executed AtiTimestamp when bulk processing started executing movements (ISO 8601, UTC).
"processed_at": "2026-08-01T09:10:00Z"Processed AtiTimestamp when bulk processing finished (ISO 8601, UTC).
}
}
Step 10 of 11 Reconciliation API step

Check Account Balance On Demand

Query either funding source at any time to validate configuration or confirm available balance before the next disbursement — here, the trust's Cobre Balance after the first payout above.

GET https://api.cobre.co/v1/accounts/acc_TrustBalanceMx01Account IDRequirediacc_… of the Cobre Balance or Connect account to inspect.
Headers
AuthorizationBearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGlfbWV4X3RydXN0X2xlbmRlcl8wMSJ9.Tr8Np2qL6wZ4vJd3mYw0sK5xF1eR7uH2gT
Request body
{}
Response 200
{
"id": "acc_TrustBalanceMx01",IdiUnique Cobre identifier for this resource.
"provider_id": "pr_mex_cobre3",Provider IdiCobre field at "provider_id" in this payload.
"provider_name": "Cobre Balance Mexico 3",Provider NameiCobre field at "provider_name" in this payload.
"connectivity": {ConnectivityiConnection/registration status for keys or accounts.
"status": "connected",ConnectivityRequirediMust be connected before routing a payout from this account.
"description": ""DescriptioniHuman-readable label or note.
},
"alias": "Fiduciary trust MXN balance",AliasiDisplay name that helps identify it and clarify its purpose.
"metadata": {MetadataiCustom key-value metadata attached to the resource.
"available_services": [Available ServicesiCobre field at "metadata.available_services" in this payload.
"mm_push_from_account"
]
},
"account_number": "646180303700100099",Account NumberiBank account or CLABE number for the counterparty.
"account_type": "clabe",Account TypeiCobre field at "account_type" in this payload.
"obtained_balance": 4750000,Balance (cents)RequirediLatest known balance in cents.
"obtained_balance_at": "2026-08-01T10:40:00Z",Obtained Balance AtiCobre field at "obtained_balance_at" in this payload.
"geo": "mex",GeoiGeography code (e.g. col = Colombia, mex = Mexico).
"tags": [TagsiCobre field at "tags" in this payload.
"accounting"
],
"currency": "mxn",CurrencyiISO currency code (e.g. cop, mxn).
"created_at": "2026-05-01T09:00:00Z",Created AtiTimestamp when the resource was created (ISO 8601, UTC).
"updated_at": "2026-08-01T10:40:00Z"Updated AtiTimestamp of the last update (ISO 8601, UTC).
}
Step 11 of 11 Reconciliation Reconciliation

Reconcile the SPEI Disbursements

Match each completion webhook to your loan ledger on external_id and mm_id — the join keys are identical whether the payout was funded by the trust's Cobre Balance or a Connect account. Cross-check the debit via GET /accounts/{acct_id}/transactions. For D+1 close, export SPEI movements with POST /reports.

Mapping the webhook payload from an earlier step onto Loan ledger. No API call is made — this step closes the loop in your own system.

Cobre field & valueLoan ledger field
content.external_id
loan_000456
loan_id
Primary join key — your loan record id.
content.id
mm_TrustLoan456
cobre_mm_id
Canonical Money Movement id from Cobre.
content.source_id
acc_TrustBalanceMx01
funding_account_id
Which of the two funding sources paid this loan — same field for either source.
content.metadata.tracking_key
20260801mmTr8gkQwofrb1a
spei_tracking_key
SPEI network tracking key — store for audit.
content.metadata.cep_url
https://cep.banco.com/download
spei_receipt_url
CEP (Comprobante Electrónico de Pago) download URL.
content.status.state
completed
disbursement_status
Map completed → FUNDED; failed/rejected/returned → review.
content.amount
250000
disbursed_amount_cents