Funding Test Senders
Credit a sender's deposit account with simulated funds in the test environment, so you can run order flows end to end without moving real money.
Funding Test Senders
Overview
To run a fiat-funded order end to end in the test environment you need a sender that actually holds a balance. Rather than making a real bank transfer into your test virtual account and waiting for it to settle, you can credit the account directly with simulated funds.
This is a test-environment feature only. The endpoint is disabled in production and returns 403 FORBIDDEN there. The funds it creates are simulated: they exist only in the test environment's ledger and have no real-world value.
Table of Contents
- Prerequisites
- Crediting a sender
- Confirming the balance
- Limits
- Errors
- Permissions
- Funding stablecoin senders
1. Prerequisites
- A sender that already has a deposit account in the currency you want to fund. If the sender has no account yet, provision one first with
POST /v1/senders/{senderId}/virtual-bank-accounts/{currency}/setup-request. - An API key with the
merchant:sender:writepermission (merchant:*:*also matches).
2. Crediting a sender
curl -X POST \
'https://api.stg.mesta.xyz/v1/senders/<SENDER_ID>/accounts/mock-deposit?amount=50¤cy=USD' \
-H 'x-api-key: <API_KEY_ID>' \
-H 'x-api-secret: <API_KEY_SECRET>'Both values are query parameters — there is no request body.
| Parameter | Required | Description |
|---|---|---|
amount | Yes | Amount to credit, in the deposit currency. Must be greater than 0 and no more than 200 per request. |
currency | Technically no — in practice yes | Currency of the deposit account to credit, for example USD, EUR, GBP or MXN. The sender must already have a deposit account in this currency. Omitting it makes the service guess a currency from the sender's profile, which can resolve a different deposit account than you intend and fail with NO_DEPOSIT_BANK_ACCOUNT_FOUND. Always pass it explicitly. |
A successful call returns 201:
{
"requestId": 177021679
}That response only confirms that the simulated deposit was accepted. It does not mean the balance has moved yet — see the next section.
To fund more than 200, repeat the call:
for i in 1 2 3 4; do
curl -X POST \
"https://api.stg.mesta.xyz/v1/senders/<SENDER_ID>/accounts/mock-deposit?amount=200¤cy=USD" \
-H 'x-api-key: <API_KEY_ID>' \
-H 'x-api-secret: <API_KEY_SECRET>'
doneMind the rate limit in section 4 — that loop consumes 4 of your 10 requests.
3. Confirming the balance
The credit is applied asynchronously. The endpoint hands the deposit off to the banking provider's simulator, and the balance updates once the resulting webhook is processed — normally within a few seconds.
Poll the balances endpoint until the amount appears:
curl 'https://api.stg.mesta.xyz/v1/senders/<SENDER_ID>/balances' \
-H 'x-api-key: <API_KEY_ID>' \
-H 'x-api-secret: <API_KEY_SECRET>'{
"data": [
{ "currency": "USD", "balance": "50.00" }
],
"requestId": 177021680
}If the balance has not moved after roughly a minute, treat the deposit as failed rather than slow, and contact your Mesta representative with the requestId from the original call.
4. Limits
| Limit | Value |
|---|---|
| Maximum per request | 200, in the deposit currency |
| Minimum per request | Greater than 0 |
| Requests | 10 per 2 hours, for this endpoint, per source IP address |
Three things about the rate limit are worth knowing before you script against it:
- The quota is keyed on your source IP, not your API key. Everything calling from behind the same network egress address — your whole CI fleet, your whole office — draws on one shared bucket of 10. Rotating API keys does not get you a fresh quota.
- Every rejected request counts towards the quota. Not just validation failures: a
401from a bad key, a403from a missing permission, a404from a wrong sender ID, and a400from a bad amount all consume one of the 10. Get a single call working by hand before putting one in a loop. - The window is 2 hours, not minutes. Exhausting the quota means waiting, so budget your calls. Combined with the 200 cap, one source IP can credit at most 2,000 per currency per 2 hours.
When the quota is exhausted the endpoint returns 429:
{
"error": {
"CODE": "REQUEST_THROTTLED",
"MESSAGE": "You have made too many requests. Please try again later.",
"DETAILS": {
"retryAfterMs": 5423118
}
},
"requestId": 177021681
}DETAILS.retryAfterMs is how long to wait, in milliseconds, before the next request is accepted.
5. Errors
| Status | Code | Meaning |
|---|---|---|
400 | INVALID_MOCK_DEPOSIT_AMOUNT | amount is missing, zero, negative, or not a number. |
400 | MOCK_DEPOSIT_AMOUNT_LIMIT_EXCEEDED | amount is above the 200 per-request cap. Split it across several calls. |
400 | NO_DEPOSIT_BANK_ACCOUNT_FOUND | The sender has no deposit account in the requested currency. Provision one first. |
400 | MOCK_DEPOSIT_NOT_SUPPORTED_FOR_ACCOUNT | The sender's deposit account is held with a banking provider that has no deposit simulator. Fund a different currency, or make a real test transfer into the account. |
403 | FORBIDDEN | The API key lacks merchant:sender:write, or the call was made against production, where the endpoint is disabled. |
404 | ENTITY_NOT_FOUND | No sender with that ID exists under your merchant account. |
429 | REQUEST_THROTTLED | Rate limit exhausted. See section 4. |
6. Permissions
The API key must carry merchant:sender:write. A wildcard merchant:*:* key also matches. Without it, every call returns 403 FORBIDDEN.
Scoping is implicit: you can only fund senders that belong to your own merchant account. A sender ID belonging to another merchant resolves as 404, not 403.
7. Funding stablecoin senders
This endpoint funds fiat deposit accounts. If you are testing a stablecoin-funded order instead, you do not need it — send test USDC or USDT to the sender's deposit wallet address from a testnet faucet. See Getting Test Tokens for faucet links and network details.
Updated about 22 hours ago

