Overvåg forbruget med X-RateLimit-headers

Læs kvote og minutgrænse fra svarenes headers, log og alarmér ved 80 procent, og brug forbrugssiden i dashboardet.

4 min Niveau: Øvet ✓ Kode testet

Du vil vide, at du nærmer dig kvoten, før kaldene begynder at fejle eller koste ekstra. Hvert svar fortæller, hvor meget der er tilbage, så din egen kode kan holde øje uden ekstra kald.

Der er ikke et REST-endpoint, som returnerer forbruget pr. nøgle. Du har to kilder: headerne på hvert svar og siden Forbrug i dashboardet. Bruger du vores MCP-server, viser værktøjet quota_status også månedens forbrug. /api/v1/stats er noget andet. Det er offentlige tal for, hvor mange adresser, veje og postnumre vi har, og det siger intet om dit forbrug.

Headerne

Hvert kald med en gyldig nøgle har disse headers:

HeaderIndhold
X-RateLimit-LimitMånedskvoten for den pulje, kaldet tæller i
X-RateLimit-RemainingHvad der er tilbage af månedskvoten efter dette kald
X-RateLimit-ResetUnix-tidsstempel (sekunder, UTC) for, hvornår måneden nulstilles: den 1. i næste måned kl. 00.00 UTC
X-RateLimit-Minute-LimitKald pr. minut, eller unlimited på Enterprise
X-RateLimit-Minute-RemainingHvad der er tilbage i det aktuelle minut
X-RateLimit-Minute-ResetUnix-tidsstempel for, hvornår minuttet nulstilles
X-Quota-Gracetrue, når en gratiskonto er over kvoten og får svar fra bufferen
X-Quota-RemainingKald tilbage i bufferen. Kun sammen med X-Quota-Grace
X-Danadresse-Key-StatusKun til stede, hvis nøglen er markeret: warn eller blocked

Hvilken pulje kaldet tæller i, afhænger af nøglen:

  • På gratisplanen (Hobby) deler alle kontoens live-nøgler én månedskvote på 2 000 kald.
  • På betalte planer har hver nøgle sin egen tæller.
  • Testnøgler tælles pr. IP-adresse på gratisplanens niveau. Se Testnøgler og sandbox.
  • Kald fra MCP-serveren har deres egen kvote, og så viser headerne MCP-kvoten.

På gratisplanen er der en buffer efter kvoten. Når X-RateLimit-Remaining er 0, får du stadig svar op til 2 400 kald, med X-Quota-Grace: true og X-Quota-Remaining. Når bufferen er brugt, svarer API'et 429 quota_exceeded indtil næste måned. På de betalte planer kan du fortsætte over kvoten, og de ekstra kald bliver faktureret. X-RateLimit-Remaining bliver stående på 0 resten af måneden. Vil du have et loft over merforbruget, så sæt et budgetloft under Betaling. Afviste kald (429) tæller ikke med i forbruget. Grænsen pr. minut er hård på alle planer undtagen Enterprise.

Se headerne fra terminalen:

Shell#headers-curl
curl -s -D - -o /dev/null "https://api.danadresse.dk/postnumre/8000" \
  -H "X-Api-Key: $DANADRESSE_API_KEY" | tr '[:upper:]' '[:lower:]' | grep -E '^x-(ratelimit|quota|danadresse)'

Læs headerne i din kode

Læs dem på hvert svar, du alligevel får, og send tallene videre til din logning eller dit metriksystem. Eksemplet beregner, hvor stor en del af måneden der er brugt, og advarer ved 80 procent:

Python#read-headers
import os
from datetime import datetime, timezone

import requests

ALARM_VED = 0.8


def forbrug(r: requests.Response) -> dict:
    h = r.headers
    limit = h.get("X-RateLimit-Limit", "")
    rest = h.get("X-RateLimit-Remaining", "")
    if not (limit.isdigit() and rest.isdigit()):
        return {}
    limit, rest = int(limit), int(rest)
    return {
        "limit": limit,
        "rest": rest,
        "andel": (limit - rest) / limit if limit else 0.0,
        "nulstilles": datetime.fromtimestamp(int(h.get("X-RateLimit-Reset", "0")), timezone.utc),
        "minut_rest": h.get("X-RateLimit-Minute-Remaining"),
        "noeglestatus": h.get("X-Danadresse-Key-Status"),
    }


r = requests.get(
    "https://api.danadresse.dk/postnumre/8000",
    headers={"X-Api-Key": os.environ["DANADRESSE_API_KEY"]},
    timeout=10,
)
f = forbrug(r)
print(f"brugt {f['andel']:.1%} af {f['limit']} kald, {f['rest']} tilbage, nulstilles {f['nulstilles']:%Y-%m-%d}")
print(f"tilbage i dette minut: {f['minut_rest']}")
if f["andel"] >= ALARM_VED:
    print("ADVARSEL: over 80 % af månedskvoten er brugt")
if f["noeglestatus"]:
    print(f"ADVARSEL: nøglen er markeret som {f['noeglestatus']} - se /dashboard/keys")

I en rigtig tjeneste skal advarslen kun sendes én gang pr. måned. Brug værdien i X-RateLimit-Reset som nøgle: har du allerede advaret for den værdi, så lad være igen. Her er det samme som en lille fetch-indpakning i Node, der sender advarslen til din egen funktion:

JavaScript#node-monitor
const advaretFor = new Set();

export async function danadresseFetch(url, init = {}, advar = console.warn) {
  const res = await fetch(url, {
    ...init,
    headers: { ...init.headers, "X-Api-Key": process.env.DANADRESSE_API_KEY },
  });
  const limit = Number(res.headers.get("x-ratelimit-limit"));
  const rest = Number(res.headers.get("x-ratelimit-remaining"));
  const reset = res.headers.get("x-ratelimit-reset");
  if (limit > 0 && Number.isFinite(rest) && (limit - rest) / limit >= 0.8 && !advaretFor.has(reset)) {
    advaretFor.add(reset);
    advar(`Danadresse: ${limit - rest} af ${limit} kald brugt denne måned`);
  }
  const status = res.headers.get("x-danadresse-key-status");
  if (status) advar(`Danadresse: nøglen er markeret som ${status}`);
  return res;
}

Kører du flere processer, så send tallene til et fælles sted (Prometheus, Datadog, en databasetabel) i stedet for at advare fra hver proces.

Plads pr. minut

X-RateLimit-Minute-Remaining er det tal, der betyder noget for batchjob. Når den nærmer sig 0, så hold en pause til X-RateLimit-Minute-Reset i stedet for at løbe ind i 429. Grænsen er 360 kald i minuttet på Hobby, 1 700 på Basis og 7 000 på Pro.

Python#minute-pacing
import time


def vent_hvis_noedvendigt(r, reserve: int = 5) -> None:
    """Kald efter hvert svar i et batchjob. Holder pause, før minutgrænsen rammes."""
    rest = r.headers.get("X-RateLimit-Minute-Remaining", "")
    reset = r.headers.get("X-RateLimit-Minute-Reset", "")
    if rest.isdigit() and reset.isdigit() and int(rest) <= reserve:
        time.sleep(max(0, int(reset) - time.time()) + 0.5)

I browseren

Kalder du API'et fra en webside, kan dit script læse alle X-RateLimit-*-headerne, X-Quota-Grace, X-Quota-Remaining og Retry-After. De er frigivet via CORS. X-Danadresse-Key-Status er ikke, men domænelåste browsernøgler bliver heller aldrig markeret som lækkede. Til overvågning er det stadig bedst at samle tallene på serversiden eller kigge i dashboardet, fordi tallene i en browser kun når frem til den besøgende, ikke til dig.

Forbrugssiden i dashboardet

Forbrug viser kontoens kald og fejl pr. dag for de seneste 30 dage, summen og den travleste dag. Tallene gælder hele kontoen, ikke den enkelte nøgle, og de bliver opdateret med en lille forsinkelse. Brug siden til at se udviklingen, og brug headerne til alarmer.

Næste skridt

Relaterede guides

Markdown-kilde Fejl i guiden? Skriv til os API-reference (Swagger)

Prøv det med en gratis nøgle

2 000 kald/måned på gratisplanen. Intet kreditkort.

Opret konto →