Libraries & examples
Heimdall is Nominatim-compatible — existing Nominatim clients work out of the box. Just change the base URL.
Use existing Nominatim clients
No official SDK needed. Any Nominatim client library works — just point it at Heimdall.
from geopy.geocoders import Nominatim
geocoder = Nominatim(
domain="api.geoheim.com",
scheme="https",
user_agent="my-app",
)
# Forward geocode
location = geocoder.geocode("Kungsgatan 15, Stockholm")
print(f"{location.latitude}, {location.longitude}")
# Reverse geocode
location = geocoder.reverse("59.33, 18.07")
print(location.address)const NodeGeocoder = require("node-geocoder");
const geocoder = NodeGeocoder({
provider: "openstreetmap",
host: "api.geoheim.com",
extra: {
headers: { "Authorization": "Bearer hk_live_…" },
},
});
const results = await geocoder.geocode("Stockholm");
console.log(results[0].latitude, results[0].longitude);Raw HTTP examples
No library needed — it's just a GET request.
curl "https://api.geoheim.com/search?q=Stockholm&format=json" \ -H "Authorization: Bearer hk_live_…"
import requests
resp = requests.get(
"https://api.geoheim.com/search",
params={"q": "Stockholm", "format": "json"},
headers={"Authorization": "Bearer hk_live_…"},
)
data = resp.json()
print(f"{data[0]['lat']}, {data[0]['lon']}")
print(data[0]["display_name"])const resp = await fetch(
"https://api.geoheim.com/search?q=Stockholm&format=json",
{ headers: { "Authorization": "Bearer hk_live_…" } }
);
const data = await resp.json();
console.log(data[0].lat, data[0].lon);package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://api.geoheim.com/search?q=Stockholm&format=json", nil)
req.Header.Set("Authorization", "Bearer hk_live_…")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var results []map[string]interface{}
json.NewDecoder(resp.Body).Decode(&results)
fmt.Printf("%s, %s\n", results[0]["lat"], results[0]["lon"])
}require "net/http"
require "json"
uri = URI("https://api.geoheim.com/search?q=Stockholm&format=json")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer hk_live_…"
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(req)
}
data = JSON.parse(resp.body)
puts "#{data[0]['lat']}, #{data[0]['lon']}"<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.geoheim.com/search?q=Stockholm&format=json",
CURLOPT_HTTPHEADER => ["Authorization: Bearer hk_live_…"],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
echo $data[0]["lat"] . ", " . $data[0]["lon"] . "\n";using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer hk_live_…");
var resp = await client.GetStringAsync(
"https://api.geoheim.com/search?q=Stockholm&format=json");
var data = JsonSerializer.Deserialize<JsonElement>(resp);
Console.WriteLine($"{data[0].GetProperty("lat")}, {data[0].GetProperty("lon")}");Use case ideas
Address autocomplete
Type-ahead search in a checkout form or booking flow. Use /autocomplete with a 200ms debounce.
Batch geocoding
Have a CSV of addresses? Loop through them with /search. At 196 req/s self-hosted, a million addresses takes under 2 hours.
Map pin drop
User clicks a map, you call /reverse to show the address. Works great with Leaflet, Mapbox GL, or Google Maps.
Delivery zone validation
Check if an address is within your service area. Use /search + viewbox + bounded=1.
Location-aware search
Bias results by user location. Pass their coordinates as a viewbox to /autocomplete.
Data enrichment
Have coordinates from GPS/IoT devices? Batch /reverse to add city, country, and postal code to your records.