SDK

La API es HTTPS y JSON sin más, así que ya funciona desde cualquier lenguaje. También estamos creando una biblioteca oficial para cada uno de los lenguajes de abajo. Cada una es deliberadamente pequeña: un cliente tipado para los ocho endpoints, tiempos de espera, reintentos ante 429 y 503, y debounce para el autocompletado. Sin framework, sin plugins.

Estado por lenguaje

JavaScript y TypeScript En desarrollo

npm install @mygeocode/sdk

Funciona en Node 18+, Deno, Bun y navegadores. Incluye tipos.

Python En desarrollo

pip install mygeocode

Python 3.9+. Clientes síncronos y asíncronos, sin más dependencias que httpx.

PHP Previsto

composer require mygeocode/sdk

PHP 8.1+. Cliente PSR-18, usa tu propia biblioteca HTTP.

Go Previsto

go get github.com/mygeocode/mygeocode-go

Solo la biblioteca estándar. Compatible con context.

Java Previsto

com.mygeocode:sdk

Java 11+. Basado en java.net.http, también se puede usar desde Kotlin.

C# Previsto

dotnet add package MyGeocode

.NET 6+. Asíncrono de principio a fin, System.Text.Json.

Ruby Previsto

gem install mygeocode

Ruby 3.0+. Net::HTTP, sin dependencias en tiempo de ejecución.

Rust Previsto

cargo add mygeocode

reqwest y serde, asíncrono por defecto.

Los comandos de instalación de arriba están reservados y funcionarán el día en que se publique cada biblioteca. ¿Quieres saber cuándo? Envía un correo en blanco a support@mygeocode.com y te responderemos una sola vez, cuando haya algo que instalar.

Qué hará cada SDK

Un método por endpoint

client.forward("..."), client.reverse(lat, lon), client.ipv4("8.8.8.8"), etc. Los valores devueltos son registros tipados que reflejan el JSON exactamente, con los mismos nombres de campos.

Reintentos que respetan las cabeceras

Un 429 con hora de reinicio se reintenta después de esa hora, hasta el límite que fijes. Un 503 se reintenta con espera progresiva. Todo lo demás se lanza como error con el code y el message de la API.

Gestión de la clave

Pasa una clave al constructor o define MYGEOCODE_KEY en el entorno. No se escribe nada en disco. Si falta la clave, se lanza un error de inmediato con una indicación hacia el panel.

Usa la API HTTP hoy

Aquí tienes una geocodificación inversa con gestión de errores y un reintento ante 429, en los lenguajes que cubrirán los primeros SDK. Es aproximadamente lo que harán las bibliotecas internamente.

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)
}

¿Usas el SDK de otro proveedor?

Puede que no necesites el nuestro. Las bibliotecas cliente oficiales de Google Maps, Bing, HERE, Mapbox e ipinfo suelen aceptar una URL base personalizada, y nuestros hosts compatibles responden en los formatos de esos proveedores. Apunta la biblioteca al host de www.mygeocode.com correspondiente y conserva el código que tienes.