Fejl og statuskoder
Alle fejl har samme form og en HTTP-status, der fortæller, om du skal rette kaldet, opgradere, vente eller prøve igen.
Fejlformatet
En fejl er altid et JSON-objekt med ét felt, error, der beskriver fejlen på engelsk. Forgren på HTTP-statussen, ikke på teksten, som kan blive præciseret over tid.
{ "error": "property not found" }Hvert svar bærer desuden en X-Request-Id-header. Angiv den, hvis du kontakter support om et bestemt kald.
Statuskoder
Tabellen er dannet direkte fra API’ets eget fejlkatalog — den samme liste, som API’et er kontrolleret imod, så en ny fejlstatus ikke kan tages i brug uden at stå her. Kataloget kan også hentes maskinlæsbart og uden nøgle fra GET /v1/errors, med en stabil type pr. fejltype.
| Status | Betydning i Grundfast | Prøv igen? |
|---|---|---|
| 400 | Ugyldig forespørgsel: forkert BFE- eller UUID-format, en manglende eller for kort parameter, et koordinat uden for Danmark, en ugyldig asOf, srid, cirkel eller polygon, eller et body, der ikke passer til skemaet. | Nej — ret kaldet. |
| 401 | Nøglen mangler, er ugyldig, udløbet eller tilbagekaldt. Svaret bærer en WWW-Authenticate-header, der beskriver formatet. | Nej — ret kaldet. |
| 402 | Funktionen er ikke med i din plan. Batch og webhooks kræver Pro; eksport og historik (asOf og /historik) kræver Scale. Beskeden nævner den plan, der skal til. | Nej — ret kaldet. |
| 403 | Kontoen er suspenderet, eller nøglen er en administrationsnøgle, der ikke gælder for data-endpoints. Et kald med cookie-session fra et andet site til et konto-endpoint (login, nøgler, betaling) afvises. Gælder ikke kald med API-nøgle. | Nej — ret kaldet. |
| 404 | Ressourcen findes ikke: ukendt BFE, UUID, CVR-nummer, kode eller sti. | Nej — ret kaldet. |
| 409 | Ressourcen er ikke i en tilstand, der tillader kaldet — typisk en eksport, der ikke er færdig endnu, når du henter filen. | Ja, når forudsætningen er opfyldt. |
| 413 | Request-body over 1 MB. Del kaldet op. | Nej — ret kaldet. |
| 415 | Et konto-endpoint fik et body, der ikke er application/json. Send Content-Type: application/json. | Nej — ret kaldet. |
| 422 | Jordstykket kunne findes, men bærer ingen ejerlavskode og intet matrikelnummer, så kortlægningen kan ikke slås op på matriklen. Slå op på koordinatet i stedet. | Nej — ret kaldet. |
| 429 | Burst-grænsen pr. minut for din plan er nået. Retry-After siger, hvornår vinduet åbner igen. Månedens kvote er brugt (eller sandbox-loftet for en testnøgle). Svaret bærer X-Quota-*-headere, og Retry-After peger på næste måned — prøv ikke igen automatisk. For mange forsøg med ugyldige nøgler fra samme IP-adresse. Ret nøglen og vent det antal sekunder, Retry-After angiver. | rate_limited: Ja, efter Retry-After. quota_exceeded: Nej — ret kaldet. auth_throttled: Ja, efter Retry-After. |
| 500 | En uventet fejl hos os. Den er logget med kaldets X-Request-Id; angiv det, hvis du kontakter support. | Ja, med backoff. |
| 502 | Kilden (fx Datafordeler) svarede med fejl, efter vi har prøvet igen, og der var ingen brugbar cachet kopi. | Ja, med backoff. |
| 503 | Kilden er ikke tilgængelig i øjeblikket, endpointet er ikke sat op i dette miljø (fx adresseindekset eller rumlige filtre), eller rate-limiteren er midlertidigt utilgængelig. Energimærke: ejendommen er ikke dækket endnu. Det er ikke det samme som "intet energimærke" — det ville være en 404. | Ja, med backoff. |
| 504 | Svaret tog længere end tidsgrænsen på ca. 20 sekunder. Arbejdet fortsætter i baggrunden, så et nyt kald er ofte hurtigt. | Ja, med backoff. |
Hvilke fejl tæller
- 5xx og 504 tæller ikke. Et kald, der ender i en serverfejl eller tidsgrænsen, lægges tilbage i månedens kvote.
- 4xx tæller med i kvoten. Et kald med en ugyldig BFE eller et ukendt nummer bruger en enhed, ligesom et vellykket kald.
- Kun vellykkede svar faktureres. Overforbrug på betalte planer beregnes ud fra svar under
400. - 402 og 429 tæller ikke. Plan-tjekket og rate limits afviser kaldet, før det måles.
Hvornår du skal prøve igen
- 429 fra burst-grænsen: vent det antal sekunder,
Retry-Afterangiver, og prøv igen. - 429 fra månedens kvote: svaret bærer også
X-Quota-*-headere, ogRetry-Afterpeger på næste måned. Prøv ikke igen automatisk. - 502, 503 og 504: prøv igen med eksponentiel backoff og jitter, fx 0,5 s, 1 s, 2 s. Stop efter nogle få forsøg.
- 400, 401, 402, 403 og 404: prøv aldrig igen uden at ændre kaldet. Svaret bliver det samme.
const RETRYABLE = new Set([429, 502, 503, 504]);
export async function grundfastGet<T>(path: string, maxAttempts = 4): Promise<T> {
for (let attempt = 1; ; attempt++) {
const res = await fetch(`https://api.grundfast.dk${path}`, {
headers: { Authorization: `Bearer ${process.env.GRUNDFAST_API_KEY}` },
});
if (res.ok) return (await res.json()) as T;
// Månedens kvote er en 429 med X-Quota-*-headere: den forsvinder ikke ved at vente.
const quotaExhausted = res.status === 429 && res.headers.has('X-Quota-Remaining');
if (!RETRYABLE.has(res.status) || quotaExhausted || attempt >= maxAttempts) {
const body = (await res.json().catch(() => ({}))) as { error?: string };
throw new Error(`Grundfast ${res.status}: ${body.error ?? res.statusText}`);
}
const retryAfter = Number(res.headers.get('Retry-After'));
const delayMs =
retryAfter > 0 ? retryAfter * 1000 : 2 ** (attempt - 1) * 500 + Math.random() * 250;
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
}
// const ejendom = await grundfastGet('/v1/bbr/ejendom/5651067');Fejl i SDK’et
TypeScript-SDK’et kaster en GrundfastError for ethvert svar uden for 2xx. Den har status (HTTP-statussen), message (teksten fra error) og retryAfter (sekunder fra Retry-After, når headeren findes). En timeout bliver til status 408.
import { GrundfastClient, GrundfastError } from '@grundfast/sdk';
const gf = new GrundfastClient({ apiKey: 'gf_live_...' });
try {
const ejendom = await gf.ejendom(5651067);
console.log(ejendom.antal_bygninger);
} catch (err) {
if (err instanceof GrundfastError && err.status === 404) {
console.log('Ukendt BFE');
} else if (err instanceof GrundfastError && err.status === 402) {
console.log('Kræver en højere plan:', err.message);
} else {
throw err;
}
}SDK’et prøver selv igen ved 408, 500, 502 og 503 og ved burst-429, med backoff og op til to ekstra forsøg som standard (maxRetries). Det prøver aldrig igen ved månedens kvote-429, og en eksport oprettes aldrig to gange. 504 prøves ikke igen automatisk, så håndtér den selv, hvis du vil.