curl --request GET \
--url https://api.pay.aptahq.com/health/detail \
--header 'X-AptaPay-Signature: <api-key>'const options = {method: 'GET', headers: {'X-AptaPay-Signature': '<api-key>'}};
fetch('https://api.pay.aptahq.com/health/detail', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/health/detail"
headers = {"X-AptaPay-Signature": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text){
"code": 200,
"message": "OK",
"data": {
"status": "ok",
"uptime_seconds": 3814,
"version": "2026-08-26T09:12:44.812Z (git: 6fa9948)",
"release": "0.1.0",
"is_test_environment": true,
"provider_environment": "production",
"providers": {
"eversend": "registered",
"flutterwave": "not_registered",
"stripe": "not_registered",
"fake": "registered"
}
}
}Full health detail — version, test-mode and provider registration
The full body /health used to serve, now behind tenant auth (L-01). Any authenticated tenant may read it — this is diagnostic information about the GATEWAY, not about any tenant’s own data, so there is no capability check beyond a valid signed request.
Answers “is the gateway healthy” in detail: uptime, the deployed version stamp, the release semver, whether the build is in test mode, and which providers have a registered adapter.
version and release answer different questions. version is a build-time stamp (ISO timestamp plus the git sha it was built from) that changes on every build — compare it against the build you just ran to confirm a deploy actually landed rather than silently no-opping. release is the semantic version cut by hand, and is the one described in CHANGELOG.md; it changes only when a release is deliberately cut, so several deploys can share one release while each has its own version.
is_test_environment: true on production is a real alarm — it means a test build shipped. Provider status reports whether an adapter is compiled in and registered, NOT network reachability: a health check that called out to providers would let a caller trigger outbound requests on demand.
provider_environment is always production and is reported so it is never assumed. The upstream provider has no sandbox — one host serves live and test traffic alike — so is_test_environment: true means “a real account with a low balance and a hard amount ceiling”, NOT “a safe place to experiment”. Test-mode transactions move real money.
curl --request GET \
--url https://api.pay.aptahq.com/health/detail \
--header 'X-AptaPay-Signature: <api-key>'const options = {method: 'GET', headers: {'X-AptaPay-Signature': '<api-key>'}};
fetch('https://api.pay.aptahq.com/health/detail', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/health/detail"
headers = {"X-AptaPay-Signature": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text){
"code": 200,
"message": "OK",
"data": {
"status": "ok",
"uptime_seconds": 3814,
"version": "2026-08-26T09:12:44.812Z (git: 6fa9948)",
"release": "0.1.0",
"is_test_environment": true,
"provider_environment": "production",
"providers": {
"eversend": "registered",
"flutterwave": "not_registered",
"stripe": "not_registered",
"fake": "registered"
}
}
}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.
Response
Healthy, with full detail.
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