> ## 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.

# Pyyntörajat

> Living Security Public API -rajapinnan pyyntökiintiöt, 429-vastauksen sopimus ja uudelleenyritys Retry-After-otsakkeen avulla.

`/v1` API soveltaa kahta toisistaan riippumatonta pyyntökiintiötä. Pyyntö hylätään,
jos jompikumpi kiintiö on käytetty loppuun.

| Kiintiö | Koskee |
| - | - |
| API-avainkohtainen | Kaikkia pyyntöjä, joissa käytetään kyseistä avainta, miltä tahansa osoitteelta |
| Asiakkaan IP-osoitekohtainen | Kaikkia pyyntöjä kyseisestä osoitteesta, todennettuja tai todentamattomia |

API-avainkohtainen kiintiö seuraa avainta sen käyttöpaikasta riippumatta. IP-osoitekohtainen kiintiö on
ainoa kiintiö todentamattomalle liikenteelle ja toinen yläraja
todennetulle liikenteelle.

<Note>
  Rajat otetaan käyttöön ennen todennusta, joten myös pyynnöt, joissa on virheelliset tai
  puuttuvat tunnistetiedot, kuluttavat lähteen kiintiötä. Tarkat numeeriset
  kiintiöt määrittää operaattori, ja ne voivat muuttua. Jäljempänä kuvattu
  vastauksen sopimus on vakaa rajapinta, jonka varaan toteutus kannattaa rakentaa.
</Note>

Todenna jommallakummalla Basic-tunnistetietojen muodolla – katso
[Pikaopas](/fi/developers/v1/quickstart) (`apikey:secret` tai `secret:`).
Aseta `BASE` organisaation alueelliseksi isännäksi – katso
[Alueet](/fi/developers/v1/regions).

## 429-vastaus

Kun kiintiö on käytetty loppuun, API palauttaa koodin `429 Too Many Requests` sekä
`Retry-After`-otsakkeen (sekunteina) ja standardin problem-details-rungon:

```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
}
```

Vastauksesta ei käy ilmi, mikä kiintiö käytettiin loppuun. Käsittele jokainen `429`
samalla tavalla: odota ja yritä sitten uudelleen.

## 429-vastausten käsittely

<Steps>
  <Step title="Noudata Retry-After-otsaketta">
    Odota vähintään `Retry-After`-otsakkeessa ilmoitettu sekuntimäärä ennen
    uudelleenyritystä. Aiempi uudelleenyritys kuluttaa vain kiintiötä pyynnöillä,
    jotka hylätään.
  </Step>

  <Step title="Kasvata odotusaikaa eksponentiaalisesti toistuvissa yrityksissä">
    Jos uudelleenyritys hylätään uudelleen, pidennä odotusaikaa ja lisää satunnaista vaihtelua (jitter),
    jotta rinnakkaiset työprosessit eivät yritä uudelleen samanaikaisesti. Älä koskaan lyhennä palvelimen `Retry-After`-arvoa paikallisen
    rajan mukaiseksi. Jos palvelin pyytää odottamaan pidempään kuin uudelleenyritysten kiintiösi sallii,
    lopeta ja ajoita työ myöhemmäksi.
  </Step>

  <Step title="Tasoita pyyntötahtia">
    Suosi tasaista pyyntötahtia piikkien sijaan. Suurissa lukuoperaatioissa käytä suurinta
    sivukokoa (`limit=500`), jolloin kokoelma katetaan vähemmillä pyynnöillä – katso
    [sivutus](/fi/developers/v1/pagination). Kun useita listauksia käydään läpi
    rinnakkain (esimerkiksi Power BI -taulut), pidä samanaikaisuus kohtuullisena ja noudata
    `Retry-After`-otsaketta, jotta tilapäinen 429-vastaus ei kaada koko päivitystä.
  </Step>
</Steps>

Tämä esimerkki yrittää uudelleen vain `429`-vastauksissa **GET**-pyynnölle, enintään
viisi kertaa ja odottaen enintään 60 sekuntia yritysten välillä. Se pysähtyy
heti muihin virheisiin. Verkon aikakatkaisut välitetään kutsujalle. Määritä
aikakatkaisut ja uudelleenyritysten kiintiöt työkuormasi mukaan. `requests` tulkitsee lukemisen
aikakatkaisun datan vastaanoton enimmäisajaksi, jolloin yhteys on toimettomana, ei kokonaisaikarajaksi.

Lataa `LIVING_SECURITY_API_KEY` salaisuuksienhallinnasta. Asenna `requests`
ennen tämän esimerkin suorittamista. Käytä esimerkkiä kutsumalla `get_with_retry("/organization")`.

```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)
```

Älä kopioi tätä silmukkaa kirjoitusoperaation ympärille. Kirjoituksen jälkeinen aikakatkaisu voi
tarkoittaa, että palvelin suoritti kirjoituksen ennen yhteyden katkeamista. Toista kirjoitus vain,
kun kyseisen operaation viitteessä on nimenomaisesti kuvattu idempotenssi, ja säilytä
sama avain ja sama sisältö. Muussa tapauksessa tarkista resurssin tila ennen uutta yritystä.

## Suositeltu päivitysaikataulu

Mitoita päivitystiheys avaimesi kiintiön ja sivukoon mukaan. Suuren kokoelman täydellinen historiallinen
lataus on kertaluonteinen kustannus; suosi vakiotilan päivityksissä inkrementaalisia aikaikkunoita, jotta jokainen ajo pysyy selvästi kiintiön alapuolella. Aseta
`limit=500` aina nimenomaisesti – oletusarvo 25 kasvattaa pyyntöjen määrää moninkertaiseksi.


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