curl --request PUT \
--url https://api.pay.aptahq.com/v1/beneficiaries/{id} \
--header 'Content-Type: application/json' \
--header 'X-AptaPay-Signature: <api-key>' \
--data '
{
"label": "<string>",
"bank_code": "<string>",
"network": "<string>",
"account_number": "<string>",
"confirm_destination_change": true
}
'const options = {
method: 'PUT',
headers: {'X-AptaPay-Signature': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
label: '<string>',
bank_code: '<string>',
network: '<string>',
account_number: '<string>',
confirm_destination_change: true
})
};
fetch('https://api.pay.aptahq.com/v1/beneficiaries/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/v1/beneficiaries/{id}"
payload = {
"label": "<string>",
"bank_code": "<string>",
"network": "<string>",
"account_number": "<string>",
"confirm_destination_change": True
}
headers = {
"X-AptaPay-Signature": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text){
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}{
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}{
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}Update a saved beneficiary
Updating label, bank_code or network needs no special flag. Changing account_number REQUIRES confirm_destination_change: true in the SAME request body — an accidental or hostile overwrite of a saved recipient’s destination must carry an explicit, auditable signal. Every accepted update writes an audit_log row with the last-4 digits before and after; never the full number.
curl --request PUT \
--url https://api.pay.aptahq.com/v1/beneficiaries/{id} \
--header 'Content-Type: application/json' \
--header 'X-AptaPay-Signature: <api-key>' \
--data '
{
"label": "<string>",
"bank_code": "<string>",
"network": "<string>",
"account_number": "<string>",
"confirm_destination_change": true
}
'const options = {
method: 'PUT',
headers: {'X-AptaPay-Signature': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
label: '<string>',
bank_code: '<string>',
network: '<string>',
account_number: '<string>',
confirm_destination_change: true
})
};
fetch('https://api.pay.aptahq.com/v1/beneficiaries/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/v1/beneficiaries/{id}"
payload = {
"label": "<string>",
"bank_code": "<string>",
"network": "<string>",
"account_number": "<string>",
"confirm_destination_change": True
}
headers = {
"X-AptaPay-Signature": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text){
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}{
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}{
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}Authorizations
v1={hex HMAC-SHA256} over the ten-field canonical string. Sent alongside X-AptaPay-Key, X-AptaPay-Timestamp and X-AptaPay-Nonce — all four are required. OpenAPI can only model one header per scheme, so the other three are described in the Authentication section above.
Path Parameters
Body
Response
Updated, masked.
The single response envelope, used by EVERY endpoint so a consuming app parses one shape everywhere.
200
"OK"
Present on success. Shape varies per endpoint.
Machine-readable error classification. EXACTLY ONE of terminal/retriable/ ambiguous is true. laces_api inferred this from the HTTP status and got it wrong, stranding real money twice (2026-08-15, 2026-08-16). Branch on these booleans, never on the status code:
terminal -> the provider refused. Reverse the debit and tell the user. retriable -> safe to retry with the SAME Idempotency-Key. ambiguous -> the outcome is UNKNOWN. Do NOT reverse. Poll instead.
Show child attributes
Show child attributes