API

Overview

The GeoRedirect.io API resolves the best destination URL for a visitor based on geo context (country, region, ASN, CIDR, etc.). Make a single POST to receive a decision in ~20ms median.

  • Base URL
    https://api.georedirect.io
  • Version
    v1
  • Format
    application/json

Authentication

Use a Bearer token in the Authorization header.

Authorization: Bearer <API_KEY>

Rotate keys regularly. Keep them secret; do not embed in public clients.

POST /v1/resolve

Resolve the destination URL for a visitor using IP and rules. If multiple rules match, the first match wins.

Request Body

{
  "ip": "203.0.113.50",
  "user_agent": "optional user agent string",
  "rules": [
    { "if": { "country": "US" }, "to": "https://example.com/us" },
    { "if": { "country": "DE" }, "to": "https://example.com/de" },
    { "else": "https://example.com/global" }
  ],
  "metadata": { "sessionId": "abc123" }
}

Response

{
  "to": "https://example.com/us",
  "matched": { "country": "US" },
  "latency_ms": 18,
  "trace_id": "trc_7QyZb2"
}
cURL
curl -X POST https://api.georedirect.io/v1/resolve \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "ip": "203.0.113.50",
    "rules": [
      {"if": {"country": "US"}, "to": "https://example.com/us"},
      {"if": {"country": "DE"}, "to": "https://example.com/de"},
      {"else": "https://example.com/global"}
    ]
  }'
PHP
$ch = curl_init("https://api.georedirect.io/v1/resolve");
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer <API_KEY>",
    "Content-Type: application/json"
  ],
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POSTFIELDS => json_encode([
    "ip" => "203.0.113.50",
    "rules" => [
      ["if" => ["country" => "US"], "to" => "https://example.com/us"],
      ["if" => ["country" => "DE"], "to" => "https://example.com/de"],
      ["else" => "https://example.com/global"]
    ]
  ])
]);
$res = curl_exec($ch);
Node (fetch)
const res = await fetch("https://api.georedirect.io/v1/resolve", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <API_KEY>",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    ip: "203.0.113.50",
    rules: [
      { if: { country: "US" }, to: "https://example.com/us" },
      { if: { country: "DE" }, to: "https://example.com/de" },
      { else: "https://example.com/global" }
    ]
  })
});
const data = await res.json();

GET /v1/health

Public health check for monitoring.

GET https://api.georedirect.io/v1/health

200 OK
{ "status": "ok", "uptime": 123456 }

GET /v1/ipinfo

Return geo context for an IP (country, region, ASN).

GET https://api.georedirect.io/v1/ipinfo?ip=203.0.113.50
Authorization: Bearer <API_KEY>

200 OK
{
  "ip": "203.0.113.50",
  "country": "US",
  "region": "CA",
  "asn": 15169
}

Errors

Status Code Message
400 bad_request Your payload is invalid or incomplete.
401 unauthorized Missing or invalid API key.
403 forbidden Key lacks permission for this endpoint.
404 not_found Resource not found.
429 rate_limited Too many requests. See rate limits.
500 server_error Unexpected error. Try again.

Error schema

{
  "error": {
    "status": 401,
    "code": "unauthorized",
    "message": "Missing or invalid API key",
    "trace_id": "trc_7QyZb2"
  }
}

Rate limits

Requests per month by plan. Bursting is allowed within reason; sustained abuse triggers 429.

Plan Included Overage
Free500 / moNot available
Starter10k / moContact support
Pro50k / moContact support
ScaleCustomContract

SDKs

Official SDKs (coming soon): PHP, Node.js, Python.

  • PHP
  • Node.js
  • Python

Webhooks

Configure webhooks to receive decision events and analytics asynchronously. We sign webhook payloads; verify signatures on your side.

{
  "event": "resolve.completed",
  "to": "https://example.com/us",
  "matched": { "country": "US" },
  "latency_ms": 18,
  "trace_id": "trc_7QyZb2",
  "delivered_at": "2025-08-13T10:12:33Z",
  "signature": "v1=hex..."
}