Skip to main content

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" }
}
FieldTypeDefinition
successbooleantrue for 2xx, false for error responses
dataobjectThe endpoint's payload — the shape is documented per endpoint
errorobjectPresent only on failure: { code, message } (see Errors)
metaobjectResponse metadata (see below)

The meta object

Every wrapped response includes meta:

FieldTypeDefinition
request_idstringUnique ID for the request — include it when contacting support
cachedbooleantrue when the response was served from cache
latencystringServer-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).

CodeMeaningDefinition
200SuccessThe request was processed and the result is in data
201CreatedThe resource was created (e.g. consent grant, webhook configure)
202AcceptedThe request was accepted for processing (e.g. async bulk jobs)
204No ContentSuccess with an empty body
400Bad RequestThe request could not be parsed, or a parameter/body was invalid
401UnauthorizedAPI key missing or invalid (MISSING_API_KEY, INVALID_API_KEY)
403ForbiddenAuthenticated but not allowed (e.g. account-scoped key required)
404Not FoundThe resource or identifier doesn't resolve (NOT_FOUND)
405Method Not AllowedThe HTTP verb isn't supported on this endpoint
409ConflictDuplicate resource, or a state conflict
422Unprocessable EntitySemantically valid but failed a business rule
429Rate LimitedQuota or throttle exceeded (RATE_LIMITED)
500Internal Server ErrorUnexpected server error — retry, contact support if persistent
502Bad GatewayAn upstream dependency failed (UPSTREAM_ERROR)
503Service UnavailableA 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"
}
}
FieldTypeDefinition
codestringA stable machine-readable identifier — branch on this, not the message
messagestringA human-readable description (wording may change)

Errors fall into three families:

FamilyCodes (examples)
Auth — credentialsMISSING_API_KEY, INVALID_API_KEY, ACCOUNT_KEY_REQUIRED
Params — the request itselfINVALID_COORDINATES, INVALID_HEX_CODE, INVALID_ADDRESS, INVALID_BODY, MISSING_BBOX, VALIDATION_ERROR, OUT_OF_BOUNDS
System — the serviceNOT_FOUND, UPSTREAM_ERROR, DB_UNAVAILABLE, PARSER_UNAVAILABLE, LANGUAGE_QUOTA, RATE_LIMITED, INTERNAL

Guidance:

  • Read code, not message — messages may be reworded; codes are stable.
  • 404 vs 502404 means the input simply didn't resolve (a normal outcome); 502 means the service failed to answer. Treat them differently.
  • 429s — wait for X-RateLimit-Reset (or Retry-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; data includes has_more and a next_cursor where applicable.
  • Cursor/v2/nearby supports cursor-based paging via next_cursor; pass it back as cursor for 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

HeaderDefinition
X-Request-IDEchoes meta.request_id for tracing
X-RateLimit-LimitMax requests allowed in the window
X-RateLimit-RemainingRequests remaining in the window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterOn 429 — seconds to wait before retrying