Internal Transactions move funds book-to-book between two Monato accounts (same institution). These do not go through SPEI, so there’s no CEP and settlement is typically near-real-time when both instruments are active and funded.
- Rail: Internal (book-to-book)
- CEP: Not applicable
- Latency: Near-real-time
- Use cases:
- Move funds between Cost Centers / Business Units
- Intra-merchant payouts
- Reserve account management
- Move funds to another Monato customer
Parity with Money Out: Request body format and most validations are the same as Money Out, with a few extra internal checks noted below.
POST /v1/transactions/internal_transaction
Path params: none
Query params: none
Headers
Authorization: Bearer <JWT>
Content-Type: application/json
Body
{
"client_id": "c2d1d1e3-3340-4170-980e-e9269bbbc551",
"source_instrument_id": "709448c3-7cbf-454d-a87e-feb23801269a",
"destination_instrument_id": "dd7f8d89-94dd-43ca-871b-720fde378b52",
"transaction_request": {
"amount": "1.90",
"currency": "MXN",
"description": "Internal transfer",
"external_reference": "1238766"
}
}
- amount
- Must be a numeric string with 2 decimal places (e.g.,
"1.90"
). - Must be greater than 0 (otherwise backend returns
DATA_ERROR: "Transaction Amount must be higher than 0."
).
- Must be a numeric string with 2 decimal places (e.g.,
- currency
- Only
"MXN"
is supported (otherwise:DATA_ERROR: "Transaction currency unsupported."
).
- Only
- description
- Length < 40 characters (if exceeded:
DATA_ERROR: "Transaction description must have less than 40 characters length."
).
- Length < 40 characters (if exceeded:
- external_reference
- Must be numeric and max 7 digits (otherwise:
DATA_ERROR: "External reference should be numeric and have a maximum length of 7 digits."
).
- Must be numeric and max 7 digits (otherwise:
- IDs
client_id
,source_instrument_id
,destination_instrument_id
must be valid UUIDs.
- Source
- Exists, is active, not blocked, and has sufficient funds
(if not:FAILED_PRECONDITION: "The account does not have sufficient funds."
).
- Exists, is active, not blocked, and has sufficient funds
- Destination
- Exists / is assigned, active, and not blocked
(if not:FAILED_PRECONDITION: "The account is not currently active."
).
- Exists / is assigned, active, and not blocked
- Same institution (internal rail)
- Destination must be internal to Monato (if not:
409 external_transfer_not_allowed
).
- Destination must be internal to Monato (if not:
- Different instruments
- Best practice:
source_instrument_id
≠destination_instrument_id
.
- Best practice:
{
"id": "09c9caac-3b74-4690-8ac5-5a01b2559b3f",
"bankId": "d3435bd9-998d-4e8a-9067-6b71d5fd3ac7",
"clientId": "b000654b-4d12-46e5-b451-662459b6effc",
"externalReference": "1238801",
"trackingId": "20250925FINCHCUCHFGMRLZ",
"description": "Prueba Internal 25/09/25",
"amount": "1.00",
"currency": "MXN",
"category": "INTER_TRANS",
"subCategory": "INT_DEBIT",
"transactionStatus": "LIQUIDATED",
"audit": {
"createdAt": "2025-09-25 15:48:28.486316-06:00",
"updatedAt": "2025-09-25 15:48:28.773897-06:00",
"deletedAt": "None",
"blockedAt": "None"
}
}
{
"code": 9,
"message": "API Error",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "FAILED_PRECONDITION",
"domain": "CORE",
"metadata": {
"error_detail": "The account is not currently active.",
"http_code": "400",
"module": "Transactions",
"method_name": "InternalTransaction",
"error_code": "10-E4120"
}
}
]
}
{
"code": 9,
"message": "API Error",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "FAILED_PRECONDITION",
"domain": "CORE",
"metadata": {
"error_detail": "The account does not have sufficient funds.",
"http_code": "400",
"module": "Transactions",
"method_name": "InternalTransaction",
"error_code": "10-E4120"
}
}
]
}
{
"code": 9,
"message": "API Error",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "DATA_ERROR",
"domain": "CORE",
"metadata": {
"error_detail": "External reference should be numeric and have a maximum length of 7 digits.",
"http_code": "400",
"module": "Transactions",
"method_name": "InternalTransaction",
"error_code": "10-E4120"
}
}
]
}
{
"code": 9,
"message": "API Error",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "DATA_ERROR",
"domain": "CORE",
"metadata": {
"error_detail": "Transaction Amount must be higher than 0.",
"http_code": "400",
"module": "Transactions",
"method_name": "InternalTransaction",
"error_code": "10-E4120"
}
}
]
}
{
"code": 9,
"message": "API Error",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "DATA_ERROR",
"domain": "CORE",
"metadata": {
"error_detail": "Transaction description must have less than 40 characters length.",
"http_code": "400",
"module": "Transactions",
"method_name": "InternalTransaction",
"error_code": "10-E4120"
}
}
]
}
{
"code": 9,
"message": "API Error",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "DATA_ERROR",
"domain": "CORE",
"metadata": {
"error_detail": "Transaction currency unsupported.",
"http_code": "400",
"module": "Transactions",
"method_name": "InternalTransaction",
"error_code": "10-E4120"
}
}
]
}
Failing rule | Typical response |
---|---|
Source account inactive/blocked | 400 FAILED_PRECONDITION (error_code: 10-E4120 ) |
Insufficient funds (source) | 400 FAILED_PRECONDITION (error_code: 10-E4120 ) |
external_reference non-numeric or > 7 digits | 400 DATA_ERROR (error_code: 10-E4120 ) |
amount ≤ 0 | 400 DATA_ERROR (error_code: 10-E4120 ) |
description ≥ 40 characters | 400 DATA_ERROR (error_code: 10-E4120 ) |
currency other than MXN | 400 DATA_ERROR (error_code: 10-E4120 ) |
Destination not found / not assigned | 404 destination_not_found |
Destination is external (not internal rail) | 409 external_transfer_not_allowed |
⚠️ Disclaimer - We plan to unify the APIs in the future so that both external Money Out (SPEI) and internal transactions (between Monato accounts) are supported through a single endpoint. For now, please use the endpoints separately as documented.