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

# Limiti di frequenza

> I budget di richieste per la Living Security Public API, il contratto della risposta 429 e come riprovare utilizzando Retry-After.

L'API `/v1` applica due budget di richieste indipendenti. Una richiesta viene rifiutata
se uno dei due budget è esaurito.

| Budget | Si applica a |
| - | - |
| Per chiave API | Ogni richiesta che presenta tale chiave, da qualsiasi indirizzo |
| Per IP del client | Ogni richiesta proveniente da tale indirizzo, autenticata o meno |

Il budget per chiave segue la chiave ovunque venga utilizzata. Il budget per IP è
l'unico budget per il traffico non autenticato e rappresenta un secondo limite per
il traffico autenticato.

<Note>
  I limiti vengono applicati prima dell'autenticazione, pertanto anche le richieste con credenziali non valide o
  mancanti vengono conteggiate nel budget dell'origine. I valori numerici esatti dei budget sono
  configurati dall'operatore e possono cambiare; il contratto della risposta descritto di seguito
  è l'interfaccia stabile su cui basare lo sviluppo.
</Note>

Eseguite l'autenticazione con una delle due forme di credenziali Basic: consultate la
[Guida introduttiva](/it/developers/v1/quickstart) (`apikey:secret` oppure `secret:`).
Impostate `BASE` sull'host regionale dell'organizzazione: consultate
[Regioni](/it/developers/v1/regions).

## La risposta 429

Quando un budget è esaurito, l'API restituisce `429 Too Many Requests` con un'intestazione
`Retry-After` (in secondi) e il corpo standard problem-details:

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

La risposta non indica quale budget sia stato esaurito. Trattate ogni `429`
allo stesso modo: attendete, quindi riprovate.

## Gestione delle risposte 429

<Steps>
  <Step title="Rispettare Retry-After">
    Attendete almeno il numero di secondi indicato nell'intestazione `Retry-After` prima di
    riprovare. Riprovare prima non fa che consumare nuovamente budget con richieste che
    verranno rifiutate.
  </Step>

  <Step title="Applicare un backoff esponenziale in caso di ripetizioni">
    Se un nuovo tentativo viene rifiutato ancora, aumentate il backoff e aggiungete un jitter casuale
    in modo che i worker paralleli non riprovino in sincronia. Non accorciate mai il valore `Retry-After` del server per adattarlo a un
    limite locale. Se il server richiede un'attesa più lunga di quella consentita dal vostro budget di tentativi,
    interrompete e pianificate l'operazione per un momento successivo.
  </Step>

  <Step title="Distribuire in modo uniforme la frequenza delle richieste">
    Preferite una frequenza di richieste costante ai picchi improvvisi. Per le letture di grandi quantità di dati, utilizzate la dimensione massima
    della pagina (`limit=500`) per coprire la raccolta con meno richieste: consultate
    [paginazione](/it/developers/v1/pagination). Quando più scansioni di elenchi vengono eseguite
    in parallelo (ad esempio le tabelle di Power BI), mantenete una concorrenza moderata e rispettate
    `Retry-After`, in modo che un 429 temporaneo non faccia fallire l'intero aggiornamento.
  </Step>
</Steps>

Questo esempio riprova solo le risposte `429` per una richiesta **GET**, con al massimo
cinque tentativi e al massimo 60 secondi di attesa tra un tentativo e l'altro. Si interrompe
immediatamente in caso di altri errori. I timeout di rete vengono propagati al chiamante. Configurate
i timeout e i budget di tentativi in base al vostro carico di lavoro. `requests` interpreta il timeout di
lettura come il tempo massimo di inattività durante la ricezione dei dati, non come una scadenza complessiva.

Caricate `LIVING_SECURITY_API_KEY` dal vostro gestore dei segreti. Installate `requests`
prima di eseguire questo esempio. Chiamate `get_with_retry("/organization")` per utilizzarlo.

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

Non copiate questo ciclo attorno a un'operazione di scrittura. Un timeout dopo una scrittura può
significare che il server l'ha confermata prima che la connessione cadesse. Ripetete una scrittura solo
quando il riferimento di tale operazione documenta esplicitamente l'idempotenza, mantenendo
la stessa chiave e lo stesso payload. In caso contrario, riconciliate lo stato della risorsa prima di riprovare.

## Pianificazione di aggiornamento consigliata

Dimensionate la cadenza di aggiornamento in base al budget della vostra chiave e alla dimensione della pagina. Un caricamento storico completo
di una raccolta di grandi dimensioni è un costo una tantum; per gli aggiornamenti a regime preferite finestre incrementali, in modo che ogni esecuzione rimanga ben al di sotto del budget. Impostate sempre
`limit=500` in modo esplicito: il valore predefinito di 25 moltiplica il numero di richieste.


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