Transfers
Transfers move funds instantly between Martis accounts within the platform. Unlike payouts that send money to external bank accounts, transfers keep funds within the Martis ecosystem for immediate availability.
For complete API documentation, see the API Reference.
The Transfer Object
A transfer contains the following attributes:
- Name
id- Type
- string
- Description
Unique identifier for the transfer
- Name
source_account_id- Type
- string
- Description
Source account identifier
- Name
destination_account_id- Type
- string
- Description
Destination account identifier
- Name
source_account_name- Type
- string
- Description
Name of the source account
- Name
destination_account_name- Type
- string
- Description
Name of the destination account
- Name
status- Type
- string
- Description
Current status:
succeededorfailed
- Name
currency- Type
- string
- Description
Three-letter currency code (e.g.,
idr)
- Name
amount- Type
- decimal
- Description
Transfer amount
- Name
description- Type
- string
- Description
Transfer description
- Name
client_reference_id- Type
- string
- Description
Merchant-provided reference identifier
- Name
created_at- Type
- datetime
- Description
Timestamp when the transfer was created
- Name
updated_at- Type
- datetime
- Description
Timestamp of last update
Create a Transfer
Creates a new transfer to another Martis account.
Request Body
- Name
destination_account_id- Type
- string
- Description
The unique identifier of the destination account. The account must be active.
- Name
amount- Type
- decimal
- Description
Transfer amount. Must be greater than 0.
- Name
currency- Type
- string
- Description
Three-letter currency code. Currently supported:
idr
- Name
client_reference_id- Type
- string
- Description
Merchant reference ID for tracking and reconciliation
- Name
description- Type
- string
- Description
Description of the transfer
Requirements
- Source account must have sufficient available balance
- Destination account must be an active Martis account
- Both accounts must support the specified currency
Request
curl https://api-staging.martis.id/api/v1/transfers \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {API_KEY}' \
--data '{
"destination_account_id": "01HZDEF456789012ABCDEF",
"amount": 100000.00,
"currency": "idr",
"description": "Revenue share payment",
"client_reference_id": "TRF-2024-001"
}'
Response 200
{
"status": "success",
"data": {
"id": "01HZTRANSFER123456ABC",
"source_account_id": "01HZABC123456789FEDCBA",
"destination_account_id": "01HZDEF456789012ABCDEF",
"source_account_name": "Source Business",
"destination_account_name": "Destination Business",
"amount": 100000.00,
"currency": "idr",
"status": "succeeded",
"description": "Revenue share payment",
"client_reference_id": "TRF-2024-001",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}
Response 400
{
"status": "fail",
"data": {
"destination_account_id": ["Destination account is not active"],
"amount": ["Amount must be greater than 0"],
"currency": ["Currency is required"]
}
}
Response 401
{
"status": "error",
"message": "Invalid or missing API key"
}
Response 403
{
"status": "error",
"message": "Insufficient balance for transfer"
}
Transfer States
Transfers are processed instantly and result in one of the following states:
| Status | Description |
|---|---|
succeeded | Transfer completed successfully. Funds are immediately available in the destination account. |
failed | Transfer failed due to insufficient balance or inactive destination account. |
Error Handling
Common transfer errors and resolutions:
| Error | Cause | Resolution |
|---|---|---|
Destination account is not active | Target account is inactive or suspended | Verify the destination account status before initiating transfer |
Insufficient balance for transfer | Source account balance is less than the transfer amount | Check available balance and reduce transfer amount if necessary |
Amount must be greater than 0 | Invalid amount provided | Ensure the amount is a positive decimal value |
Currency is required | Missing currency field | Include the currency field in the request body |
Destination account not found | Invalid destination account ID | Verify the destination account ID is correct |
Idempotency
Include an Idempotency-Key header to safely retry transfer requests without creating duplicates.
Best Practices
- Use unique keys tied to business operations (e.g., invoice ID, order ID)
- Store the mapping between business identifiers and idempotency keys
- Retry with the same key if the initial request times out or returns a 5xx error
Request with Idempotency Key
curl https://api-staging.martis.id/api/v1/transfers \
--request POST \
--header 'Authorization: Bearer {API_KEY}' \
--header 'Idempotency-Key: revenue-share-invoice-001' \
--header 'Content-Type: application/json' \
--data '{
"destination_account_id": "01HZDEF456789012ABCDEF",
"amount": 100000.00,
"currency": "idr"
}'
See Idempotency for key generation strategies.
Use Cases
Revenue Sharing
Split payment revenue between platform and merchants:
# Platform receives payment of 1,000,000 IDR
# Transfer 85% (850,000 IDR) to merchant account
curl https://api-staging.martis.id/api/v1/transfers \
--request POST \
--header 'Authorization: Bearer {API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
"destination_account_id": "{MERCHANT_ACCOUNT_ID}",
"amount": 850000.00,
"currency": "idr",
"description": "Revenue share - Order #12345",
"client_reference_id": "order-12345-share"
}'
Multi-Account Treasury
Move funds between business units or regional accounts:
curl https://api-staging.martis.id/api/v1/transfers \
--request POST \
--header 'Authorization: Bearer {API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
"destination_account_id": "{REGIONAL_ACCOUNT_ID}",
"amount": 5000000.00,
"currency": "idr",
"description": "Monthly operating budget - Region West",
"client_reference_id": "budget-2025-01-west"
}'