SPEI Transactions API — V1 to V2 Migration Guide
Why Migrate?
The V1 SPEI Transactions API (/spei/v1/deposits and /spei/v1/withdrawals) uses offset-based pagination, which suffers from increasing latency as you paginate deeper into large result sets. Clients performing reconciliation over wide date ranges have experienced significant slowdowns on V1.
The V2 APIs resolve these performance issues by replacing offset pagination with token-based pagination. These changes bring many benefits:
- Consistent performance: response times remain stable regardless of how deep you paginate. Latency spikes are not expected with the new APIs.
- Incremental synchronization: you can resume from the last token without re-fetching earlier pages.
- Cleaner response format: response payloads were improved to contain the most relevant and useful data for the deposits and withdrawals.
- Bidirectional refund linking: both deposits and withdrawals include cross-references to their counterpart, simplifying refund reconciliation.
Endpoint Mapping
| Resource | V1 Endpoint | V2 Endpoint |
|---|---|---|
| Deposits | GET /spei/v1/deposits | GET /spei/v2/deposits, see API reference. |
| Withdrawals | GET /spei/v1/withdrawals | GET /spei/v2/withdrawals, see API reference. |
| Single Withdrawal | Not available | GET /spei/v2/withdrawals/{wid}, see API reference. |
Pagination Details
The V1 API responses included page, page_size, total_pages, and total_elements. With the V2, these fields were deprecated, and the new response includes a next_page_token field.
Pass it as page_token in the next request to retrieve the following page. When next_page_token is absent, you have reached the end of the collection.
Opaque page tokensThe
page_tokenvalues are opaque. Do not parse, decode, or construct them. They are only valid for the original query parameters — changing filters while reusing a token produces undefined behavior.
Deposits
Removed Query Parameters
The following V1 query parameters have been removed in V2 and have no direct equivalent:
| V1 Parameter | Notes |
|---|---|
page | Replaced by token-based pagination. Use page_token instead. |
Query Parameter Equivalents
The following V1 query parameters have a direct or renamed equivalent in V2:
| V1 Parameter | V2 Parameter | Notes |
|---|---|---|
only_refunds | only_refunds | Unchanged. |
receiver_clabe | receiver_clabe | Unchanged. |
sender_clabe | sender_clabe | Unchanged. |
clabe_type | clabe_type | Unchanged. |
deposit_status | status | Renamed. Values are now uppercase (e.g., COMPLETE, PENDING, FAILED). |
tracking_key | tracking_key | Unchanged. |
start_date | created_at_gte | ISO 8601 timestamp (e.g., 2025-04-10T00:00:00Z). Inclusive. Defaults to the start of the previous day when not provided. |
end_date | created_at_lte | ISO 8601 timestamp. Inclusive. When both bounds are provided, created_at_gte must be less than or equal to created_at_lte. |
page_size | page_size | Unchanged. The maximum is 1000. Default is 25. |
Removed Response Fields
The following V1 response fields have been removed in V2 and have no direct equivalent:
| V1 Field | Notes |
|---|---|
depositId | No longer exposed. |
currency | Always MXN; no longer returned. |
Response Field Equivalents
The V1 response nests most transaction metadata inside a details object. V2 promotes these fields to the top level for a flatter, more ergonomic structure.
| V1 Field | V2 Field | Notes |
|---|---|---|
fid | fid | Unchanged. |
senderClabe | sender.clabe | Moved into a structured sender object that also includes name, bank, and rfc_curp. |
receiverClabe | receiver_clabe | Unchanged. |
status | status | Values are now uppercase. |
amount | amount | Unchanged. |
details.claveRastreo | tracking_key | Promoted to top level. |
details.numericReference | numeric_reference | Promoted to top level. |
details.concepto | description | Renamed and promoted to top level. |
details.cepLink | cep_link | Promoted to top level. |
details.senderName | sender.name | Moved into sender object. |
details.senderBank | sender.bank | Moved into sender object. |
details.paymentId | payment_id | Promoted to top level. |
New Fields in V2
The following fields are new in V2 and were not available in V1:
| V2 Field | Description |
|---|---|
operation_date | The date the deposit was processed by the banking system. Format: ISO 8601 date (YYYY-MM-DD). |
refunded_withdrawal | Lightweight reference to the original withdrawal that was reversed, containing wid, tracking_key, and origin_id. See Refund Reconciliation. |
errors | Array of error objects describing why the deposit reached a non-successful final state. Each error contains a code and message. null when the deposit has no errors. |
The V1 field details.multiclabe_validation_error has been deprecated. In V2, deposit errors are now defined in the errors field, which provides structured error information with a code and message for each error. The complete error catalogue can be found in the API Reference.
Withdrawals
Removed Query Parameters
The following V1 query parameters have been removed in V2 and have no direct equivalent:
| V1 Parameter | Notes |
|---|---|
wid | Use GET /spei/v2/withdrawals/{wid} to fetch a single withdrawal by ID instead. |
page | Replaced by token-based pagination. Use page_token instead. |
Query Parameter Equivalents
The following V1 query parameters have a direct or renamed equivalent in V2:
| V1 Parameter | V2 Parameter | Notes |
|---|---|---|
origin_id | origin_id | Unchanged. |
receiver_clabe | account_number | Renamed. Searches across CLABE, debit card, and phone number. |
withdrawal_status | status | Renamed. Values are now uppercase (e.g., COMPLETE, PENDING, FAILED, PROCESSING). |
tracking_key | tracking_key | Unchanged. |
only_refunds | only_refunds | Unchanged. |
start_date | created_at_gte | ISO 8601 timestamp. Inclusive. Defaults to the start of the previous day when not provided. |
end_date | created_at_lte | ISO 8601 timestamp. Inclusive. When both bounds are provided, created_at_gte must be less than or equal to created_at_lte. |
page_size | page_size | Unchanged. The maximum is 1000. Default is 25. |
Removed Response Fields
The following V1 response fields have been removed in V2 and have no direct equivalent:
| V1 Field | Notes |
|---|---|
currency | Always MXN; no longer returned. |
Response Field Equivalents
The V1 response nests most transaction metadata inside a details object. V2 promotes these fields to the top level and replaces the embedded full deposit object with a lightweight reference.
| V1 Field | V2 Field | Notes |
|---|---|---|
wid | wid | Unchanged. |
details.originId | origin_id | Promoted to top level. |
amount | amount | Unchanged. |
status | status | Values are now uppercase. |
details.claveDeRastreo | tracking_key | Promoted to top level. |
details.concepto | description | Renamed and promoted to top level. |
details.beneficiaryName | beneficiary.name | Moved into structured beneficiary object. |
details.beneficiaryClabe | beneficiary.account.number | Moved into beneficiary.account with a type discriminator (CLABE, DEBIT_CARD, PHONE). Debit card numbers are obfuscated for security. |
details.cepLink | cep_link | Promoted to top level. |
details.fechaOperacion | operation_date | Promoted to top level; formatted as ISO 8601 date (YYYY-MM-DD). |
refundDeposit (full deposit) | refunded_deposit (lightweight) | Replaced with a lightweight reference. See Refund Reconciliation. |
New Fields in V2
The following fields are new in V2 and were not available in V1:
| V2 Field | Description |
|---|---|
operation_date | The specific date when the withdrawal was processed by the banking system. Format: ISO 8601 date (YYYY-MM-DD). |
refunded_deposit | Lightweight reference to the compensatory deposit, containing fid and tracking_key. See Refund Reconciliation. |
Refund Reconciliation
When a withdrawal fails, the banking system may issue a compensatory deposit back to the sender.
V2 Approach
V2 provides bidirectional linking with lightweight references on both sides:
- A withdrawal includes a
refunded_depositobject with the compensatory deposit'sfidandtracking_key. - A deposit includes a
refunded_withdrawalobject with the original withdrawal'swid,tracking_key, andorigin_id.
V2 Withdrawal V2 Deposit
┌─────────────────────────┐ ┌─────────────────────────┐
│ wid: "w-123" │ │ fid: "d-456" │
│ status: "FAILED" │ │ status: "COMPLETE" │
│ refunded_deposit: { │──────▶│ refunded_withdrawal: { │
│ fid: "d-456" │ │ wid: "w-123" │
│ tracking_key: "..." │◀──────│ tracking_key: "..." │
│ } │ │ origin_id: "a261847a" │
└─────────────────────────┘ │ } │
└─────────────────────────┘
To reconcile refunds in V2:
-
Starting from withdrawals: Search the refunded withdrawals, using the
only_refundsparam. Each result contains arefunded_depositwith thefidandtracking_keyof the compensatory deposit. These two fields allow us to match the deposit that was created to compensate the withdrawal. -
Starting from deposits: Search the refunded deposits, using the
only_refundsparam. Each result contains arefunded_withdrawalwith thewid,tracking_key, andorigin_idof the compensated withdrawal. These three fields allow us to match the withdrawal that originated the compensatory deposit.
Updated 7 months ago
