Transfer funds between merchants
Move funds from one merchant's balance to another merchant's balance.
An internal transfer moves funds between the balances of two Datman merchants. For comparison: a payout is an external transfer that moves funds from a merchant's balance to their verified bank account.
You can use internal transfers when:
- A merchant owes another merchant for a service that wasn't paid through a split payment, for example a delivery fee for an order paid in cash.
- A payment was split incorrectly, and you want to correct the balances.
Requirements
Before you begin, take into account the following requirements, limitations, and preparations.
| Requirement | Description |
|---|---|
| Integration type | You need a Datman reseller or platform integration. |
| API credentials | You need your api_token, sent in the api_token header. See Authentication. |
| Webhooks | Make sure that your server can receive and accept the internal transfer succeeded and internal transfer failed webhooks. |
| Limitations | The source and destination merchants must be different merchants, in the same country, with the same customer type. The amount must not be over the internal transfer limit for the merchant or the country. |
| Setup steps | Internal transfers must be enabled for both merchants, and for the country. |
How it works
Transfer requests go through the following stages:
-
Transfer request sent: You send a Transfer funds between two merchants request.
-
Checks: Datman checks that both merchants exist, are enabled for internal transfers and are in the same country, and that the amount is under the limit.
- If the checks pass, Datman accepts the request and returns
statusprocessing. - If a check fails, the request fails with an error code. See Troubleshooting.
- If the checks pass, Datman accepts the request and returns
-
Transfer processed: Datman processes the transfer asynchronously.
-
Result sent: Datman sends a webhook to the
webhook_urlfrom your request. The transfer either succeeded and the funds have moved, or it failed.
Initiate an internal transfer
-
To move funds between merchants, send a Transfer funds between two merchants request. In the body of the request, specify the following fields:
Parameter Required Description source_merchant_idRequired The MID of the merchant the funds come from, as a string of digits. destination_merchant_idRequired The MID of the merchant the funds go to, as a string of digits. amountRequired The amount in minor units. For example, 350 is GBP 3.50. transfer_category_codeRequired The category of the transfer, as agreed with Datman. descriptionRequired Your description of the transfer. referenceRequired Your reference for the transfer. It is returned in the webhook. webhook_urlRequired Where Datman sends the result of the transfer. Use HTTPS. order_idThe order the transfer relates to, if any. Note that
amountis in minor units, unlike most Datman APIs, which use major units such as 24.50.For example, to transfer GBP 3.50 from Example Pizza Ltd to Example Couriers Ltd, for a delivery that the shopper paid in cash, send
amount350. The API Explorer has the full request, with examples you can try. -
The response contains a
request_idandstatusprocessing. Save therequest_id, because you need it to match the webhook to your transfer.Response - Transfer accepted
{ "request_id": "3f1c2b6a-8d4e-4f0a-9b7c-1e2d3c4b5a69", "reference": "REF-100245-DLV", "status": "processing" }This status is not final. The response only confirms that Datman accepted the transfer.
Troubleshooting
If an internal transfer request fails, the response contains an error_code and a message:
| HTTP status | error_code | What to check |
|---|---|---|
| 400 | SAME_SOURCE_AND_DESTINATION_MERCHANT | The source and destination merchants must be different. |
| 400 | (none) | The message names the field that failed validation. |
| 401 | UNAUTHORIZED | The api_token header is missing or invalid. |
| 403 | INTERNAL_TRANSFER_SENDER_NOT_ENABLED | Internal transfers are not enabled for the source merchant. |
| 403 | MERCHANTS_DIFFERENT_COUNTRY | The merchants must be in the same country. |
| 403 | AMOUNT_EXCEEDED_THRESHOLD | The amount is over the internal transfer limit. |
| 404 | SOURCE_MERCHANT_NOT_FOUND, DESTINATION_MERCHANT_NOT_FOUND | The merchant doesn't exist. |
If the transfer is accepted but then fails with reason Insufficient funds, check the balance of the source merchant:
- Get the account balance of the source merchant, with its MID in the path.
- Check the
availablebalance. Note that it is in major units. - If the amount is lower than the transfer amount, wait until more funds are available, or transfer a smaller amount.
Get status updates
For every internal transfer request, Datman sends one webhook to your webhook_url. The webhook is sent once and isn't retried.
Before you trust the payload, verify the X-Datman-Signature header: the HMAC-SHA256 of the raw request body, computed with your webhook secret and hex-encoded. See Webhooks for how to verify an HMAC signature. Respond with HTTP 200.
You can identify the transfer by the request_id from the response, and by your reference.
1. Internal transfer succeeded
When the funds have moved, Datman sends an internal transfer succeeded webhook with:
status: success
This status is final.
Internal transfer succeeded
{
"request_id": "3f1c2b6a-8d4e-4f0a-9b7c-1e2d3c4b5a69",
"status": "success",
"currency": "GBP",
"source_merchant_id": "1000001",
"destination_merchant_id": "1000002",
"amount": 350,
"transfer_category_code": 1,
"reference": "REF-100245-DLV"
}2. Internal transfer failed
When the transfer fails, Datman sends an internal transfer failed webhook. It has no status. Instead, it has:
reason: why the transfer failed, for example Insufficient funds or Transfer failed.
This status is final. The funds are not moved.
Internal transfer failed
{
"request_id": "3f1c2b6a-8d4e-4f0a-9b7c-1e2d3c4b5a69",
"reason": "Insufficient funds",
"currency": "GBP",
"source_merchant_id": "1000001",
"destination_merchant_id": "1000002",
"amount": 350,
"transfer_category_code": 1,
"reference": "REF-100245-DLV"
}Note that in both webhooks, amount is in minor units, currency is not present for every transfer, and the merchant IDs can be strings or numbers.

