Urania Geo API Documentation

Integrate Urania’s RESTful GeoData API into your applications with ease.
Fetch datasets like countries, states, cities, and postal codes — all from one unified API.

Get Your API Key

Getting Started

The Urania API provides seamless access to geo datasets in a RESTful, developer-friendly way. All requests require an X-API-Key header for authentication — no OAuth, no tokens, no complexity.

GET https://urania.obilodev.com/v1/countries
Headers:
  X-API-Key: YOUR_API_KEY
  Accept: application/json

Works in desktop, web, mobile, or server environments — just include your API key in the request header.

Authentication Example

Every request must include your X-API-Key header. Example using JavaScript (fetch):

const headers = { "X-API-Key": "YOUR_API_KEY" };
fetch("https://urania.obilodev.com/v1/countries", { headers })
  .then(res => res.json())
  .then(console.log)
  .catch(console.error);

Usage Example

Want to cascade Countries - States - Cities into a HTML select form input, and cUrling using Javascript:


const countrySelect = document.getElementById('country');
const stateSelect = document.getElementById('state');
const citySelect = document.getElementById('city');
const API_KEY = 'your_api_key';
const BASE_URL = 'https://urania.obilodev.com/api/v1';

// Helper to fetch JSON
async function fetchData(url) {
    const res = await fetch(url, {
        headers: { 'X-API-KEY': API_KEY }
    });
    const json = await res.json();
    return json.data || [];
}

// Populate countries
(async () => {
    const countries = await fetchData(`${BASE_URL}/countries`);
    countries.forEach(c => {
        countrySelect.insertAdjacentHTML(
            'beforeend',
            ``
        );
    });
})();

// When country changes → fetch states
countrySelect.addEventListener('change', async () => {
    const countryId = countrySelect.value;

    stateSelect.innerHTML = '';
    citySelect.innerHTML = '';

    if (!countryId) return;

    const states = await fetchData(`${BASE_URL}/states?country_id=${countryId}`);
    states.forEach(s => {
        stateSelect.insertAdjacentHTML(
            'beforeend',
            ``
        );
    });
});

// When state changes → fetch cities
stateSelect.addEventListener('change', async () => {
    const stateId = stateSelect.value;

    citySelect.innerHTML = '';

    if (!stateId) return;

    const cities = await fetchData(`${BASE_URL}/cities?state_id=${stateId}`);
    cities.forEach(city => {
        citySelect.insertAdjacentHTML(
            'beforeend',
            ``
        );
    });
});

Response Codes

StatusMeaning
200 OKRequest successful
400 Bad RequestMalformed or invalid parameters
401 UnauthorizedMissing or invalid API key
404 Not FoundResource not found
429 Too Many RequestsRate limit exceeded
500 Server ErrorUnexpected internal error

Rate Limits

Note: Urania currently has no strict rate limits. However, to ensure fair use, please avoid sending unnecessary bulk requests.

Projects & API Keys

Every user works with Projects. A project can have multiple API keys, each representing a deployment target — web, mobile, or backend.

  • Create a project in your dashboard.
  • Generate, disable, or delete keys at any time.
  • Each key is scoped to a specific project for better analytics.

Monitoring & Logs

Urania automatically logs your API activity. You can view usage statistics, performance metrics, and error breakdowns — all from your project dashboard.

Available Endpoints

Retrieve a list of all countries available in the dataset.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/countries", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/countries",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/countries", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/countries", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/countries")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/countries");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/countries" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "countries": [
            "Afghanistan",
            "Aland Islands",
            "Albania",
            "Algeria",
            "American Samoa"
        ]
    },
    "status": "success"
}

Retrieve detailed information about a specific country available in the dataset.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/countries/{country}", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/countries/{country}",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/countries/{country}", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/countries/{country}", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/countries/{country}")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/countries/{country}");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/countries/{country}" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "country": "Nigeria",
        "iso2": "NG",
        "iso3": "NGA",
        "phoneCode": "+234",
        "currency": "NGN",
        "timezone": "Africa/Lagos",
        "id": 152
    },
    "status": "success"
}

Fetch states within a specific country.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/countries/{country}/states", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/countries/{country}/states",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/countries/{country}/states", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/countries/{country}/states", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/countries/{country}/states")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/countries/{country}/states");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/countries/{country}/states" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "country": "Nigeria",
        "states": [
            "Abia",
            "Adamawa",
            "Akwa Ibom",
            "Anambra",
            "Bauchi"
        ]
    },
    "status": "success"
}

Fetch a list of all states in the dataset.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/states", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/states",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/states", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/states", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/states")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/states");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/states" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "states": [
            "Abia",
            "Adamawa",
            "Akwa Ibom",
            "Anambra",
            "Bauchi"
        ]
    },
    "status": "success"
}

Retrieve all cities within a given state.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/states/{state}/cities", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/states/{state}/cities",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/states/{state}/cities", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/states/{state}/cities", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/states/{state}/cities")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/states/{state}/cities");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/states/{state}/cities" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "state": "Abia",
        "cities": [
            "Aba",
            "Umuahia",
            "Ohafia",
            "Arochukwu",
            "Bende"
        ]
    },
    "status": "success"
}

Fetch a list of all cities in the dataset.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/cities", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/cities",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/cities", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/cities", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/cities")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/cities");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/cities" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "cities": [
            "Aba",
            "Umuahia",
            "Ohafia",
            "Arochukwu",
            "Bende"
        ]
    },
    "status": "success"
}

Retrieve information about a specific city available in the dataset.

import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
response = requests.get("https://urania.obilodev.com/api/v1/cities/{city}", headers=headers)
print(response.json())
$curl = curl_init();
curl_setopt_array($curl, [
  CURLOPT_URL => "https://urania.obilodev.com/api/v1/cities/{city}",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["X-API-Key: YOUR_API_KEY"]
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import fetch from "node-fetch";
const res = await fetch("https://urania.obilodev.com/api/v1/cities/{city}", {
  headers: { "X-API-Key": "YOUR_API_KEY" }
});
console.log(await res.json());
package main
import ("fmt"; "net/http"; "io/ioutil")
func main() {
  req, _ := http.NewRequest("GET", "https://urania.obilodev.com/api/v1/cities/{city}", nil)
  req.Header.Add("X-API-Key", "YOUR_API_KEY")
  res, _ := http.DefaultClient.Do(req)
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}
use reqwest::blocking::Client;
fn main() -> Result<(), Box> {
    let client = Client::new();
    let res = client.get("https://urania.obilodev.com/api/v1/cities/{city}")
        .header("X-API-Key", "YOUR_API_KEY")
        .send()?
        .text()?;
    println!("{}", res);
    Ok(())
}
import java.net.*;
import java.io.*;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://urania.obilodev.com/api/v1/cities/{city}");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-Key", "YOUR_API_KEY");
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String inputLine; StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) response.append(inputLine);
    in.close();
    System.out.println(response.toString());
  }
}
curl -X GET "https://urania.obilodev.com/api/v1/cities/{city}" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Accept: application/json"
Sample Response
{
    "code": 200,
    "data": {
        "name": "Aba",
        "lat": "5.1200000",
        "lng": "7.4000000",
        "stateId": 1,
        "countryId": null
    },
    "status": "success"
}

Urania API is Free of Charge — no subscription required.
Donations and gifts are always welcome to help keep the servers running 💙

← Back to Obioma Onwuka
Theme Settings
Color Scheme
Light
Dark
Layout Mode
Fluid
Detached
Topbar Color
Light
Dark
Brand
Menu Color
Light
Dark
Brand
Sidebar Size
Default
Compact
Condensed
Hover View
Full Layout
Hidden
Container Width
Layout Position
Buy Now