Build a Delivery Address Capture Flow for Ghana
The business problem
Ghana has sparse street addressing, so "type your address" is the wrong UI — most customers don't have one to type. A working capture flow instead combines several weaker signals into one usable delivery address: where the customer tapped on a map, whatever digital address that resolves to, the locality it's in, a landmark to describe it by, and a freeform note for the part no coordinate captures (which gate, which floor, "ask the shop next door"). None of these alone is enough; together they're what a rider actually needs.
What AfriHex returns
The pieces, and where each comes from:
| Piece | Source | Endpoint |
|---|---|---|
| Dropped pin | The device — a map tap or GPS fix | (client-side; not an AfriHex call) |
| Digital address + locality | Reverse geocoding the pin | GET /v2/reverse?lat=&lng= |
| Landmark reference | Landmark search near the pin | GET /v2/landmarks/geocode?near= |
| Gate/access note | Free text the customer types | Stored in label/notes on the profile |
| Saved, shareable record | A slug-addressable profile | POST /v2/profile |
Before you begin
- An API key, and a UI that captures a coordinate from a map tap or device GPS — this flow assumes you already have that pin.
- Decide your own event for "customer confirmed this" (a tap on a review screen, typically) — AfriHex stores what you send it, it doesn't track confirmation state for you. See Understanding Confidence and Verification for why that distinction matters.
- A slug scheme for saved addresses (3–30 chars, lowercase/numbers/hyphens) — one per customer, or one per delivery location if a customer has several.
Copyable request
Step 1 — the customer drops a pin; reverse-geocode it for locality and a digital address:
curl "https://api.afrihex.com/v2/reverse?lat=5.6221843&lng=-0.1729361" \
-H "X-API-Key: $AFRIHEX_API_KEY"
Step 2 — offer nearby landmarks so the customer can pick one to describe the spot by:
curl "https://api.afrihex.com/v2/landmarks/geocode?near=5.6221843,-0.1729361&radius=500" \
-H "X-API-Key: $AFRIHEX_API_KEY"
Step 3 — after the customer reviews and confirms, save the combined record:
curl -X POST "https://api.afrihex.com/v2/profile" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "ama-osu-home",
"display_name": "Ama Owusu",
"phone": "+233241234567",
"lat": 5.6221843,
"lng": -0.1729361,
"label": "Near Accra Mall, blue gate opposite Goil, third house on the left"
}'
Full example response
{
"slug": "ama-osu-home",
"display_name": "Ama Owusu",
"hex_code": null,
"lat": 5.6221843,
"lng": -0.1729361,
"label": "Near Accra Mall, blue gate opposite Goil, third house on the left",
"notes": null,
"view_count": 0,
"created_at": "2026-09-02T12:00:00Z",
"edit_token": "…",
"phone": "+233241234567",
"alert_email": null,
"flood_alerts_on": false
}
Field-by-field explanation
| Field | Notes |
|---|---|
slug | The shareable identifier — this is what you'd hand a rider or print on a package, not the raw coordinates |
edit_token | Returned once, on creation — store it server-side; it's required for any future PATCH/DELETE on this profile |
label | The single freeform field for landmark + gate/access note — put your customer-facing description here, e.g. "Near Accra Mall, blue gate opposite Goil, third house" |
notes | A second freeform field for anything internal (rider instructions, delivery preferences) that shouldn't necessarily show on a public profile view |
hex_code | Optional — attach an AfriHex code (e.g. AF-GH-7-0GXTQD5VJZZZZ) if you want the profile keyed to a grid cell as well as a coordinate |
flood_alerts_on / alert_email | Opt-in proactive flood alerts for this saved location — requires alert_email when enabled |
Your own system, not this endpoint, is where you record that and when the
customer confirmed the pin — e.g. provenance.source: user_confirmed in your
own database row, timestamped to the confirmation tap. See Understanding
Confidence and
Verification for the full set
of provenance tiers this maps onto.
Error and edge cases
409slug already taken. Slugs are global, not per-customer — namespace them (e.g.{customer_id}-home) rather than using a raw display name.400invalid coordinates. The pin must fall inside the active country — sameOUT_OF_BOUNDSbehaviour as every other endpoint (see Your First AfriHex Request).- No landmark within
radius.GET /v2/landmarks/geocode?near=can legitimately return zero results in a sparsely-mapped area — fall back to letting the customer type a free-text description intolabelinstead of blocking the flow on a landmark pick. - The customer's pin and their claimed digital address disagree. This happens — a customer types a GhanaPostGPS code from memory while dropping a pin somewhere else. Don't silently prefer one; show both and let them resolve the conflict, or flag it for review if this profile feeds a KYC/delivery-verification flow (see Validate a Customer Address for Onboarding).
- Lost
edit_token. There's no recovery endpoint — if you didn't persist it, the profile is effectively read-only until the customer re-creates one under a new slug. Store it the same way you'd store a password hash: once, server-side, at creation time.
Production checklist
-
edit_tokenis persisted server-side at creation — never only shown to the client and discarded. - Slugs are namespaced per customer/account, not raw user input.
- The confirmation event (who confirmed, when, from what pin) is recorded in your system, not assumed from AfriHex's response.
- Landmark search has a graceful empty-result fallback to free text.
- Reverse-geocode failures (
404) don't block saving the profile — a coordinate and a customer-writtenlabelare enough on their own.
Related endpoints / next guide
- Choose the Right Location Identifier — why a coordinate alone isn't a stable identifier to key this profile on.
- Search Informal Landmarks and Local Aliases — getting good landmark suggestions for step 2.
- Route a Driver to the Correct Entrance — using this saved profile as a routing destination.