> For the complete documentation index, see [llms.txt](https://docs.okup.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.okup.ai/okupai-api/basics/authentication.md).

# Authentication

Authenticate to the API

Use an API key passed via the `X-API-Key` HTTP header to authenticate every request.

* **Header**: `X-API-Key: YOUR_API_KEY`
* **Base path**: `https://api.okup.ai/data/...`

#### Getting an API key

* **Request access** from OkupAI support or your account manager.
* Keys are **shown only once** when created; store them securely. If lost, mint a new key and revoke the old one.

#### Send your key in requests

Use the `X-API-Key` header on every call.

```bash
curl -sS \
  -H 'X-API-Key: YOUR_API_KEY' \
  'Https://api.okup.ai/data/bookings?from=2025-01-01&to=2025-01-31&limit=2'
```

Example JSON response (truncated):

```json
{
  "total": 42,
  "limit": 2,
  "offset": 0,
  "has_more": true,
  "next_offset": 2,
  "items": [
    {
      "internal_booking_id": "b3d1…",
      "booking_id": "123456789",
      "platform": "airbnb",
      "friendly_name": "Main Apartment",
      "listing_id": "987654",
      "booking_date": "2025-01-02",
      "reservation_start": "2025-01-10",
      "reservation_end": "2025-01-12",
      "status": "confirmed",
      "guest_name": "Jane Doe",
      "currency": "EUR"
    }
  ]
}
```

#### Authorization and data scope

* Your key is tied to your account and client access.
* Responses are automatically filtered to the units you’re allowed to access.
* If you currently have no unit access, list endpoints return an empty `items` array and `total: 0`.

#### Error codes

* **401 Unauthorized**: Missing `X-API-Key` header.
* **403 Forbidden**: Invalid, expired, revoked, or unsupported API key.
* **429 Too Many Requests**: The key exceeded its request allowance. Wait for the number of seconds in `Retry-After` before retrying.

#### Key lifecycle and separation

* API keys may expire or be revoked. Stop using a key immediately when OkupAI returns `403`.
* OkupAI records `last_used_at` for active keys so unused credentials can be identified and rotated.
* Site-bound Booking Engine keys start with `okw_` and work only with `/website/v1`. They are intentionally rejected by `/data/*`.
* Never expose any API key in browser JavaScript, mobile apps, logs, URLs, or source control. Send requests from your backend and keep the key in an environment variable or secret manager.

#### Rate limits

The default limits are **300 read requests per minute** and **30 write requests per minute**, per API key. Successful responses include:

* `X-RateLimit-Limit`
* `X-RateLimit-Remaining`

When the limit is exceeded, the API returns JSON with status `429` and a `Retry-After` header. Respect that header and retry with exponential backoff and jitter. Do not run several full-sync jobs for the same account at the same time.

{% tabs %}
{% tab title="JavaScript" %}

```js
// Server-side (Node 18+). Don’t expose API keys in the browser.
const BASE_URL = 'https://api.okup.ai';
const API_KEY = process.env.OKUPAI_API_KEY;

const res = await fetch(`${BASE_URL}/data/bookings?from=2025-01-01&to=2025-01-31&limit=10`, {
  headers: { 'X-API-Key': API_KEY },
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const data = await res.json();
console.log(data);
```

{% endtab %}

{% tab title="Python" %}

```python
import os, requests

BASE_URL = "https://api.okup.ai"
API_KEY = os.environ["OKUPAI_API_KEY"]

r = requests.get(
    f"{BASE_URL}/data/bookings",
    headers={"X-API-Key": API_KEY},
    params={"from": "2025-01-01", "to": "2025-01-31", "limit": 10},
    timeout=30,
)
r.raise_for_status()
print(r.json())
```

{% endtab %}

{% tab title="cURL" %}

```bash
curl -sS \
  -H "X-API-Key: $OKUPAI_API_KEY" \
  "https://api.okup.ai/data/bookings?from=2025-01-01&to=2025-01-31&limit=10"
```

{% endtab %}
{% endtabs %}
