> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livingsecurity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Forespørselsgrenser

> Forespørselsbudsjetter for Living Security Public API, 429-svarkontrakten og hvordan man prøver på nytt med Retry-After.

API-et `/v1` håndhever to uavhengige forespørselsbudsjetter. En forespørsel avvises
hvis ett av budsjettene er brukt opp.

| Budsjett | Gjelder for |
| - | - |
| Per API-nøkkel | Alle forespørsler som bruker den nøkkelen, fra en hvilken som helst adresse |
| Per klient-IP | Alle forespørsler fra den adressen, autentisert eller ikke |

Budsjettet per nøkkel følger nøkkelen uansett hvor den brukes. Budsjettet per IP
er det eneste budsjettet for uautentisert trafikk og en ekstra øvre grense for
autentisert trafikk.

<Note>
  Grensene håndheves før autentisering, slik at forespørsler med ugyldig eller
  manglende legitimasjon også teller mot kildens budsjett. De nøyaktige tallverdiene
  for budsjettene konfigureres av operatøren og kan endres. Svarkontrakten nedenfor
  er det stabile grensesnittet du bør bygge på.
</Note>

Autentiser med en av de to Basic-legitimasjonsformene – se
[Hurtigstart](/no/developers/v1/quickstart) (`apikey:secret` eller `secret:`).
Sett `BASE` til organisasjonens regionale vert – se
[Regioner](/no/developers/v1/regions).

## 429-svaret

Når et budsjett er brukt opp, returnerer API-et `429 Too Many Requests` med en
`Retry-After`-header (i sekunder) og standard problem-details-innhold:

```json 429 Too Many Requests theme={null}
{
  "type": "https://docs.livingsecurity.com/developers/v1/errors/rate_limited",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded. Retry after the Retry-After interval.",
  "code": "rate_limited",
  "request_id": "req_...",
  "doc_url": "https://docs.livingsecurity.com/developers/v1/errors/rate_limited",
  "retryable": true
}
```

Svaret oppgir ikke hvilket budsjett som er brukt opp. Behandle alle `429` på
samme måte: vent, og prøv deretter på nytt.

## Håndtering av 429-svar

<Steps>
  <Step title="Overhold Retry-After">
    Vent minst det antallet sekunder som står i `Retry-After`-headeren før du
    prøver på nytt. Hvis du prøver på nytt tidligere, bruker du bare opp budsjett
    på forespørsler som uansett vil bli avvist.
  </Step>

  <Step title="Bruk eksponentiell backoff ved gjentatte avvisninger">
    Hvis et nytt forsøk avvises igjen, øker du ventetiden og legger til tilfeldig jitter
    slik at parallelle arbeidsprosesser ikke prøver på nytt samtidig. Forkort aldri serverens `Retry-After` for å passe en lokal
    grense. Hvis serveren ber deg vente lenger enn det forsøksbudsjettet ditt tillater,
    bør du avslutte og planlegge jobben til et senere tidspunkt.
  </Step>

  <Step title="Jevn ut forespørselsraten">
    Foretrekk en jevn forespørselsrate framfor rykkvise bølger av forespørsler. Ved masseuthenting bruker du maksimal
    sidestørrelse (`limit=500`) for å dekke samlingen med færre forespørsler – se
    [paginering](/no/developers/v1/pagination). Når flere listegjennomganger kjører
    parallelt (for eksempel Power BI-tabeller), bør du holde samtidigheten moderat og overholde
    `Retry-After` slik at en midlertidig 429 ikke får hele oppdateringen til å mislykkes.
  </Step>
</Steps>

Dette eksempelet prøver bare på nytt ved `429`-svar for en **GET**-forespørsel, med maksimalt
fem forsøk og maksimalt 60 sekunders ventetid mellom forsøkene. Det stopper
umiddelbart ved andre feil. Nettverkstidsavbrudd sendes videre til den som kaller. Konfigurer
tidsavbrudd og forsøksbudsjetter etter din arbeidsbelastning. `requests` tolker lesetidsavbruddet
som maksimal inaktiv tid under mottak av data, ikke som en samlet tidsfrist.

Last inn `LIVING_SECURITY_API_KEY` fra hemmelighetsbehandleren din. Installer `requests`
før du kjører dette eksempelet. Kall `get_with_retry("/organization")` for å bruke det.

```python Python theme={null}
import os
import random
import time
import requests

# US: BASE = "https://api.us-east-1.livingsecurity.ai/v1"
BASE = "https://api.eu-west-1.livingsecurity.ai/v1"
AUTH = ("apikey", os.environ["LIVING_SECURITY_API_KEY"])

def get_with_retry(path, params=None, max_attempts=5):
    if not 1 <= max_attempts <= 5:
        raise ValueError("max_attempts must be between 1 and 5")
    for attempt in range(max_attempts):
        response = requests.get(
            f"{BASE}{path}", auth=AUTH, params=params,
            headers={"Living-Security-Version": "2026-07-01"},
            timeout=(5, 30), allow_redirects=False,
        )
        if response.status_code != 429:
            response.raise_for_status()
            if not 200 <= response.status_code < 300:
                raise RuntimeError("Unexpected redirect; check your regional API URL")
            return response

        # The API returns Retry-After as a whole number of seconds.
        raw_wait = response.headers.get("Retry-After", "")
        request_id = response.headers.get("Request-Id", "unknown")
        response.close()
        if attempt == max_attempts - 1:
            raise RuntimeError(f"Retry budget exhausted; request_id={request_id}")
        if not raw_wait.isascii() or not raw_wait.isdigit() or len(raw_wait) > 6:
            raise RuntimeError(f"Invalid Retry-After; request_id={request_id}")

        wait = max(int(raw_wait), min(2 ** attempt, 30))
        delay = wait + random.uniform(0, 1)
        if delay > 60:
            raise RuntimeError(f"Retry-After exceeds wait budget; request_id={request_id}")
        time.sleep(delay)
```

Ikke kopier denne løkken rundt en skriveoperasjon. Et tidsavbrudd etter en skriving kan
bety at serveren rakk å lagre endringen før forbindelsen brøt sammen. Gjenta en skriving bare
når referansen for den aktuelle operasjonen uttrykkelig dokumenterer idempotens, og bevar
den samme nøkkelen og den samme nyttelasten. Ellers må du avstemme ressursens tilstand før du prøver på nytt.

## Anbefalt oppdateringsplan

Dimensjoner oppdateringsfrekvensen ut fra nøkkelbudsjettet og sidestørrelsen din. En fullstendig historisk
innlasting av en stor samling er en engangskostnad. Foretrekk inkrementelle vinduer for
jevnlige oppdateringer, slik at hver kjøring holder seg godt innenfor budsjettet. Angi alltid
`limit=500` eksplisitt – standardverdien 25 multipliserer antall forespørsler.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.