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

# Batas Laju

> Anggaran permintaan untuk Living Security Public API, kontrak respons 429, dan cara mencoba ulang dengan Retry-After.

API `/v1` menerapkan dua anggaran permintaan yang independen. Suatu permintaan
ditolak jika salah satu anggaran telah habis.

| Anggaran | Berlaku untuk |
| - | - |
| Per kunci API | Setiap permintaan yang menyertakan kunci tersebut, dari alamat mana pun |
| Per IP klien | Setiap permintaan dari alamat tersebut, baik terautentikasi maupun tidak |

Anggaran per kunci mengikuti kunci tersebut ke mana pun kunci itu digunakan. Anggaran per IP
merupakan satu-satunya anggaran untuk lalu lintas yang tidak terautentikasi dan menjadi batas kedua untuk
lalu lintas yang terautentikasi.

<Note>
  Batas diberlakukan sebelum autentikasi, sehingga permintaan dengan kredensial yang tidak valid atau
  tidak ada juga dihitung terhadap anggaran sumber. Anggaran numerik yang tepat
  dikonfigurasi oleh operator dan dapat berubah; kontrak respons di bawah ini
  adalah antarmuka stabil yang dapat dijadikan acuan dalam pengembangan.
</Note>

Lakukan autentikasi dengan salah satu bentuk kredensial Basic — lihat
[Panduan Memulai](/id/developers/v1/quickstart) (`apikey:secret` atau `secret:`).
Atur `BASE` ke host regional organisasi — lihat
[Wilayah](/id/developers/v1/regions).

## Respons 429

Ketika suatu anggaran habis, API mengembalikan `429 Too Many Requests` dengan header
`Retry-After` (dalam detik) dan isi problem-details standar:

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

Respons tidak menyebutkan anggaran mana yang habis. Perlakukan setiap `429`
dengan cara yang sama: tunggu, lalu coba lagi.

## Menangani 429

<Steps>
  <Step title="Patuhi Retry-After">
    Tunggu setidaknya selama jumlah detik yang tercantum pada header `Retry-After` sebelum
    mencoba ulang. Mencoba ulang lebih awal hanya akan kembali menghabiskan anggaran pada permintaan yang akan
    ditolak.
  </Step>

  <Step title="Lakukan backoff eksponensial pada pengulangan">
    Jika percobaan ulang kembali ditolak, perpanjang backoff Anda dan tambahkan jitter acak
    agar worker paralel tidak mencoba ulang secara bersamaan. Jangan pernah memperpendek `Retry-After` dari server agar sesuai dengan batas
    lokal. Jika server meminta Anda menunggu lebih lama daripada yang diizinkan oleh anggaran percobaan ulang Anda,
    hentikan dan jadwalkan pekerjaan tersebut untuk nanti.
  </Step>

  <Step title="Haluskan laju permintaan Anda">
    Utamakan laju permintaan yang stabil daripada lonjakan. Untuk pembacaan data dalam jumlah besar, gunakan ukuran
    halaman maksimum (`limit=500`) agar seluruh koleksi dapat dicakup dengan lebih sedikit permintaan — lihat
    [paginasi](/id/developers/v1/pagination). Ketika beberapa penelusuran daftar berjalan
    secara paralel (misalnya tabel Power BI), jaga konkurensi tetap moderat dan patuhi
    `Retry-After` agar 429 yang bersifat sementara tidak menggagalkan seluruh proses penyegaran.
  </Step>
</Steps>

Contoh ini hanya mencoba ulang respons `429` untuk permintaan **GET**, dengan paling banyak
lima percobaan dan waktu tunggu paling lama 60 detik di antara percobaan. Contoh ini berhenti
segera pada kesalahan lainnya. Timeout jaringan diteruskan ke pemanggil. Konfigurasikan
timeout dan anggaran percobaan ulang sesuai dengan beban kerja Anda. `requests` menafsirkan read
timeout sebagai waktu idle maksimum saat menerima data, bukan batas waktu keseluruhan.

Muat `LIVING_SECURITY_API_KEY` dari secret manager Anda. Instal `requests`
sebelum menjalankan contoh ini. Panggil `get_with_retry("/organization")` untuk menggunakannya.

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

Jangan menyalin perulangan ini untuk operasi tulis. Timeout setelah operasi tulis dapat
berarti server telah menyimpan perubahan tersebut sebelum koneksi gagal. Ulangi operasi tulis hanya
jika referensi operasi tersebut secara eksplisit mendokumentasikan idempotensi, dengan mempertahankan
kunci dan payload yang sama. Jika tidak, rekonsiliasi status sumber daya sebelum mencoba lagi.

## Jadwal penyegaran yang direkomendasikan

Sesuaikan frekuensi penyegaran dengan anggaran kunci dan ukuran halaman Anda. Pemuatan riwayat lengkap
dari koleksi besar hanya menimbulkan biaya satu kali; utamakan jendela inkremental untuk
penyegaran kondisi stabil agar setiap proses tetap jauh di bawah anggaran. Selalu atur
`limit=500` secara eksplisit — nilai default 25 melipatgandakan jumlah permintaan.


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