Responses
Every AfriHex API response follows the same envelope, so client code is uniform across every endpoint.
The response envelope
{
"success": true,
"data": { },
"meta": { "request_id": "…", "cached": false, "latency": "12.3ms" }
}
| Field | Type | Definition |
|---|---|---|
success | boolean | true for 2xx, false for error responses |
data | object | The endpoint's payload — the shape is documented per endpoint |
error | object | Present only on failure: { code, message } (see Errors) |
meta | object | Response metadata (see below) |
The meta object
Every wrapped response includes meta:
| Field | Type | Definition |
|---|---|---|
request_id | string | Unique ID for the request — include it when contacting support |
cached | boolean | true when the response was served from cache |
latency | string | Server-side processing time (e.g. 12.3ms) |
Two exceptions to the envelope:
- Map tiles (
/v2/map/tiles) and cell GeoJSON (/v2/hexcode/{code}/geojson) return raw GeoJSON —FeatureCollection/Feature— so you can hand them straight to Leaflet/Mapbox. - Location ping (
/v2/location/ping) returns a minimal flat body to save mobile bandwidth.
HTTP status codes
The API uses conventional HTTP status codes. In general: 2xx success, 4xx
client errors (fix the request), 5xx server errors (retry with backoff).
| Code | Meaning | Definition |
|---|---|---|
| 200 | Success | The request was processed and the result is in data |
| 201 | Created | The resource was created (e.g. consent grant, webhook configure) |
| 202 | Accepted | The request was accepted for processing (e.g. async bulk jobs) |
| 204 | No Content | Success with an empty body |
| 400 | Bad Request | The request could not be parsed, or a parameter/body was invalid |
| 401 | Unauthorized | API key missing or invalid (MISSING_API_KEY, INVALID_API_KEY) |
| 403 | Forbidden | Authenticated but not allowed (e.g. account-scoped key required) |
| 404 | Not Found | The resource or identifier doesn't resolve (NOT_FOUND) |
| 405 | Method Not Allowed | The HTTP verb isn't supported on this endpoint |
| 409 | Conflict | Duplicate resource, or a state conflict |
| 422 | Unprocessable Entity | Semantically valid but failed a business rule |
| 429 | Rate Limited | Quota or throttle exceeded (RATE_LIMITED) |
| 500 | Internal Server Error | Unexpected server error — retry, contact support if persistent |
| 502 | Bad Gateway | An upstream dependency failed (UPSTREAM_ERROR) |
| 503 | Service Unavailable | A required service isn't configured or is down (e.g. DB_UNAVAILABLE, PARSER_UNAVAILABLE, LANGUAGE_QUOTA) |
Errors
On failure, success is false and the error object describes what happened:
{
"success": false,
"error": {
"code": "INVALID_COORDINATES",
"message": "query parameters 'lat' and 'lng' are required"
}
}
| Field | Type | Definition |
|---|---|---|
code | string | A stable machine-readable identifier — branch on this, not the message |
message | string | A human-readable description (wording may change) |
Errors fall into three families:
| Family | Codes (examples) |
|---|---|
| Auth — credentials | MISSING_API_KEY, INVALID_API_KEY, ACCOUNT_KEY_REQUIRED |
| Params — the request itself | INVALID_COORDINATES, INVALID_HEX_CODE, INVALID_ADDRESS, INVALID_BODY, MISSING_BBOX, VALIDATION_ERROR, OUT_OF_BOUNDS |
| System — the service | NOT_FOUND, UPSTREAM_ERROR, DB_UNAVAILABLE, PARSER_UNAVAILABLE, LANGUAGE_QUOTA, RATE_LIMITED, INTERNAL |
Guidance:
- Read
code, notmessage— messages may be reworded; codes are stable. - 404 vs 502 —
404means the input simply didn't resolve (a normal outcome);502means the service failed to answer. Treat them differently. - 429s — wait for
X-RateLimit-Reset(orRetry-After) before retrying. ACCOUNT_KEY_REQUIRED— the tenant-scoped endpoints (KYC, monitoring, consent, collections, service areas, webhooks, AML) require an account-scoped API key, not a legacy one.
Pagination
Two pagination styles are used:
- Limit/offset —
?limit=&offset=on list endpoints;dataincludeshas_moreand anext_cursorwhere applicable. - Cursor —
/v2/nearbysupports cursor-based paging vianext_cursor; pass it back ascursorfor the next page.
Bulk endpoints return a summary block (total, found, not_found) plus
per-row results, so partial failures are easy to report.
Response headers
| Header | Definition |
|---|---|
X-Request-ID | Echoes meta.request_id for tracing |
X-RateLimit-Limit | Max requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in the window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | On 429 — seconds to wait before retrying |