curl --request GET \
--url https://api.pay.aptahq.com/healthconst options = {method: 'GET'};
fetch('https://api.pay.aptahq.com/health', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/health"
response = requests.get(url)
print(response.text){
"code": 200,
"message": "OK",
"data": {
"status": "ok",
"release": "0.1.0"
}
}Liveness — status and release only
The liveness check — point your uptime monitor here. Unauthenticated and cheap, so a pinger can hit it every minute without credentials.
L-01 (security audit): trimmed to status and release only. This endpoint used to also report uptime, the build version stamp (including a git sha), whether the build is in test mode, and which providers have a registered adapter — all of it readable by anyone on the public internet with no credentials. None of that is directly exploitable, but it is exactly the kind of reconnaissance a pre-attack probe collects for free, and an anonymous caller has no operational need for more than “is it up”. The full body moved to GET /health/detail, which requires a signed tenant request — see that operation below.
release stays here deliberately: it is the semver CHANGELOG.md already describes publicly, and “which release is live” is a legitimate unauthenticated question for a status dashboard — unlike the build stamp, test-mode flag, or provider roster, it discloses nothing about internal topology.
The route is /health, not /healthz. The conventional spelling is unreachable on the deployed host: something in front of Cloud Run matches the literal lowercase /healthz and returns its own 404 before the request arrives (verified 2026-08-29 — /healthz/ and /HEALTHZ both returned 200 from this app, and the same build served /healthz as 200 over a local socket, which is what ruled out the application). It was removed rather than kept as an alias, so that no route behaves differently across deployments.
curl --request GET \
--url https://api.pay.aptahq.com/healthconst options = {method: 'GET'};
fetch('https://api.pay.aptahq.com/health', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.pay.aptahq.com/health"
response = requests.get(url)
print(response.text){
"code": 200,
"message": "OK",
"data": {
"status": "ok",
"release": "0.1.0"
}
}Response
Healthy.
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