ApogeoAPI quickstart — Go (net/http)

Use ApogeoAPI from Go with the standard library — no dependencies required.

1. Authenticate

Every request needs an X-API-Key header. Get your key from the dashboard — free tier or 14-day trial, no credit card.

Client setup

package apogeo

import (
    "encoding/json"
    "errors"
    "io"
    "net/http"
    "os"
    "time"
)

var client = &http.Client{Timeout: 5 * time.Second}
var apiKey = os.Getenv("APOGEOAPI_KEY")
const base = "https://api.apogeoapi.com/v1"

func get(path string, out any) error {
    req, _ := http.NewRequest("GET", base+path, nil)
    req.Header.Set("X-API-Key", apiKey)
    res, err := client.Do(req)
    if err != nil {
        return err
    }
    defer res.Body.Close()
    if res.StatusCode >= 400 {
        return errors.New(res.Status)
    }
    body, _ := io.ReadAll(res.Body)
    return json.Unmarshal(body, out)
}

2. Get country data

Returns ISO codes, capital, currency with live exchange rate, phone code, flag URL, timezones, name translations and more — for any of the 250 countries.

Get country data

type Country struct {
    ISO2     string `json:"iso2"`
    Name     string `json:"name"`
    Capital  string `json:"capital"`
    Currency string `json:"currency"`
}

var ar Country
if err := get("/countries/AR", &ar); err != nil {
    log.Fatal(err)
}
fmt.Println(ar.Name, ar.Capital, ar.Currency)

Full country list: browse all 250 →

3. IP geolocation

Pass any IPv4 or IPv6 address. Returns country, city, timezone, coordinates and accuracy radius. Use /ip/me server-side to detect the visitor.

IP geolocation

type IPGeo struct {
    IP          string  `json:"ip"`
    Country     string  `json:"country"`
    CountryCode string  `json:"countryCode"`
    Timezone    string  `json:"timezone"`
    Latitude    float64 `json:"latitude"`
    Longitude   float64 `json:"longitude"`
}

var geo IPGeo
get("/ip/8.8.8.8", &geo)
fmt.Println(geo.Country, geo.Timezone)

Try it live without signup: /ip-lookup →

4. Live exchange rates

161 currencies, refreshed every 4 hours. Specify a base currency and any number of target codes.

Live exchange rates

type FX struct {
    Base  string             `json:"base"`
    Rates map[string]float64 `json:"rates"`
}

var fx FX
get("/exchange-rates/USD?targets=EUR,ARS,BRL", &fx)
fmt.Printf("1 USD = %.2f ARS\n", fx.Rates["ARS"])

5. States & cities

List all states / provinces for a country (5,000+ globally). Each includes the ISO 3166-2 code and coordinates. Cities are accessible by state ID with /v1/states/:id/cities.

Country → states

type State struct {
    Name      string `json:"name"`
    StateCode string `json:"stateCode"`
    ISO3166   string `json:"iso3166_2"`
}
type StatesRes struct{ Data []State `json:"data"` }

var res StatesRes
get("/countries/AR/states?limit=30", &res)
for _, s := range res.Data {
    fmt.Println(s.StateCode, s.Name)
}

6. Production-grade error handling

Always handle 429 (rate limit) — read the Retry-After header and back off. For transient 5xx, retry up to 3 times with exponential backoff.

Rate-limit aware retry

func getWithRetry(path string, out any) error {
    for attempt := 0; attempt < 3; attempt++ {
        err := get(path, out)
        if err == nil {
            return nil
        }
        if strings.Contains(err.Error(), "429") {
            time.Sleep(time.Duration(1<<attempt) * time.Second)
            continue
        }
        return err
    }
    return errors.New("max retries exceeded")
}

Ship this today

Get your API key in 30 seconds — free tier, no credit card.

Get your API key

Other languages

Want the full OpenAPI spec? Swagger UI →