Reconciling PayOuts means matching the Money Movement you created (the payment intent, and its final status) against the Transactions that actually moved funds in your Cobre Balance, across Colombia, Mexico, and US payout rails.This guide explains how Money Movements and Transactions relate to each other, what to expect on the balance for each terminal status, and how to reconcile on demand or in bulk using Reports.
Money Movements vs. Transactions#
Every payout involves two related but distinct identifiers:| Identifier | Prefix | Generated when | Represents |
|---|
| Money Movement ID | mm_ | The payout is created | The payment intent/request and its lifecycle status |
| Transaction ID | trx_ | Funds are debited or credited on your Cobre Balance | The actual balance-affecting ledger entry |
A single Money Movement can generate zero, one, or more Transactions, depending on how its lifecycle unfolds. Every Transaction that results from a Money Movement carries a metadata.money_movement_id field linking it back — use this field to group Transactions by the payout that generated them.Always provide external_id when creating a payout (Create a Money Movement). It's echoed back on the Money Movement and is the simplest way to match a Cobre payout to your internal invoice, order, or payment record. Example — how a PayOut and its Transaction(s) unfold, step by step:
Payout Lifecycle and Balance Impact#
A payout's status.state tells you whether it completed, and its status.code / status.description explain why when it didn't. See Money Movement Statuses for the full catalog of reason codes, and the Money Movement guide for the complete lifecycle model.| Terminal state | Typical Transactions | Net balance impact |
|---|
completed | 1 debit | Negative (funds sent) |
canceled | 0 (canceled before a debit was applied — e.g., an approval was denied) | None |
failed | 0 — a failed payout never generates a debit at all | None |
rejected | 0, or 1 debit + 1 offsetting credit if a debit was already applied | None (if reversed) |
failed and rejected aren't interchangeable for reconciliation purposes. failed covers operational/platform-level issues caught before any debit is applied (e.g. NSF, limits exceeded, processing errors) — there's never a Transaction to look for. rejected covers rail- or bank-level rejections, which can happen after the debit already posted — that's the case that produces the offsetting credit below.
A payout can occasionally transition from completed to rejected if the destination bank returns the funds after Cobre already confirmed completion. When this happens, Cobre applies an offsetting credit transaction to your Cobre Balance. Don't treat completed as a permanently final balance state for reconciliation — always check for a later reversal Transaction under the same money_movement_id.
For SPEI payouts in Mexico specifically, a returned transfer generates a spei_return credit Transaction that offsets the original spei_debit — reconcile MX payout reversals by matching these two transaction types under the same money_movement_id.
Reconciling Payouts On Demand#
| Filter | Use it to |
|---|
state | Isolate completed, rejected, failed, or canceled payouts |
external_id | Find the Money Movement for a specific internal reference (contains match) |
source_id / destination_id | Reconcile all payouts from a Cobre Balance or to a counterparty |
created_at_gte / created_at_lte | Bound the query to a date range |
amount, amount_gte, amount_lte, currency | Narrow by value |
Cross-reference the result against Obtain an Account Transactions (GET /accounts/{acct_id}/transactions), filtering credit_debit_type=debit and matching metadata.money_movement_id, to confirm the balance-affecting side of each payout.
Reconciling Payouts in Bulk#
For date-range or high-volume reconciliation, use Reports instead of paginating through query results:1.
Create a report for the Money Movement side (money_movement_csv_v1 for CSV, or money_movement_v1 for JSON) and one for the Transaction side (transactions_csv_v1 for CSV, or account_transactions_v1 for JSON), over the same date range.
2.
Group both reports by metadata.money_movement_id.
3.
A money_movement_id with exactly one debit row reconciles as a completed payout; one with a debit and an offsetting credit reconciles as a reversed rejection or failure.
Reconciling Payouts in Real Time#
On-demand queries and Reports are both pull-based. For real-time reconciliation, subscribe to Money Movement status events via Notifications & Subscriptions instead — Cobre pushes a webhook as soon as a payout's status changes (money_movements.status.completed, money_movements.status.rejected, money_movements.status.failed, money_movements.status.canceled), so you can update your ledger the moment it happens rather than polling for it.Webhook delivery is best-effort, not guaranteed forever — see Notifications & Subscriptions for the retry window. Treat webhooks as your real-time signal and on-demand queries or Reports as the periodic fallback that catches anything a webhook missed.
Opening and Closing Balance Reconciliation#
Beyond individual payouts, clients often need to reconcile a Cobre Balance's opening balance, closing balance, and daily totals — independent of which payout generated each Transaction. See Opening and Closing Balance Reconciliation for the full walkthrough, including request/response examples.
Allowed Actions on Payout Reconciliation#
🔍 Retrieval — Money Movements
🔍 Retrieval — Transactions
🔍 Retrieval — Daily Balance History
Description: Query payouts on demand by state, external ID, counterparty, date range, or amount.
What to expect after the action: A paginated list of Money Movement objects with their current status. How to Get Started#
1
Always provide external_id on every payout
It's the fastest way to match a Cobre Money Movement to your internal record, and it's searchable via the external_id filter.
2
Subscribe to Money Movement status events instead of polling
3
Know your rail's reason codes
Review
Money Movement Statuses so a
failed or
rejected payout's
code and
description are actionable rather than opaque.
4
Decide between on-demand queries and Reports upfront
Use on-demand queries for individual payouts or small batches, and Reports for date-range or high-volume reconciliation.
What to expect after using this API#
1
Every payout resolves to a matched Money Movement + Transaction pair
Completed payouts show one debit; reversed rejections or failures show a debit and an offsetting credit under the same money_movement_id.
2
Opening and closing balances validate against Daily Balance History
initial_balance and end_balance from Daily Balance History match what you compute manually from ordered Transactions.
3
Discrepancies isolate to a specific money_movement_id
Any balance mismatch narrows down to one payout you can investigate directly via its Money Movement and Transaction records.