API reference
Usage
Counts of authenticated calls per day, key and capability. Metered, not billed; an estimate exists only when a price table is configured.
GET /v1/usage/export
Export usage rows
Exports the caller's counted calls, one row per day, key and capability, as JSON or CSV.
format csv returns text/csv as an attachment with the same four columns. The window is inclusive UTC days, at most 366; the default is the last 30 days.
Parameters
formatquery, string- Default
"json". fromquery, string or null- No description in the schema.
toquery, string or null- No description in the schema.
Request body
None.
Example request
curl
curl -sS -X GET "https://api.afaprotocol.com/v1/usage/export?from=2026-08-03&to=2026-09-01&format=json" \
-H "X-API-Key: afa-beta-EXAMPLE-e4qs"
Python
import requests
API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
params = {
"format": "json",
"from": "2026-08-03",
"to": "2026-09-01"
}
r = requests.get(f"{API}/v1/usage/export", headers=headers, params=params, timeout=30)
r.raise_for_status()
print(r.json())
Example response
HTTP 200
{
"billing_status": "metered_not_billed",
"from": "2026-08-03",
"row_count": 1,
"rows": [
{
"calls": 412,
"capability": "events:write",
"day": "2026-09-01",
"key_id": "7a1c3e5b-2d4f-4a6b-9c8e-0f1a2b3c4d5e"
}
],
"to": "2026-09-01",
"total_calls": 412,
"user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_token / invalid_or_expired_api_key | No credential, an expired session, or a revoked or expired key. |
| 403 | scope_missing | A key limited by scopes lacks usage; the body names it. |
| 400 | invalid_format / invalid_date / from_after_to / range_too_wide | A parameter did not parse or the window is out of bounds. |
What would show this is false
Export the same window as json and csv: the row counts match and the CSV header is day,key_id,capability,calls.
GET /v1/usage/summary
Monthly totals
Totals the caller's counted calls for one month by capability and by key.
Counts, does not charge. The estimate exists only when the operator configured a price table; otherwise estimate is null and estimate_status says why.
Parameters
monthquery, string or null- YYYY-MM, default: current UTC month
Request body
None.
Example request
curl
curl -sS -X GET "https://api.afaprotocol.com/v1/usage/summary?month=2026-09" \
-H "X-API-Key: afa-beta-EXAMPLE-e4qs"
Python
import requests
API = "https://api.afaprotocol.com"
headers = {"X-API-Key": "afa-beta-EXAMPLE-e4qs"}
params = {
"month": "2026-09"
}
r = requests.get(f"{API}/v1/usage/summary", headers=headers, params=params, timeout=30)
r.raise_for_status()
print(r.json())
Example response
HTTP 200
{
"billing_status": "metered_not_billed",
"estimate": null,
"estimate_status": "no_price_table",
"month": "2026-09",
"per_capability": {
"events:write": 412,
"grants": 38,
"verify": 9
},
"per_key": {
"7a1c3e5b-2d4f-4a6b-9c8e-0f1a2b3c4d5e": 459
},
"total_calls": 459,
"user_id": "2f6e1a0c-9b4d-4e8a-8c31-5d7f0a2b9c14"
}
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_token / invalid_or_expired_api_key | No credential, an expired session, or a revoked or expired key. |
| 403 | scope_missing | A key limited by scopes lacks usage; the body names it. |
| 400 | invalid_month | month must be YYYY-MM. |
What would show this is false
Sum per_capability and sum per_key: both equal total_calls. Calls to sign-in, health and cron paths are not counted because they map to no capability.