Skip to main content

Identity & KYC

Part of AfriHex Verify — verify a customer's address before you lend, onboard, or deliver to them. AfriHex turns an address or a live GPS fix into a verifiable identity signal: structured address components, a confidence score, risk signals, fraud checks, and optionally a cryptographically signed certificate you can keep for compliance.

Verification is usually the start of a longer relationship, not the end: once a customer is onboarded, Location Monitoring and Collections & Service Areas (both part of AfriHex Operate) are what tell you if they've moved.

The quality score​

Every resolved location carries quality_score (0.0–1.0), computed from data completeness — street, area, postcode, bounding box, coordinates. Use it as your threshold for "verified enough":

  • ≥ 0.8 — strong address, suitable for KYC without further checks.
  • 0.5 – 0.8 — usable, but consider corroborating evidence.
  • < 0.5 — sparse; escalate for manual review.

Verify an address (KYC)​

POST /v2/kyc/verify accepts four input methods. Pick the one that matches the data you have:

Methodlocation you send
gps_fixlat + lng from the customer's device
hex_codea hex code (e.g. from an earlier session)
gps_codea GhanaPostGPS code like GA-142-7281
manualcoords you type-checked yourself (lowest trust)

Request object — POST /v2/kyc/verify:

ParameterTypeRequiredDefinition
customer_idstringrequiredYour customer identifier
methodstringrequiredgps_fix, manual, hex_code, or gps_code
locationobjectrequiredInput matching the method: {lat,lng}, {hex_code}, or {gps_code}
consent_tokenstringrequiredThe consent token (from monitoring consent)
device_idstringoptionalDevice identifier, for fraud correlation
curl -X POST "https://api.afrihex.com/v2/kyc/verify" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_123",
"method": "gps_code",
"location": { "gps_code": "GA-142-7281" }
}'
{
"success": true,
"data": {
"verification_id": "uuid",
"verified": true,
"hex_code": "AF-GH-7-...",
"ghanapost_code": "GA-142-7281",
"address": { "region": "Greater Accra", "district": "Accra Metropolitan", "area": "Accra Central" },
"quality_score": 0.91,
"verification": { "method": "gps_code", "accuracy_meters": 250, "confidence": "high" },
"risk_signals": {
"known_residential_area": true,
"address_density": "high",
"previously_verified_by_others": true
}
}
}

Proximity verification​

POST /v2/verify/proximity is for the moment you actually meet the customer: compare their declared address with the live GPS fix from their device and get a confidence score plus a device-integrity report (mock-location detection, provider, accuracy, IP-geo consistency).

curl -X POST "https://api.afrihex.com/v2/verify/proximity" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_123",
"consent_token": "tok_...",
"declared_address": "GA-142-7281",
"device_location": {
"lat": 5.5561,
"lng": -0.1962,
"gps_accuracy_m": 12,
"is_mock_location": false
}
}'
{
"success": true,
"data": {
"verification_id": "6f3c…",
"result": "NEAR",
"verified": true,
"confidence": 0.97,
"declared_address": {
"gps_code": "GA1427281",
"region": "Greater Accra",
"district": "Accra",
"area": "West Ridge",
"postcode": "GA142"
},
"proximity": { "distance_m": 18.4, "within_threshold": true },
"integrity": {
"mock_location": "NOT_DETECTED",
"gps_accuracy": "GOOD",
"provider": "gps",
"ip_geo_match": "MATCH"
},
"timestamp": "2026-08-05T15:30:00Z"
}
}

The response returns result: NEAR | FAR, verified, confidence, and the integrity factors. verified is true only when the device is NEAR and confidence ≥ 0.6.

Request object — POST /v2/verify/proximity:

ParameterTypeRequiredDefinition
customer_idstringrequiredYour customer identifier
consent_tokenstringrequiredThe consent token
declared_addressstringrequiredThe customer's declared GhanaPostGPS code
device_locationobjectrequiredThe device's live fix — {lat, lng} plus optional integrity fields below
device_idstringoptionalDevice identifier
device_signalsobjectoptionale.g. { "timezone": "Africa/Accra" }

device_location optional integrity fields: gps_accuracy_m, altitude_m, speed_mps, bearing_deg, location_provider (gps/network/fused/ passive), is_mock_location, location_age_ms. When absent, the matching integrity check reports NOT_PROVIDED instead of failing.

Signed certificates​

When a verification passes, AfriHex can issue an Ed25519-signed certificate — a shareable, independently verifiable artifact for your records or a regulator:

# Get a verification certificate
curl "https://api.afrihex.com/v2/certificates/{id}" \
-H "X-API-Key: $AFRIHEX_API_KEY"

# Public verification (no API key needed) — an auditor can check any cert
curl "https://api.afrihex.com/v2/certificates/{id}/verify"

The public verification key is published at /.well-known/verification-key.json, so anyone can verify a certificate without an account.

{
"success": true,
"data": {
"certificate_id": "cert_…",
"valid": true,
"signature_valid": true,
"subject": { "hex_code": "AF-GH-7-0GXTQD5RFZZZZ", "quality_score": 0.91 },
"issued_at": "2026-08-05T15:30:00Z",
"revoked": false
}
}

Proof of delivery​

POST /v2/pod/issue and POST /v2/pod/confirm issue a signed delivery receipt at the point of handover and confirm it with a webhook (delivery.confirmed) to your systems:

curl -X POST "https://api.afrihex.com/v2/pod/issue" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_123",
"declared_address": "GA-142-7281",
"consent_token": "tok_..."
}'
{
"success": true,
"data": {
"pod_id": "pod_9ab1",
"order_ref": "ORD-887",
"destination": { "hex_code": "AF-GH-7-0GXTQD5RFZZZZ", "label": "Customer doorstep" },
"confirmed_location": { "lat": 5.6041, "lng": -0.1953 },
"distance_m": 14.2,
"location_verified": true,
"recipient_verified": true,
"status": "issued",
"issuer": "delivery_partner"
}
}

The receipt carries a signature you can verify against the same public key, plus an optional webhook to your backend on confirmation.

Re-verification scheduling​

POST /v2/verify/schedule schedules periodic re-verification (e.g. annually for loan reviews); manage schedules with GET/DELETE /v2/verify/schedule/{id}.

Unlike kyc/verify and verify/proximity above, re-verification scheduling requires Banking Suite access — it's provisioned per institution.

Compliance notes​

  • An address match or proximity result is location evidence — not guaranteed proof of identity, ownership, residence, creditworthiness, or legality. A verified: true result means a location claim was corroborated by data of a known quality; it is one input to your own decisioning policy, never the decision itself. This applies to every building block on this page — quality scores, proximity verification, signed certificates, and proof of delivery alike. See Understanding Confidence and Verification for the same principle spelled out field-by-field, and Risk & Fraud's compliance notes for how it extends to fraud and AML/PEP signals.
  • Every verification is persisted with a verification_id, timestamp, and method, giving you an audit trail. If your account has Banking Suite access, retrieve it yourself with GET /v2/banking/audit-log.
  • Risk signals and fraud checks are advisory — combine them with your own policies. A fraud check can be degraded when a sub-check couldn't run (fewer signals than usual, not "nothing found") — see Fraud detection.
  • See Fraud & Risk for the fraud-detection layer that runs alongside KYC.

API reference​

See Identity & KYC — API Reference for every endpoint in this group.