curl --request GET \
--url https://api.pay.aptahq.com/v1/float/{currency} \
--header 'X-AptaPay-Signature: <api-key>'const options = {method: 'GET', headers: {'X-AptaPay-Signature': '<api-key>'}};
fetch('https://api.pay.aptahq.com/v1/float/{currency}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/v1/float/{currency}"
headers = {"X-AptaPay-Signature": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text){
"code": 200,
"message": "OK",
"data": {
"currency": "UGX",
"available_minor": 1520000,
"reserved_minor": 30000,
"collected_minor": 2450000,
"paid_out_minor": 900000,
"provider_fees_minor": 56300
}
}{
"code": 400,
"message": "validation_failed",
"data": {
"field": "currency",
"reason": "\"XYZ\" is not a currency this gateway can represent in exact minor units."
}
}{
"code": 200,
"message": "OK",
"data": "<unknown>",
"error": {
"code": "payout_rejected_by_provider",
"message": "<string>",
"terminal": true,
"retriable": true,
"ambiguous": true,
"details": {}
}
}Your own float in one currency
The single figure a confirm screen or a top-up alert watches. Same data as GET /v1/float, narrowed to one currency so a dashboard polling a single corridor does not fetch them all.
A currency you have never used returns ZEROES, not a 404. “You hold no UGX” and “UGX is not a currency” are different answers, and only the second is an error. A dashboard for a supported corridor renders zeros rather than handling an exception.
A currency this gateway cannot represent in exact minor units IS a 400. That is a caller bug, and the gateway refuses to guess a decimal exponent rather than risk a 100x error on a zero-decimal currency.
See GET /v1/float for what each figure means — in particular why provider_fees_minor is already reflected in available_minor and must not be subtracted again, and why this is not GET /v1/balances.
curl --request GET \
--url https://api.pay.aptahq.com/v1/float/{currency} \
--header 'X-AptaPay-Signature: <api-key>'const options = {method: 'GET', headers: {'X-AptaPay-Signature': '<api-key>'}};
fetch('https://api.pay.aptahq.com/v1/float/{currency}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/v1/float/{currency}"
headers = {"X-AptaPay-Signature": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text){
"code": 200,
"message": "OK",
"data": {
"currency": "UGX",
"available_minor": 1520000,
"reserved_minor": 30000,
"collected_minor": 2450000,
"paid_out_minor": 900000,
"provider_fees_minor": 56300
}
}{
"code": 400,
"message": "validation_failed",
"data": {
"field": "currency",
"reason": "\"XYZ\" is not a currency this gateway can represent in exact minor units."
}
}{
"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
ISO 4217 code, case-insensitive. For example UGX or KES.
"UGX"
Response
The tenant's position in that currency, zeroed if it has none yet.
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