Skip to main content

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:

PieceSourceEndpoint
Dropped pinThe device — a map tap or GPS fix(client-side; not an AfriHex call)
Digital address + localityReverse geocoding the pinGET /v2/reverse?lat=&lng=
Landmark referenceLandmark search near the pinGET /v2/landmarks/geocode?near=
Gate/access noteFree text the customer typesStored in label/notes on the profile
Saved, shareable recordA slug-addressable profilePOST /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​

FieldNotes
slugThe shareable identifier — this is what you'd hand a rider or print on a package, not the raw coordinates
edit_tokenReturned once, on creation — store it server-side; it's required for any future PATCH/DELETE on this profile
labelThe 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"
notesA second freeform field for anything internal (rider instructions, delivery preferences) that shouldn't necessarily show on a public profile view
hex_codeOptional — 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_emailOpt-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​

  • 409 slug already taken. Slugs are global, not per-customer — namespace them (e.g. {customer_id}-home) rather than using a raw display name.
  • 400 invalid coordinates. The pin must fall inside the active country — same OUT_OF_BOUNDS behaviour 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 into label instead 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_token is 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-written label are enough on their own.