SDKs
The API is plain HTTPS and JSON, so it already works from any language. We are also building an official library for each of the languages below. Each one is deliberately small: a typed client for the eight endpoints, timeouts, retries on 429 and 503, and debouncing for autocomplete. No framework, no plugins.
Status by language
JavaScript and TypeScript In progress
npm install @mygeocode/sdkWorks in Node 18+, Deno, Bun and browsers. Ships with types.
Python In progress
pip install mygeocodePython 3.9+. Sync and async clients, no dependencies beyond httpx.
PHP Planned
composer require mygeocode/sdkPHP 8.1+. PSR-18 client, bring your own HTTP library.
Go Planned
go get github.com/mygeocode/mygeocode-goStandard library only. Context aware.
Java Planned
com.mygeocode:sdkJava 11+. Built on java.net.http, also usable from Kotlin.
C# Planned
dotnet add package MyGeocode.NET 6+. Async throughout, System.Text.Json.
Ruby Planned
gem install mygeocodeRuby 3.0+. Net::HTTP, no runtime dependencies.
Rust Planned
cargo add mygeocodereqwest and serde, async by default.
The install commands above are reserved and will work the day each library is released. Want to know when? Send a blank email to [email protected] and we will reply once, when there is something to install.
What every SDK will do
One method per endpoint
client.forward("..."), client.reverse(lat, lon), client.ipv4("8.8.8.8"), and so on. Return values are typed records that mirror the JSON exactly, with the same field names.
Retries that respect the headers
A 429 with a reset time is retried after that time, up to a limit you set. A 503 is retried with backoff. Everything else is raised as an error with the API's code and message.
Key handling
Pass a key to the constructor or set MYGEOCODE_KEY in the environment. Leave both out and the client uses the free tier. Nothing is written to disk.
Use the HTTP API today
Here is a reverse geocode with error handling and a retry on 429, in the languages the first SDKs will cover. This is roughly what the libraries will do internally.
const BASE = "https://api.mygeocode.com/v1";
async function reverse(lat, lon, { key = process.env.MYGEOCODE_KEY, retries = 2 } = {}) {
const url = new URL(BASE + "/reverse");
url.searchParams.set("lat", lat);
url.searchParams.set("lon", lon);
const headers = key ? { "X-API-Key": key } : {};
const res = await fetch(url, { headers });
if (res.status === 429 && retries > 0) {
const reset = Number(res.headers.get("X-Quota-Reset")) * 1000;
const wait = Math.min(Math.max(reset - Date.now(), 1000), 60_000);
await new Promise((r) => setTimeout(r, wait));
return reverse(lat, lon, { key, retries: retries - 1 });
}
const data = await res.json();
if (data.status !== "ok") throw new Error(`${data.error.code}: ${data.error.message}`);
return data.result;
}
const place = await reverse(48.8584, 2.2945);
console.log(place.formatted, place.precision);import os
import time
import requests
BASE = "https://api.mygeocode.com/v1"
class MyGeocodeError(Exception):
pass
def reverse(lat, lon, key=os.environ.get("MYGEOCODE_KEY"), retries=2):
headers = {"X-API-Key": key} if key else {}
r = requests.get(f"{BASE}/reverse", params={"lat": lat, "lon": lon}, headers=headers, timeout=10)
if r.status_code == 429 and retries > 0:
reset = int(r.headers.get("X-Quota-Reset", 0))
time.sleep(min(max(reset - time.time(), 1), 60))
return reverse(lat, lon, key=key, retries=retries - 1)
data = r.json()
if data["status"] != "ok":
raise MyGeocodeError(f'{data["error"]["code"]}: {data["error"]["message"]}')
return data["result"]
place = reverse(48.8584, 2.2945)
print(place["formatted"], place["precision"])<?php
const BASE = "https://api.mygeocode.com/v1";
function reverse(float $lat, float $lon, ?string $key = null, int $retries = 2): array
{
$key ??= getenv("MYGEOCODE_KEY") ?: null;
$ch = curl_init(BASE . "/reverse?" . http_build_query(["lat" => $lat, "lon" => $lon]));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => $key ? ["X-API-Key: $key"] : [],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status === 429 && $retries > 0) {
sleep(5);
return reverse($lat, $lon, $key, $retries - 1);
}
$data = json_decode($body, true);
if ($data["status"] !== "ok") {
throw new RuntimeException($data["error"]["code"] . ": " . $data["error"]["message"]);
}
return $data["result"];
}
$place = reverse(48.8584, 2.2945);
echo $place["formatted"], " (", $place["precision"], ")\n";package main
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"strconv"
"time"
)
const base = "https://api.mygeocode.com/v1"
type Result struct {
Formatted string `json:"formatted"`
Lat float64 `json:"lat"`
Lon float64 `json:"lon"`
Precision string `json:"precision"`
}
type envelope struct {
Status string `json:"status"`
Result *Result `json:"result"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
func reverse(lat, lon float64, retries int) (*Result, error) {
q := url.Values{"lat": {strconv.FormatFloat(lat, 'f', -1, 64)}, "lon": {strconv.FormatFloat(lon, 'f', -1, 64)}}
req, _ := http.NewRequest("GET", base+"/reverse?"+q.Encode(), nil)
if key := os.Getenv("MYGEOCODE_KEY"); key != "" {
req.Header.Set("X-API-Key", key)
}
resp, err := (&http.Client{Timeout: 10 * time.Second}).Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 429 && retries > 0 {
time.Sleep(5 * time.Second)
return reverse(lat, lon, retries-1)
}
var env envelope
if err := json.NewDecoder(resp.Body).Decode(&env); err != nil {
return nil, err
}
if env.Status != "ok" {
return nil, errors.New(env.Error.Code + ": " + env.Error.Message)
}
return env.Result, nil
}
func main() {
place, err := reverse(48.8584, 2.2945, 2)
if err != nil {
panic(err)
}
fmt.Println(place.Formatted, place.Precision)
}Using another provider's SDK?
You may not need ours. The official Google Maps, Bing, HERE, Mapbox and ipinfo client libraries mostly accept a custom base URL, and our drop-in hosts answer in those providers' formats. Point the library at the matching mygeocode.com host and keep the code you have.