Why this API Endpoints Integration Guide FAQ View Docs ↓

Free · Open · No Auth Required

Nigerian geo-data,
finally structured.

One API for all 36 states + FCT, 774 LGAs, GPS coordinates, NIPOST postal codes, geopolitical zones, and proximity search — built for Nigerian developers tired of building location dropdowns from scratch.

GET nigeria.jamiuadewaleyusuf.com/api/v1/states/lagos/lgas
{
  "status": "success",
  "meta": {
    "state": {
      "name":     "Lagos",
      "capital":  "Ikeja",
      "geo_zone": "SW",
      "iso_code": "NG-LA"
    },
    "total": 20
  },
  "data": [
    {
      "name":       "Agege",
      "slug":       "agege",
      "state":      "Lagos",
      "coordinates": {
        "lat": 6.6167,
        "lng": 3.3167
      },
      "postal_code": "100283"
    },
    // ... 19 more LGAs
  ]
}
37States + FCT
774LGAs covered
9API Endpoints
6Geo Zones
0Auth required

The Problem

Every Nigerian developer has built this themselves — at least twice.

Shipping a product in Nigeria means writing the same address form logic, the same state/LGA arrays, the same KYC dropdowns — over and over. This API ends that cycle.

Hardcoded state arrays
Most teams maintain a static JSON or PHP array of states and LGAs, copied from another project, riddled with spelling inconsistencies and missing new LGAs.
No coordinates or postal codes
When location features land on the roadmap — delivery radius, store finder, nearest agent — the team has to source coordinates manually from Wikipedia or Google Maps.
Inconsistent data across products
"Akwa Ibom" appears as "Akwa-Ibom", "AkwaIbom", "Cross-River" — especially across microservices. Slugs, ISO codes, and consistent naming solve this.
KYC & fintech onboarding
Address verification, state-of-origin fields, and document validation all need authoritative location data with postal codes matching NIPOST format.
Delivery & logistics
E-commerce platforms need to know if a customer address is within delivery range. The proximity endpoint returns nearby LGAs sorted by distance in km.
Geopolitical zone analytics
NGOs, government apps, and electoral platforms need to group states by NC / NE / NW / SE / SS / SW zones. One endpoint returns this entire structure.

API Reference

9 endpoints. Zero setup.

No API key. No registration. Just fetch. All responses return a consistent JSON envelope.

BASE URL https://nigeria.jamiuadewaleyusuf.com/api/v1
ParamTypeRequiredDescription
geo_zone string optional Filter by zone code: NC NE NW SE SS SW

Example Request

GET /api/v1/states?geo_zone=SW

Example Response

{
  "status": "success",
  "data": [
    {
      "id": 25,
      "name": "Lagos",
      "slug": "lagos",
      "capital": "Ikeja",
      "geo_zone": "SW",
      "geo_zone_full": "South West",
      "iso_code": "NG-LA",
      "country_code": "NG",
      "coordinates": { "lat": 6.5244, "lng": 3.3792 },
      "postal_prefix": "100",
      "lga_count": 20
    }
  ],
  "meta": { "total": 6 }
}

The {slug} parameter accepts: slug (lagos), state name (Lagos), or ISO code (NG-LA).

GET /api/v1/states/lagos
GET /api/v1/states/Lagos       # also works
GET /api/v1/states/NG-LA       # also works
GET /api/v1/states/rivers/lgas

{
  "status": "success",
  "data": [
    {
      "name": "Port Harcourt",
      "slug": "port-harcourt",
      "state": "Rivers",
      "coordinates": { "lat": 4.8156, "lng": 7.0498 },
      "postal_code": "500001"
    }
  ],
  "meta": {
    "state": { "name": "Rivers", "capital": "Port Harcourt" },
    "total": 23
  }
}
ParamTypeRequiredDescription
state string optional Filter by state slug or name
GET /api/v1/lgas?state=kano
ParamTypeRequiredDescription
q string required Search term, min 2 characters
state string optional Scope to a single state
GET /api/v1/lgas/search?q=aba&state=abia

Returns all 6 zones: North Central (NC), North East (NE), North West (NW), South East (SE), South South (SS), South West (SW) — each with their states grouped.

GET /api/v1/geo-zones

{
  "status": "success",
  "data": [
    {
      "zone": "NC",
      "zone_full": "North Central",
      "state_count": 7,
      "states": [ ... ]
    }
  ],
  "meta": { "total_zones": 6 }
}

{zone} accepts short form (SW) or full name (South West).

GET /api/v1/geo-zones/SW/states
ParamTypeRequiredDescription
code string required NIPOST postal code (3–10 digits)

Tries exact LGA match first. Falls back to state-level prefix match (first 3 digits).

GET /api/v1/postal-codes/lookup?code=100283
ParamTypeRequiredDefaultDescription
lat float required Latitude
lng float required Longitude
radius float optional 100 Radius in km (max 500)
limit int optional 10 Max results (max 50)
type string optional lga lga or state
GET /api/v1/nearby?lat=6.45&lng=3.39&radius=30&limit=5

{
  "data": [
    {
      "name": "Lagos Island",
      "state": "Lagos",
      "coordinates": { "lat": 6.4531, "lng": 3.3958 },
      "postal_code": "101221",
      "distance_km": 1.84
    }
  ],
  "meta": {
    "center": { "lat": 6.45, "lng": 3.39 },
    "radius_km": 30,
    "total": 5
  }
}

Response Envelope

{
  "status": "success",  // or "error"
  "data":   { ... },        // resource or array
  "meta":   {               // present on lists
    "total": 20,
    "state": { ... }
  }
}

// Error format
{
  "status":  "error",
  "message": "State not found"
}

Consistent slug resolution

All {slug} parameters accept the slug (akwa-ibom), the state name (Akwa Ibom), or the ISO code (NG-AK). Case-insensitive.

HTTP Status Codes

200 — Success  ·  404 — Not found  ·  422 — Validation error

No authentication

This is a public API. No API key, no OAuth, no headers required. Just make the request.


Integration Guide

Drop it into anything in minutes.

Ready-made snippets for the most common Nigerian dev stacks.

const BASE = '.jamiuadewaleyusuf.com/api/v1';

// Get all states
const states = await fetch(`${BASE}/states`).then(r => r.json());

// Get LGAs for a state
const { data: lgas } = await fetch(`${BASE}/states/lagos/lgas`).then(r => r.json());

// Find LGAs near a coordinate
const nearby = await fetch(
  `${BASE}/nearby?lat=6.45&lng=3.39&radius=50&limit=10`
).then(r => r.json());

// Lookup postal code
const location = await fetch(`${BASE}/postal-codes/lookup?code=100283`).then(r => r.json());
<?php

use Illuminate\Support\Facades\Http;

class NigeriaLocationService
{
    private string $base = 'https://nigeria.jamiuadewaleyusuf.com/api/v1';

    public function states(string $geoZone = null): array
    {
        $params = $geoZone ? ['geo_zone' => $geoZone] : [];
        return Http::get("{$this->base}/states", $params)->json('data');
    }

    public function lgasByState(string $state): array
    {
        return Http::get("{$this->base}/states/{$state}/lgas")->json('data');
    }

    public function nearby(float $lat, float $lng, int $radius = 100): array
    {
        return Http::get("{$this->base}/nearby", compact('lat', 'lng', 'radius'))->json('data');
    }

    public function lookupPostal(string $code): ?array
    {
        $resp = Http::get("{$this->base}/postal-codes/lookup", ['code' => $code])->json();
        return $resp['status'] === 'success' ? $resp['data'] : null;
    }
}
import requests

BASE = ".jamiuadewaleyusuf.com/api/v1"

# All states in South West
states = requests.get(f"{BASE}/states", params={"geo_zone": "SW"}).json()["data"]

# LGAs by state
lgas = requests.get(f"{BASE}/states/lagos/lgas").json()["data"]

# Nearby
nearby = requests.get(f"{BASE}/nearby", params={
    "lat": 6.45, "lng": 3.39, "radius": 50
}).json()["data"]

# Postal lookup
location = requests.get(f"{BASE}/postal-codes/lookup", params={"code": "100283"}).json()
import 'dart:convert';
import 'package:http/http.dart' as http;

const _base = 'https://nigeria.jamiuadewaleyusuf.com/api/v1';

// Get states
Future<List> getStates() async {
  final res = await http.get(Uri.parse('$_base/states'));
  return jsonDecode(res.body)['data'];
}

// Get LGAs
Future<List> getLgas(String state) async {
  final res = await http.get(Uri.parse('$_base/states/$state/lgas'));
  return jsonDecode(res.body)['data'];
}

// Nearby
Future<List> getNearby(double lat, double lng, {int radius=100}) async {
  final uri = Uri.parse('$_base/nearby').replace(queryParameters: {
    'lat': '$lat', 'lng': '$lng', 'radius': '$radius'
  });
  final res = await http.get(uri);
  return jsonDecode(res.body)['data'];
}
import { useState, useEffect } from 'react';

const BASE = 'https://nigeria.jamiuadewaleyusuf.com/api/v1';

// State → LGA cascade hook
export function useNigeriaLocation() {
  const [states, setStates] = useState([]);
  const [lgas, setLgas] = useState([]);
  const [selectedState, setSelectedState] = useState('');

  useEffect(() => {
    fetch(`${BASE}/states`)
      .then(r => r.json())
      .then(d => setStates(d.data));
  }, []);

  useEffect(() => {
    if (!selectedState) return;
    fetch(`${BASE}/states/${selectedState}/lgas`)
      .then(r => r.json())
      .then(d => setLgas(d.data));
  }, [selectedState]);

  return { states, lgas, setSelectedState };
}
# All states
curl https://nigeria.jamiuadewaleyusuf.com/api/v1/states

# States by geopolitical zone
curl "https://nigeria.jamiuadewaleyusuf.com/api/v1/states?geo_zone=SW"

# LGAs for a state
curl https://nigeria.jamiuadewaleyusuf.com/api/v1/states/lagos/lgas

# Nearby (Abuja coords)
curl "https://nigeria.jamiuadewaleyusuf.com/api/v1/nearby?lat=9.0765&lng=7.3986&radius=50"

# Postal code lookup
curl "https://nigeria.jamiuadewaleyusuf.com/api/v1/postal-codes/lookup?code=900001"

# Search LGAs
curl "https://nigeria.jamiuadewaleyusuf.com/api/v1/lgas/search?q=aba"

Use Cases

Built for real Nigerian product problems.

🛒
E-commerce Checkout
Populate state → LGA cascading dropdowns. Validate postal codes. Auto-suggest delivery zone from coordinates.
Fintech KYC
Validate state of origin, LGA of residence, and postal codes during onboarding with authoritative NIPOST data.
Logistics & Delivery
Use the /nearby endpoint to check if a delivery address falls within your service radius and calculate zones.
Property & Real Estate
Filter listings by LGA, show nearby LGAs, embed coordinates into search indexes for map-based interfaces.
Data Analytics
Group survey or transaction data by geopolitical zone. Normalize inconsistent location strings across datasets.
Healthcare & NGOs
Map patients or beneficiaries to LGAs, generate zone-level reports, and power humanitarian response dashboards.
Mobile Apps
Seed a local SQLite database from the /states and /lgas endpoints for offline-capable Nigerian location pickers.
Civic & GovTech
Electoral maps, constituency data, and local government listings structured with ISO codes and geo zone groupings.

FAQ

Common questions.

Yes, completely free and completely open. No registration, no API key, no rate limit headers to manage. Just hit the endpoint. If this API helps your product, consider giving the project a star on GitHub or sharing it with other Nigerian developers.
State and LGA data comes from the Nigerian Federal Government's official classification. Coordinates are centroid points from GeoNames and OpenStreetMap. Postal codes follow the official NIPOST 6-digit format. ISO codes are from ISO 3166-2:NG.
Coordinates represent the centroid of the LGA's major town or headquarters, not the geographic center of the LGA polygon. They are accurate enough for proximity search, map pins, and zone calculations. For precision polygon-level boundaries, you would need a GeoJSON shapefile source.
Absolutely. The full source code is available. It's a standard Laravel 11 application. Run php artisan migrate && php artisan db:seed and you have your own private instance. This is especially useful for teams with strict data residency requirements.
Fetch /api/v1/states on page load to populate your state dropdown. When a user selects a state, fire a request to /api/v1/states/{slug}/lgas to populate the LGA dropdown. Both responses are fast enough for real-time use without caching.
Common uses: checking if a customer's GPS coordinates are within your delivery radius (set radius to your max km), finding the nearest service agents to a user, sorting properties by proximity to a search location, and building "stores near you" features. Pass type=state to find the nearest states instead of LGAs.
CORS is open — you can call this API directly from browser JavaScript, React, Vue, or any frontend. No proxy needed. If you're building a high-traffic product, consider self-hosting to avoid depending on external uptime.
This is a community resource hosted on a Contabo VPS with Uptime Kuma monitoring. For production applications, consider caching responses locally (state lists almost never change) or self-hosting. A free resource cannot guarantee enterprise SLAs — plan accordingly.