Frictionless SPEI
Automated Deposit Resolution for SPEI Transfers
What Is Frictionless SPEI
Frictionless SPEI is how we handle the reality that users don't always follow deposit instructions. They send the wrong amount, they skip the checkout entirely, they fat-finger a number — it happens constantly. Instead of routing every mismatch to a human queue, the system now resolves the most common cases automatically and credits the user in real time.
The money still lands in the right bank account. Nothing changes on the settlement side. The difference is that we no longer need a person to figure out who sent the funds and manually push a balance update. The system does it.
The core idea: if we can identify the sender with confidence, we credit them immediately — regardless of whether the amount matches or whether a checkout existed at the time of transfer.
In practice, this eliminates the bulk of manual deposit reviews, “wrong amount” escalations, “deposit without checkout” tickets, and the reconciliation overhead that comes with all of it.
The feature builds on top of standard SPEI integration. If you haven't set up regular SPEI payments yet, do that first — Frictionless SPEI is an extension of the base SPEI flow, not a replacement.
Why We Built This
SPEI deposits are the backbone of how users fund their accounts. But the previous system was brittle — it only auto-credited a deposit if everything matched perfectly: the right CLABE, the exact amount down to the centavo, and an active checkout session. Miss any one of those, and the deposit got kicked to manual review.
Users regularly send round numbers instead of the exact checkout amount ($500 instead of $497.30)
Returning users skip the checkout entirely and transfer directly to their CLABE
Each unmatched deposit generates a support ticket, an Ops investigation, and a delayed credit
Finance had to reconcile these manually at end of day, adding another layer of friction
The information was there — we had the CLABE, the sender's history, the banking metadata. We just weren't using it to auto-resolve.
Frictionless SPEI closes that gap.
How Deposits Worked Before
Under the previous model, a SPEI deposit followed a strict matching pipeline. All three conditions had to pass:
CLABE match
Transfer had to hit a CLABE assigned to an active user
Exact amount
Transferred amount had to match the checkout amount exactly
Active checkout
Open, unexpired checkout session at time of transfer
If any condition failed, the deposit went into a manual review queue. The user's balance stayed flat until someone resolved it. Every unresolved deposit was a ticket that needed human judgment, and the volume scaled linearly with user growth.
How Identification Works: CLABE + Identifiers
Every deposit relies on two distinct layers of identification working together.
Layer 1: CLABE
Tonder-Managed
Every merchant + customer combination gets a unique 18-digit CLABE assigned by Tonder. This is the primary deposit identifier. Merchants don't manage CLABEs — Tonder handles assignment and lifecycle.
Layer 2: Identifiers
Merchant-Provided
Merchants attach their own identifiers via metadata fields: external_id (primary reference) and optional additional_external_id for complex use cases.
How It Works Now: The Two Use Cases
Use Case 1: Mismatched Amount
A user opens a checkout for $100 MXN but sends $600 MXN. The system handles it automatically.
Checkout created for $100 MXN
User initiates a deposit through the checkout flow
User sends $600 MXN
Actual transfer amount differs from checkout
CLABE matched, identity confirmed
System confirms the sender despite amount mismatch
Balance credited: $600 MXN
Actual received amount credited, flagged as mismatched
Webhook payload:
{
"data": {
"amount": 600.0,
"metadata": {
"external_id": "ORDER-12345",
"mismatched_deposit": "True",
"original_expected_amount": "100"
}
}
}Ops dashboard view:
Use Case 2: Direct Transfer Without Checkout
A returning user sends money straight to their CLABE without opening a checkout. The system recognizes them from history.
User transfers $700 MXN to saved CLABE
No checkout session exists
No active checkout found
System proceeds to history lookup
Historical match found
Last successful transaction on this CLABE identifies the user
Deposit auto-created, user credited
Balance updated instantly with $700 MXN
Important: UC2 only works for returning users with at least one prior successful deposit on the same CLABE. First-time deposits without a checkout can't be auto-resolved — they require manual reconciliation via Tonder support.
Webhook payload:
{
"data": {
"amount": 700.0,
"metadata": {
"external_id": "CUSTOMER-12345",
"concept": "Frictionless deposit - auto-created"
}
}
}How to tell which use case triggered: UC1 includes mismatched_deposit: "True". UC2 includes concept: "Frictionless deposit - auto-created".
Integration: Choosing an Identifier Strategy
Single Identifier
Use the same identifier for both use cases. One reconciliation flow, one code path. Best for customer-centric platforms like gaming wallets or prepaid accounts.
{
"amount": 500,
"currency": "MXN",
"payment_method": "spei",
"metadata": {
"external_id": "PLAYER-12345"
}
}Dual Identifiers
Different tracking per use case. Use external_id for order-level (UC1) and additional_external_id for customer-level (UC2).
{
"amount": 500,
"currency": "MXN",
"payment_method": "spei",
"metadata": {
"external_id": "ORDER-12345",
"additional_external_id": "PLAYER-98765"
}
}Strategy comparison:
Custom Field Aliases
Merchants can configure domain-specific field names instead of the generic external_id. For example, a gaming platform might use order_id and player_id.
What Still Goes to Manual Review
First-time without checkout
No prior history to match against
CLABE conflicts
History links to multiple users
Unassigned CLABEs
CLABE not mapped to any merchant + customer
Flagged transactions
Risk or compliance rules triggered
Extreme mismatches (>500%)
May warrant a second look
Rapid-fire deposits
Multiple deposits in short timeframe
Day-to-Day Impact on Operations
Review every unmatched deposit manually
System auto-resolves mismatches and no-checkout deposits
Manually identify users from CLABE + banking data
User identification automated via CLABE history
Validate amounts, cross-check checkouts
Amount and checkout validation handled by system
Credit balances by hand
Balances credited in real time
Handle user complaints about delayed deposits
Complaints drop — users credited before they notice
Reconcile everything at end of day
Reconciliation cleaner — fewer manual entries
For Finance Teams
Fewer corrections
Deposits credited correctly the first time — no post-hoc balance adjustments
Cleaner reconciliation
Fewer orphaned deposits sitting in limbo at end of day
Full metadata
Every auto-resolved deposit logged with amounts, match basis, timestamp, user ID, and identifier fields
Complete audit trail
Nothing is silently resolved — every decision is traceable
Implications for Merchants
For merchants running deposits through Tonder, Frictionless SPEI means end users get a noticeably better experience. Deposits that previously would have been stuck in a queue now land instantly. This matters most for gaming wallets, prepaid balances, and event top-ups — where even a 10-minute delay feels broken.
Merchants also gain control over how they handle each use case. With webhook flags (mismatched_deposit, concept), they can build different notification flows — alerting users about amount mismatches or confirming successful top-ups for direct transfers.
Technical Notes
Resolution Pipeline
1. Is the CLABE assigned to a merchant + customer?
2. Is there an active checkout?
3. Does the CLABE have deposit history?
Idempotency
Every deposit event processed exactly once. Duplicate SPEI notifications caught by reference deduplication.
Latency
Auto-resolved deposits credited within the same processing cycle. No batching. Effectively instant.
Observability
Full logging of resolution path, confidence basis, identifier fields, and input data snapshot.
Control and Configuration
Frictionless SPEI can be disabled at any time — globally or per-merchant. When disabled, all deposits revert to strict-match behavior with a single toggle.
Global enable/disable
On or off for all merchants
Per-merchant override
Disable for specific merchants
Scenario-level control
Enable UC1, UC2, or both independently
Amount threshold
Max auto-credit amount — above goes to manual review
Integration Best Practices
Start simple
Use single identifier with just external_id unless you have a concrete reason for dual. You can always add additional_external_id later.
Always validate
Verify webhook signatures, check identifiers exist in your system, prevent duplicate processing, and validate amounts are reasonable.
Handle edge cases
Build handling for very large mismatches (>5x expected), rapid-fire deposits, unknown identifiers, and missing fields.
Log everything
CLABE used, all identifiers, amount mismatches, auto-creation events, and reconciliation results. Essential for disputes and compliance.
Common Questions
Should we use single or dual identifiers?
Start with single. It's simpler and covers most use cases. Only go dual if you specifically need different tracking for checkout-based deposits vs. direct transfers.
Do we need to store CLABEs?
Optional. Tonder manages CLABEs and includes them in webhooks. Store them only if you need them for customer service or analytics.
Can a user get credited more than their actual deposit?
No. The system always credits the actual received amount, never the checkout amount.
What if frictionless resolution credits the wrong user?
That would require the CLABE assignment to be wrong — a data integrity issue upstream. Every auto-resolution is logged and reversible.
Does this affect refunds or withdrawals?
No. Frictionless SPEI only applies to incoming deposit resolution.
Is there a risk of money laundering through mismatched amounts?
The same AML checks apply. Amount mismatches above configurable thresholds route to manual review, and all transactions feed into standard compliance monitoring.
What happens if UC2 can't find a historical transaction?
The deposit fails to auto-process. It won't silently drop — it just can't be resolved without history. Contact Tonder support for manual reconciliation.
Integration Checklist
Choose identifier strategy (single or dual)
Decide on custom field aliases (optional — coordinate with Tonder support)
Update payment requests to include identifier fields in metadata
Update webhook handler to read identifier fields and use-case flags
Implement reconciliation logic for both UC1 and UC2 paths
Test UC1 in staging (send mismatched amounts, verify webhook payload)
Test UC2 in staging (send without checkout, verify historical match)
Add logging and monitoring for all deposit events
Deploy to production