Skip to main content

Location Monitoring

Part of AfriHex Operate — the same consent-gated pings and drift/geofence machinery power both a field-ops tracking feed and, for banks, the tail end of the AfriHex Verify onboarding flow. Consent-based, background location tracking for loan portfolios: instead of re-verification calls that borrowers ignore, the bank's app reports location silently on a schedule, and AfriHex alerts you the moment a borrower drifts out of their zone.

The flow is always:

consent → register zones → pings (on a schedule) → drift detection → webhook alert

Monitoring is opt-in. Record the customer's consent, including the hash of the signed legal document:

POST /v2/consent/grant

curl -X POST "https://api.afrihex.com/v2/consent/grant" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_123",
"loan_id": "loan_456",
"scope": "background_location",
"purpose": "loan_collections",
"legal_document_hash": "sha256-of-signed-consent",
"consent_token": "tok_...",
"duration_days": 365
}'
{
"success": true,
"data": {
"consent_id": "consent_…",
"customer_id": "cust_123",
"loan_id": "loan_456",
"scope": "background_location",
"purpose": "loan_collections",
"expires_at": "2027-08-05T15:30:00Z",
"active": true
}
}

The consent_token is used on every ping. Revoke at any time with POST /v2/consent/revoke and check status with GET /v2/consent/status. Grant in bulk with POST /v2/consent/bulk-grant. To erase already-collected pings and drift events on request (rather than waiting out the retention window), see Consent-Based Location Monitoring.

Request object — POST /v2/consent/grant:

ParameterTypeRequiredDefinition
customer_idstringrequiredYour identifier for the customer
loan_idstringrequiredYour identifier for the loan
legal_document_hashstringrequiredSHA-256 of the signed consent document
consent_tokenstringrequiredUnique token used on every ping for this consent
scopestringoptionalWhat's collected — defaults to background_location
purposestringoptionalWhy — unspecified (default), loan_collections, fleet_dispatch, delivery_tracking, or safety_monitoring. A separate question from scope; surfaced back on GET /v2/consent/status
duration_daysintegeroptionalConsent validity in days (default 365)

2. Report a ping​

The bank's app (or the SDK) sends the borrower's background location fix:

POST /v2/location/ping

curl -X POST "https://api.afrihex.com/v2/location/ping" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_123",
"loan_id": "loan_456",
"lat": 5.6041,
"lng": -0.1953,
"consent_token": "tok_...",
"source": "gps"
}'
{
"success": true,
"data": { "status": "ok", "next_ping_in": "daily" }
}

The response is intentionally minimal (bandwidth matters on mobile). Send source: "none" with lat/lng of 0 as a heartbeat when the device has no GPS fix — the platform flags a borrower "going dark" instead of just seeing silence.

Request object — POST /v2/location/ping:

ParameterTypeRequiredDefinition
customer_idstringrequiredYour customer identifier
loan_idstringrequiredYour loan identifier
lat / lngnumberrequiredThe device's location fix (0 if none)
consent_tokenstringrequiredThe token from the consent grant
captured_atintegeroptionalUnix epoch ms when the fix was captured
sourcestringoptionalgps, network, or none (location off)

Schedule​

Set the ping frequency per loan — riskier or higher-value loans can ping more often:

POST /v2/monitoring/schedule with frequency: "2h" | "6h" | "daily" | "weekly". Read it with GET /v2/monitoring/schedule.

ParameterTypeRequiredDefinition
loan_idstringrequiredThe loan to schedule
customer_idstringrequiredThe customer
frequencystringrequired2h, 6h, daily, or weekly

3. Drift detection​

Each ping is compared against the borrower's registered zones. If they move outside, a drift event fires and a webhook is dispatched.

GET /v2/monitoring/drift?customer_id=cust_123

{
"success": true,
"data": {
"events": [
{
"event_id": "evt_...",
"customer_id": "cust_123",
"from_hex": "AF-GH-7-0GXTQD5RFZZZZ",
"to_hex": "AF-GH-7-0GXTQD5RJ0000",
"distance_hops": 4,
"timestamp": "2026-08-06T08:00:00Z"
}
]
}
}

Also available: GET /v2/monitoring/summary, GET /v2/monitoring/history (location timeline for dispute resolution), and GET /v2/monitoring/staleness (borrowers who've gone silent).

4. Get alerted (webhooks)​

Configure a webhook once; drift and geofence events are POSTed to you automatically:

POST /v2/webhooks/configure

curl -X POST "https://api.afrihex.com/v2/webhooks/configure" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://bank.example.com/webhooks/afrihex",
"secret": "a-long-random-secret",
"event_types": ["drift", "geofence_breach"]
}'
{
"success": true,
"data": {
"id": "webhook_…",
"url": "https://bank.example.com/webhooks/afrihex",
"event_types": ["drift", "geofence_breach"],
"active": true
}
}

Deliveries are signed with X-Webhook-Signature (HMAC-SHA256), retried with backoff, and inspectable via GET /v2/webhooks/deliveries. See Webhooks for the full contract.

Request object — POST /v2/webhooks/configure:

ParameterTypeRequiredDefinition
urlstringrequiredHTTPS endpoint that receives the events
secretstringrequiredHMAC signing secret (stored encrypted)
event_typesarray<string>optionalDefaults to ["drift"]; e.g. ["drift","geofence_breach"]

5. Geofences (beyond the home zone)​

Beyond "moved from home", define custom geofences — "alert if the borrower enters a known high-risk area", or "if they go more than 50 km from Accra":

curl -X POST "https://api.afrihex.com/v2/geofence/create" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Accra 50km zone",
"fence_type": "circle",
"center_lat": 5.6037,
"center_lng": -0.187,
"radius_km": 50,
"customer_id": "cust_123",
"alert_on": "exit"
}'
{
"success": true,
"data": {
"id": "geo_1",
"name": "Accra 50km zone",
"fence_type": "circle",
"center_lat": 5.6037,
"center_lng": -0.187,
"radius_km": 50,
"alert_on": "exit",
"active": true
}
}

fence_type is circle (default, needs center_lat/center_lng + radius_km), polygon (needs a polygon array of [lng, lat] exterior-ring points, at least 3), or isochrone (needs center_lat/center_lng + minutes, same drive-time contour as service areas) — exactly the fields for the chosen type are required. alert_on is exit (default, alerts when the customer leaves) or enter.

  • POST /v2/geofence/check — is a coordinate inside a geofence?
  • GET /v2/geofence/list, DELETE /v2/geofence/{id} — manage them.
  • A ping inside a geofence fires the geofence_breach webhook event.

6. Export​

Pull monitoring data into your own risk models or regulators:

  • GET /v2/export/pings?loan_ids=...&format=csv
  • GET /v2/export/drift?days=90&format=csv
  • GET /v2/export/zones?format=csv

Exports return raw CSV (format=csv, the default is JSON):

customer_id,loan_id,lat,lng,hex_code,timestamp
cust_001,loan_456,5.6041,-0.1953,AF-GH-7-0GXTQD5RFZZZZ,2026-08-01T10:00:00Z

SDK​

The TypeScript SDK wraps the whole flow — see SDK → monitoring:

await afrihex.consent.grant({customer_id, loan_id, ...})
await afrihex.location.ping({customer_id, loan_id, lat, lng, consent_token})
const drift = await afrihex.monitoring.drift({customer_id})

API reference​

See Location Monitoring — API Reference for every endpoint in this group.