Set default payment detail
curl --request PATCH \
--url https://sandbox-api.sakawave.example/v1/transfer-recipients/{recipientId}/payment-details/{paymentDetailId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"isDefault": true
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({isDefault: true})
};
fetch('https://sandbox-api.sakawave.example/v1/transfer-recipients/{recipientId}/payment-details/{paymentDetailId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox-api.sakawave.example/v1/transfer-recipients/{recipientId}/payment-details/{paymentDetailId}"
payload = { "isDefault": True }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"id": "01K2Z3AB4Q5R6S7T8VWXYZABCD",
"recipientId": "01K2Z3AB4G5H6J7K8MNPQRSTVW",
"routeId": "01K2Z3AB4M5N6P7Q8RSTVWXYZA",
"paymentMethod": "bank-transfer",
"currency": "KES",
"country": "KE",
"accountHolderName": "Ada Okafor",
"institutionName": "Example Bank",
"maskedIdentifier": "•••• 6789",
"isDefault": true,
"providerLocked": false,
"createdAt": "2026-08-14T09:06: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": 404,
"code": "resource_not_found",
"message": "Resource not found."
}{
"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."
}Transfer destinations
Set default payment detail
Makes this detail the recipient’s default — the one used when a destination is created without naming a detail. The previous default is demoted in the same transaction.
PATCH
/
v1
/
transfer-recipients
/
{recipientId}
/
payment-details
/
{paymentDetailId}
Set default payment detail
curl --request PATCH \
--url https://sandbox-api.sakawave.example/v1/transfer-recipients/{recipientId}/payment-details/{paymentDetailId} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"isDefault": true
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({isDefault: true})
};
fetch('https://sandbox-api.sakawave.example/v1/transfer-recipients/{recipientId}/payment-details/{paymentDetailId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://sandbox-api.sakawave.example/v1/transfer-recipients/{recipientId}/payment-details/{paymentDetailId}"
payload = { "isDefault": True }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"id": "01K2Z3AB4Q5R6S7T8VWXYZABCD",
"recipientId": "01K2Z3AB4G5H6J7K8MNPQRSTVW",
"routeId": "01K2Z3AB4M5N6P7Q8RSTVWXYZA",
"paymentMethod": "bank-transfer",
"currency": "KES",
"country": "KE",
"accountHolderName": "Ada Okafor",
"institutionName": "Example Bank",
"maskedIdentifier": "•••• 6789",
"isDefault": true,
"providerLocked": false,
"createdAt": "2026-08-14T09:06: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": 404,
"code": "resource_not_found",
"message": "Resource not found."
}{
"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."
}The body must be exactly
{ "isDefault": true }. There is no way to clear a default: a recipient with any details always has one. To change it, promote a different detail.
Error codes
| Status | code | Cause |
|---|---|---|
400 | validation_failed | An identifier is not a ULID, or the body is not { "isDefault": true }. |
404 | payment_detail_not_found | The recipient exists, but has no such detail. |
401 | INVALID_API_KEY | The key is missing, invalid, inactive, expired, from the other environment, or blocked by its IP allowlist. |
404 | recipient_not_found | No such recipient for this business, or it has been deleted. |
429 | api_key_rate_limit_exceeded | The per-minute limit for this key was exceeded. All of these operations share a 120-per-minute allowance. |
Authorizations
A secret API key, sent as Authorization: Bearer sk_test_… in sandbox or Bearer sk_live_… in live.
Path Parameters
Saved recipient ULID. A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
Payment detail ULID. A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
Body
application/json
Response
Successful response.
A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
A 26-character ULID.
Required string length:
26Pattern:
^[0-7][0-9A-HJKMNP-TV-Z]{25}$Example:
"01K2Z3AB4C5D6E7F8G9HJKMNPQ"
Available options:
bank-transfer, momo-transfer Available options:
NGN, USD, GBP, EUR, GHS, ZAR, UGX, CAD, MXN, AED, AUD, SGD, HKD, KES, TZS, BRL, CNY, XAF, PHP, USDC Required string length:
2The last four characters of the routing identifier, masked.
True when the provider holds the routing fields and they cannot be edited here.
Example:
"2026-08-14T09:00:00.000Z"