Internal Transfers Guide
This guide explains how to perform internal transfers between accounts at the same bank, covering the three available methods and their use cases.
Overview
Internal transfers move funds between accounts within the same bank, without going through the PIX network. They are processed instantly.
There are three ways to identify the destination account:
| Method | Endpoint | Destination requirement | Use case |
|---|---|---|---|
| By Account ID | /transfers/internal | Must have API access enabled | Transfers between your own accounts |
| By Document | /transfers/internal/by-document | Any account at the bank | Transfers to any account holder |
| By Branch/Account | /transfers/internal/by-bank-account | Must have API access enabled | When you have branch and account number |
1. Transfer by Account ID
The most performant method. Use when both source and destination accounts are registered in the API.
Endpoint: POST /v1/accounts/{accountId}/transfers/internal
curl -X POST "https://api.corpxapi.com/v1/accounts/{accountId}/transfers/internal" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: int-001" \
-d '{
"destinationAccountId": "773107de-139e-48d1-9462-f4e88f251891",
"value": 1500.00,
"description": "Transfer between branches",
"identifier": "branch-transfer-001"
}'
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
destinationAccountId | string (UUID) | Yes | Destination account UUID (API internal ID) |
value | number | Yes | Amount in BRL (max 2 decimal places) |
description | string | Yes | Transfer description |
identifier | string | No | Unique identifier for tracking |
Response (200):
{
"transactionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"destinationAccountId": "773107de-139e-48d1-9462-f4e88f251891",
"value": 1500.00,
"status": "COMPLETED",
"description": "Transfer between branches",
"identifier": "branch-transfer-001",
"createdAt": "2026-03-18T15:30:00Z"
}
2. Transfer by Document (CPF/CNPJ)
Use when the destination account is not registered in the API. Works for any account in the banking ecosystem.
Endpoint: POST /v1/accounts/{accountId}/transfers/internal/by-document
curl -X POST "https://api.corpxapi.com/v1/accounts/{accountId}/transfers/internal/by-document" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: int-002" \
-d '{
"document": "12345678000190",
"value": 500.00,
"description": "Supplier payment",
"identifier": "supplier-payment-002"
}'
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
document | string | Yes | CPF or CNPJ of the destination account holder (numbers only) |
value | number | Yes | Amount in BRL |
description | string | Yes | Transfer description |
identifier | string | No | Unique identifier for tracking |
3. Transfer by Branch and Account Number
Use when you have the branch and account number. Both accounts must be registered in the API.
Endpoint: POST /v1/accounts/{accountId}/transfers/internal/by-bank-account
curl -X POST "https://api.corpxapi.com/v1/accounts/{accountId}/transfers/internal/by-bank-account" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: int-003" \
-d '{
"branch": "0001",
"accountNumber": "200038274",
"value": 250.00,
"description": "Refund",
"identifier": "refund-003"
}'
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
branch | string | Yes | Destination account branch |
accountNumber | string | Yes | Destination account number |
value | number | Yes | Amount in BRL |
description | string | Yes | Transfer description |
identifier | string | No | Unique identifier for tracking |
Which method to choose?
Does the destination account have API access?
├── YES → Do you have the Account ID (UUID)?
│ ├── YES → Use /transfers/internal (fastest)
│ └── NO → Use /transfers/internal/by-bank-account
└── NO → Use /transfers/internal/by-document
Practical examples:
- Moving funds between your company's branches →
/transfers/internal(by Account ID) - Paying a supplier at the bank →
/transfers/internal/by-document(by CPF/CNPJ) - Transferring to a known account by branch number →
/transfers/internal/by-bank-account
Webhooks
After an internal transfer, both parties receive a webhook:
- Sender:
transfer.internal.out - Receiver:
transfer.internal.in
{
"id": "evt_abc123",
"type": "transfer.internal.in",
"eventType": "transfer.internal.in",
"accountId": "773107de-139e-48d1-9462-f4e88f251891",
"data": {
"amount": 1500.00,
"currency": "BRL",
"status": "SUCCESS",
"completedAt": "2026-03-18T15:30:00Z",
"source": {
"name": "SOURCE COMPANY LTDA",
"taxId": "12345678000100"
},
"destination": {
"name": "DESTINATION COMPANY LTDA",
"taxId": "12345678000200"
}
}
}
To receive these webhooks, include transfer.internal.in and/or transfer.internal.out in your subscription event types.
Common Errors
| Code | Message | Cause |
|---|---|---|
| 400 | destinationAccountId is required | Missing required field |
| 400 | value must be positive | Invalid amount |
| 404 | destination account not found | Destination not found (by-bank-account) |
| 422 | insufficient_balance | Insufficient balance in source account |
| 502 | unable to create internal transfer | Banking partner error |