Heimdall

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.

Python — geopy
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)
JavaScript — node-geocoder
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
curl "https://api.geoheim.com/search?q=Stockholm&format=json" \
  -H "Authorization: Bearer hk_live_…"
Python
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"])
JavaScript / TypeScript
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);
Go
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"])
}
Ruby
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
<?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";
C# / .NET
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.