Authentication
All /v2/* endpoints require an API key. Authenticate by sending your key in
the X-API-Key header on every request:
curl "https://api.afrihex.com/v2/lookup?address=GA-142-7281" \
-H "X-API-Key: $AFRIHEX_API_KEY"
Get a key — self-service signup
Create a free-tier key in one call. No password needed. The key is returned once and emailed to you, so store it securely.
POST /v2/self/signup
Request object:
| Parameter | Type | Required | Definition |
|---|---|---|---|
name | string | required | Your name or app name |
email | string | required | Where the key and welcome email are sent |
curl -X POST "https://api.afrihex.com/v2/self/signup" \
-H "Content-Type: application/json" \
-d '{
"name": "Your App",
"email": "you@example.com"
}'
{
"success": true,
"data": {
"id": 1,
"name": "Your App",
"email": "you@example.com",
"key": "9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f",
"key_prefix": "9f8e7d6c...",
"tier": "free",
"daily_limit": 100,
"expires_at": null,
"note": "Store this key securely — it will not be shown again."
}
}
Set it as an environment variable:
export AFRIHEX_API_KEY="9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f"
Auth errors
If the key is missing, the API returns 401:
{
"success": false,
"error": { "code": "MISSING_API_KEY", "message": "X-API-Key header is required" }
}
If the key is unknown, revoked, or expired:
{
"success": false,
"error": { "code": "INVALID_API_KEY", "message": "invalid or revoked API key" }
}
Some endpoints also require an account-scoped key — a legacy key returns:
{
"success": false,
"error": { "code": "ACCOUNT_KEY_REQUIRED", "message": "this endpoint requires an account API key; legacy keys without an account identity cannot access tenant data" }
}
Key management
| Endpoint | Purpose |
|---|---|
POST /v2/self/signup | Create a free-tier key |
GET /v2/me | View your key details and usage |
POST /v2/me/rotate | Rotate your key (old key is revoked) |
DELETE /v2/me/key | Revoke your key |
GET /v2/usage | View your usage |
Rotating or revoking a key takes effect immediately:
# View your key metadata + usage
curl "https://api.afrihex.com/v2/me" -H "X-API-Key: $AFRIHEX_API_KEY"
# Rotate (old key is revoked; new key returned once)
curl -X POST "https://api.afrihex.com/v2/me/rotate" -H "X-API-Key: $AFRIHEX_API_KEY"
# Revoke your key
curl -X DELETE "https://api.afrihex.com/v2/me/key" -H "X-API-Key: $AFRIHEX_API_KEY"
# Check usage against your plan
curl "https://api.afrihex.com/v2/usage" -H "X-API-Key: $AFRIHEX_API_KEY"
Keep keys secret — never commit them to source control, and never send them from client-side code where users can see them.
App-user accounts
Separate from a static developer key, the platform also issues per-user tokens for mobile and web apps — one per signed-in user, not one key shared by the whole app:
| Endpoint | Purpose |
|---|---|
POST /v2/auth/login | Email/password sign-in, returns a personal token |
POST /v2/auth/google/mobile | Verify a Google ID token server-side and get a personal token (Android / iOS, no redirect) |
POST /v2/me/password | Attach a password to an OAuth-only account, or change an existing one |
POST /v2/auth/forgot-password | Email a one-time, hashed, 30-minute password reset token |
POST /v2/auth/reset-password | Reset the password with the emailed token |
The token these return is an X-API-Key value, scoped to that one
user — send it in the same header as any other key; it is not a separate
bearer/session scheme. This is the recommended pattern for a mobile app: mint
a token per signed-in user rather than embedding your static developer key in
the app bundle, where it's extractable and shared by every install. See
Mobile Integration for the full pattern.
Banking Suite access
Banking Suite — collections/*, analytics/portfolio-risk, verify/schedule*,
and banking/audit-log — is provisioned per institution, separately from
your plan tier. A Free or Pro key doesn't get it just by having higher rate
limits; it's granted explicitly. An account without it gets:
{
"success": false,
"error": {
"code": "BANKING_ACCESS_REQUIRED",
"message": "this account is not provisioned for Banking Suite — contact us to get set up"
}
}
If your account has an IP allowlist configured (optional, ask us to set one up), a request from outside it gets:
{
"success": false,
"error": {
"code": "IP_NOT_ALLOWED",
"message": "this request's IP address is not on the account's allowlist"
}
}
POST /v2/kyc/verify and POST /v2/verify/proximity are not gated by
this — any authenticated account can call them, same as before. They're
shared with the general-purpose Address Verify product (the embeddable
widget), so Banking Suite provisioning only applies to the lending-specific
tools: collection zone tracking, portfolio risk, re-verification scheduling,
and the audit-log endpoint. See Identity & KYC,
Collections & Service Areas, and
Risk & Fraud for what each covers.
To get an account provisioned (with or without an IP allowlist), contact developers@afrihex.com.
Plan tiers
| Tier | Requests / 24h | Best for |
|---|---|---|
| Free | 100 | Evaluation and prototypes |
| Basic | 5,000 | Production apps getting started |
| Pro | 20,000 | Growing applications |
| Enterprise | 100,000+ | Banks and large platforms |
See Rate Limits for how quotas are enforced and the headers to monitor.
Local development
In development (ENVIRONMENT=development) authentication may be disabled on
self-hosted instances. Public deployments always require a key.