curl --request POST \
--url https://sandbox-api.sakawave.example/v1/cards/{cardId}/fund \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"externalReference": "card_fund_20260814_001",
"accountId": "01K2Z3AB4D5E6F7G8H9JKMNPQR",
"amountUsd": "2500",
"fxQuoteId": "01K2Z3AB4V5W6X7Y8ZABCDEFGH"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
externalReference: 'card_fund_20260814_001',
accountId: '01K2Z3AB4D5E6F7G8H9JKMNPQR',
amountUsd: '2500',
fxQuoteId: '01K2Z3AB4V5W6X7Y8ZABCDEFGH'
})
};
fetch('https://sandbox-api.sakawave.example/v1/cards/{cardId}/fund', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox-api.sakawave.example/v1/cards/{cardId}/fund"
payload = {
"externalReference": "card_fund_20260814_001",
"accountId": "01K2Z3AB4D5E6F7G8H9JKMNPQR",
"amountUsd": "2500",
"fxQuoteId": "01K2Z3AB4V5W6X7Y8ZABCDEFGH"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "01K2Z3AB4R5S6T7V8WXYZABCDE",
"cardId": "01K2Z3AB4S5T6V7W8XYZABCDEF",
"type": "funding",
"status": "pending",
"sourceCurrency": "NGN",
"destinationCurrency": "USD",
"sourceAmount": "4000000",
"destinationAmount": "2500",
"failureCode": null,
"failureReason": null,
"completedAt": null,
"createdAt": "2026-08-14T09:11:40.000Z",
"updatedAt": "2026-08-14T09:12:00.000Z"
}{
"statusCode": 400,
"message": "Must be a valid identifier.",
"code": "validation_failed",
"errors": [
{
"message": "Must be a valid identifier.",
"field": "accountId",
"code": "custom",
"path": [
"accountId"
]
}
]
}{
"statusCode": 401,
"code": "INVALID_API_KEY",
"message": "Invalid or inactive API credentials."
}{
"statusCode": 403,
"message": "International wallets for your customers are not available yet. Your own approval cannot be used for a customer wallet.",
"code": "international_customer_wallet_not_supported",
"currency": "USD"
}{
"statusCode": 404,
"code": "resource_not_found",
"message": "Resource not found."
}{
"statusCode": 409,
"code": "resource_conflict",
"message": "The request conflicts with the current resource state."
}{
"statusCode": 429,
"message": "Too many API requests. Try again later.",
"code": "api_key_rate_limit_exceeded",
"retryAfterSeconds": 17
}{
"statusCode": 500,
"code": "internal_server_error",
"message": "An unexpected error occurred."
}{
"statusCode": 503,
"code": "provider_unavailable",
"message": "We could not issue an account number just now. Try again shortly."
}Fund a card
Moves USD from one of your accounts onto a card. Returns the operation, which may still be pending while the provider settles it.
curl --request POST \
--url https://sandbox-api.sakawave.example/v1/cards/{cardId}/fund \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"externalReference": "card_fund_20260814_001",
"accountId": "01K2Z3AB4D5E6F7G8H9JKMNPQR",
"amountUsd": "2500",
"fxQuoteId": "01K2Z3AB4V5W6X7Y8ZABCDEFGH"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
externalReference: 'card_fund_20260814_001',
accountId: '01K2Z3AB4D5E6F7G8H9JKMNPQR',
amountUsd: '2500',
fxQuoteId: '01K2Z3AB4V5W6X7Y8ZABCDEFGH'
})
};
fetch('https://sandbox-api.sakawave.example/v1/cards/{cardId}/fund', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox-api.sakawave.example/v1/cards/{cardId}/fund"
payload = {
"externalReference": "card_fund_20260814_001",
"accountId": "01K2Z3AB4D5E6F7G8H9JKMNPQR",
"amountUsd": "2500",
"fxQuoteId": "01K2Z3AB4V5W6X7Y8ZABCDEFGH"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"id": "01K2Z3AB4R5S6T7V8WXYZABCDE",
"cardId": "01K2Z3AB4S5T6V7W8XYZABCDEF",
"type": "funding",
"status": "pending",
"sourceCurrency": "NGN",
"destinationCurrency": "USD",
"sourceAmount": "4000000",
"destinationAmount": "2500",
"failureCode": null,
"failureReason": null,
"completedAt": null,
"createdAt": "2026-08-14T09:11:40.000Z",
"updatedAt": "2026-08-14T09:12:00.000Z"
}{
"statusCode": 400,
"message": "Must be a valid identifier.",
"code": "validation_failed",
"errors": [
{
"message": "Must be a valid identifier.",
"field": "accountId",
"code": "custom",
"path": [
"accountId"
]
}
]
}{
"statusCode": 401,
"code": "INVALID_API_KEY",
"message": "Invalid or inactive API credentials."
}{
"statusCode": 403,
"message": "International wallets for your customers are not available yet. Your own approval cannot be used for a customer wallet.",
"code": "international_customer_wallet_not_supported",
"currency": "USD"
}{
"statusCode": 404,
"code": "resource_not_found",
"message": "Resource not found."
}{
"statusCode": 409,
"code": "resource_conflict",
"message": "The request conflicts with the current resource state."
}{
"statusCode": 429,
"message": "Too many API requests. Try again later.",
"code": "api_key_rate_limit_exceeded",
"retryAfterSeconds": 17
}{
"statusCode": 500,
"code": "internal_server_error",
"message": "An unexpected error occurred."
}{
"statusCode": 503,
"code": "provider_unavailable",
"message": "We could not issue an account number just now. Try again shortly."
}active or frozen. Any other status is refused with 409 card_not_usable.
amountUsd is in USD minor units — "2500" is $25.00 — whatever currency your account is in. When the account is not USD, quote first and pass fxQuoteId.
externalReference is the idempotency key across all card operations, not just funding. Reusing one returns the existing operation of whatever type it was.Error codes
| Status | code | Cause |
|---|---|---|
400 | validation_failed | A field failed validation. |
403 | card_client_account_required | The account is a customer wallet. |
409 | card_not_usable | The card is not active or frozen. |
409 | card_account_ineligible | The account is missing, inactive, or cannot be debited. |
409 | card_fx_quote_required | The account is not USD and no quote was supplied. |
409 | card_fx_quote_invalid | The quote is expired, spent, or bound to a different account, card, or operation. |
409 | card_fx_quote_amount_mismatch | The quote was created for a different USD amount. |
409 | insufficient_funds | The account cannot cover the amount. |
503 | card_provider_unavailable | The card provider could not be reached. |
401 | INVALID_API_KEY | The key is missing, invalid, inactive, expired, from the other environment, or blocked by its IP allowlist. |
404 | card_not_found | No such card for this business. |
429 | api_key_rate_limit_exceeded | The per-minute limit for this key was exceeded. |
Authorizations
A secret API key, sent as Authorization: Bearer sk_test_… in sandbox or Bearer sk_live_… in live.
Path Parameters
Card ULID. A 26-character ULID.
26^[0-7][0-9A-HJKMNP-TV-Z]{25}$"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
Body
1 - 120The account funding the card, or receiving the withdrawal. One of your own, never a customer wallet.
26^[0-7][0-9A-HJKMNP-TV-Z]{25}$"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
A positive integer number of minor units.
^[1-9]\d*$"2500000"
Required when the account is not USD.
26^[0-7][0-9A-HJKMNP-TV-Z]{25}$"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
Response
Successful response.
A 26-character ULID.
26^[0-7][0-9A-HJKMNP-TV-Z]{25}$"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
A 26-character ULID.
26^[0-7][0-9A-HJKMNP-TV-Z]{25}$"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
issuance, funding, withdrawal, termination created, submitting, pending, completed, failed NGN, USD, GBP, EUR, GHS, ZAR, UGX, CAD, MXN, AED, BTC, ETH, USDT, USDC NGN, USD, GBP, EUR, GHS, ZAR, UGX, CAD, MXN, AED, BTC, ETH, USDT, USDC An integer number of the asset’s smallest unit. Use this value for arithmetic.
^-?\d+$"2500000"
An integer number of the asset’s smallest unit. Use this value for arithmetic.
^-?\d+$"2500000"
"2026-08-14T09:00:00.000Z"
"2026-08-14T09:00:00.000Z"
"2026-08-14T09:00:00.000Z"