# Internal Transactions API 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. ## Overview - **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. ## Endpoint `POST /v1/transactions/internal_transaction` ## Request **Path params:** none **Query params:** none **Headers** - `Authorization: Bearer ` - `Content-Type: application/json` **Body** ```json { "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" } } ``` ## Validations ### Field-level - **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."`). - **currency** - Only **`"MXN"`** is supported (otherwise: `DATA_ERROR: "Transaction currency unsupported."`). - **description** - **Length < 40** characters (if exceeded: `DATA_ERROR: "Transaction description must have less than 40 characters length."`). - **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."`). - **IDs** - `client_id`, `source_instrument_id`, `destination_instrument_id` must be valid **UUIDs**. ### Instrument state - **Source** - **Exists**, is **active**, **not blocked**, and has **sufficient funds** (if not: `FAILED_PRECONDITION: "The account does not have sufficient funds."`). - **Destination** - **Exists / is assigned**, **active**, and **not blocked** (if not: `FAILED_PRECONDITION: "The account is not currently active."`). - **Same institution (internal rail)** - Destination must be **internal to Monato** (if not: `409 external_transfer_not_allowed`). - **Different instruments** - Best practice: `source_instrument_id` **≠** `destination_instrument_id`. ## Response examples ### Succed (LIQUIDATED) ```json { "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" } } ``` ## Error Examples ### Invactive account — 400 FAILED_PRECONDITION (10-E4120) ```json { "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" } } ] } ``` ### Insufficient funds — 400 FAILED_PRECONDITION (10-E4120) ```json { "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" } } ] } ``` ### Invalid External reference — 400 DATA_ERROR (10-E4120) ```json { "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" } } ] } ``` ### Invalid amount (<= 0) — 400 DATA_ERROR (10-E4120) ```json { "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" } } ] } ``` ### Large description — 400 DATA_ERROR (10-E4120) ```json { "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" } } ] } ``` ### Currency not supported — 400 DATA_ERROR (10-E4120) ```json { "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" } } ] } ``` ### Error mapping (quick reference) | 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.