Skip to content
locate-me v0.1.0
Checking

ReferenceErrors

Errors

Every error is JSON with a stable machine-readable code and a short message for people. Branch on error, never on the message.

Shape

HTTP/1.1 404 Not Found
content-type: application/json

{
  "error": "reserved_address",
  "message": "private or reserved addresses have no location"
}

The status code tells you who should act: 4xx means change the request, 429 and 503 mean wait and retry. Inside a bulk response, entries that fail carry only {"ip", "error"} and the request itself still succeeds.

Codes(18)

StatusCodeMeaning and what to do
400invalid_ipNot a valid IPv4 or IPv6 address. Send the address without port, brackets or zone ID.
400invalid_langlang is not one of en, de, es, fr, ja, pt-BR, ru, zh-CN.
400invalid_bodyThe bulk body is not {"ips": ["..."]}. The message names the JSON problem.
401unauthorizedThe key is missing, unknown or disabled. See Authentication.
404not_foundThe database has no location for this address. Not an error in your request.
404reserved_addressA private, loopback, link-local, documentation, multicast or other special-purpose address. These never have a location.
404route_not_foundNo such endpoint. Check the path and the /v1 prefix.
405method_not_allowedThe endpoint exists but not with this method.
413payload_too_largeThe body is larger than server.max_body_bytes. Send fewer addresses per request.
415unsupported_media_typeA bulk request without Content-Type: application/json.
422empty_batchips is empty.
422batch_too_largeMore addresses than limits.bulk_max_ips. Split the batch.
429rate_limitedOut of units. Wait Retry-After seconds, then retry. See Rate Limits.
429exceeds_burstThe request costs more than the key's burst and can never succeed. Split the batch; do not retry.
500internal_errorA bug or a damaged database. The server keeps running; report it with the time of the request.
503database_unavailableNo database is loaded yet, usually right after the first start. Retry-After: 30.
503overloadedToo many requests in flight (server.max_inflight_requests). Retry-After: 1.
503timeoutThe request took longer than server.request_timeout_ms. Retry-After: 1.

Retrying

Retry only 429 rate_limited and 503, after the Retry-After delay, with a little jitter so clients do not return in step. Give up after a few attempts.

JavaScript
const BASE = "http://localhost:8080";

async function locate(ip, attempts = 3) {
  const url = `${BASE}/v1/lookup/${encodeURIComponent(ip)}`;
  for (let i = 0; ; i++) {
    const res = await fetch(url, {
      headers: { "X-API-Key": process.env.LOCATE_ME_KEY },
    });
    const body = await res.json();
    if (res.ok) return body;
    const retry = res.status === 503 || body.error === "rate_limited";
    if (!retry || i + 1 >= attempts) throw new Error(body.error);
    const wait = Number(res.headers.get("retry-after") ?? 1) * 1000;
    await new Promise((r) => setTimeout(r, wait + Math.random() * 250));
  }
}
Esc