Skip to main content

Ship an address picker in 10 minutes

You'll build a checkout-style address field. Customers either type a place name and pick a suggestion, or paste their GhanaPostGPS code. Either way you get back coordinates and an AfriHex code you can save with the order.

Three calls do it all:

StepCallWhat it gives you
1. Suggest places as they typeGET /v2/search/autocompleteNames and coordinates
2. Or look up a GhanaPostGPS codeGET /v2/lookupThe code's coordinates, region and area
3. Get the AfriHex codeGET /v2/hexcodecode to store and short_code to show

You need Node.js 18 or newer and a free key from Authentication.

:::warning Keep your key on the server Anyone can read an API key in browser code. The page below talks to your own small server, and only the server talks to AfriHex. :::

1. The server (server.mjs)​

import express from 'express'

const app = express()
const KEY = process.env.AFRIHEX_API_KEY
const afrihex = (path) =>
fetch(`https://api.afrihex.com${path}`, { headers: { 'X-API-Key': KEY } }).then(r => r.json())

// Suggestions as the customer types. lat/lng bias results towards the user.
app.get('/places', async (req, res) => {
const q = encodeURIComponent(req.query.q ?? '')
const near = req.query.lat ? `&lat=${req.query.lat}&lng=${req.query.lng}` : ''
const json = await afrihex(`/v2/search/autocomplete?q=${q}&limit=5${near}`)
res.json(json.data?.results ?? [])
})

// The chosen place, or a pasted GhanaPostGPS code, becomes an AfriHex code.
app.get('/pick', async (req, res) => {
let { lat, lng, gps } = req.query
let area = ''
if (gps) {
const found = await afrihex(`/v2/lookup?address=${encodeURIComponent(gps)}`)
if (!found.success) return res.status(404).json({ error: 'GhanaPostGPS code not found' })
lat = found.data.center_latitude
lng = found.data.center_longitude
area = `${found.data.area}, ${found.data.district}`
}
const hex = await afrihex(`/v2/hexcode?lat=${lat}&lng=${lng}`)
res.json({ lat: Number(lat), lng: Number(lng), area, code: hex.data.code, short_code: hex.data.short_code })
})

app.use(express.static('public'))
app.listen(3000, () => console.log('Open http://localhost:3000'))

2. The page (public/index.html)​

<!doctype html>
<meta charset="utf-8">
<label>Delivery address
<input id="q" placeholder="Search a place, or paste a GhanaPostGPS code" autocomplete="off" style="width:22rem">
</label>
<ul id="list"></ul>
<p id="picked"></p>

<script>
const q = document.getElementById('q')
const list = document.getElementById('list')
const picked = document.getElementById('picked')
const isGpsCode = (s) => /^[A-Z]{2}-?\d{3,4}-?\d{4}$/i.test(s.trim())
let timer

q.addEventListener('input', () => {
clearTimeout(timer)
timer = setTimeout(async () => {
list.innerHTML = ''
if (isGpsCode(q.value)) return show(`/pick?gps=${encodeURIComponent(q.value.trim())}`)
if (q.value.trim().length < 3) return
const places = await fetch(`/places?q=${encodeURIComponent(q.value)}`).then(r => r.json())
for (const p of places) {
const li = document.createElement('li')
li.textContent = p.display_name
li.onclick = () => show(`/pick?lat=${p.latitude}&lng=${p.longitude}`, p.display_name)
list.append(li)
}
}, 250)
})

async function show(url, label = '') {
const r = await fetch(url).then(r => r.json())
list.innerHTML = ''
picked.textContent = r.error ?? `${label || r.area} · AfriHex code ${r.short_code}`
// Save r.code, r.lat and r.lng with the order.
}
</script>

3. Run it​

npm init -y && npm install express
export AFRIHEX_API_KEY="your key"
node server.mjs

Open http://localhost:3000, type Spintex, pick a suggestion, and the AfriHex code appears. Paste GA-183-8164 instead and you get Bukom, Accra.

What to save​

FieldWhy
codeThe full AfriHex code. Store this one.
short_codeThe same code without the trailing Zs, for showing to people. Every endpoint accepts either form.
lat, lngThe point the customer chose.

Next steps​

  • Pass the customer's location as lat/lng to /places so nearby places come first.
  • Add landmark directions such as "Opposite the Shell filling station" with GET /v2/reverse?lat=…&lng=…&descriptors=true. See Addresses.
  • Capture the customer's gate as well as the area: see Delivery address capture.