
# API Keys API

Met deze endpoints kunt u de API-sleutels van uw account vanuit code beheren. Ze werken allemaal uitsluitend op de sleutels van het aanroepende account.

Er zijn twee soorten sleutels, en ze bevinden zich op afzonderlijke paden:

- **Uw hoofdsleutel** — de enige sleutel met volledige toegang onder **Instellingen → Integraties → API-sleutel**. Bekijk het gemaskeerde voorbeeld, controleer uw gebruik van de snelheidslimiet, roteer de sleutel of trek deze in. Dit zijn de `/api-keys/current`, `/api-keys/rotate` en `/api-keys/usage` endpoints hieronder.
- **Scoped sleutels** — extra, benoemde sleutels die u aanmaakt voor een specifieke taak, elk beperkt tot de onderdelen van de API die u kiest. Dit zijn de `/api-keys` en `/api-keys/{id}` endpoints onder [Scoped sleutels](#scoped-keys). Er verandert niets aan uw hoofdsleutel wanneer u er een aanmaakt; bestaande integraties blijven onaangetast.

Alle onderstaande paden zijn relatief ten opzichte van de API-basis-URL:

```
https://api.youraiconnector.com/v1
```

Elk verzoek moet worden geverifieerd. Zie [Authenticatie](authentication.md) voor de vier geaccepteerde methoden. De voorbeelden hier gebruiken de `X-API-Key`-header (en één queryparameter-vorm voor cURL).

> **Lees dit eerst.** Het roteren of intrekken van uw sleutel is **onmiddellijk** van kracht. Zodra een van beide aanroepen slaagt, werkt de oude sleutel niet meer — elke integratie die deze nog gebruikt, begint `401`-fouten te ontvangen. Plan dit zorgvuldig: roteer tijdens een onderhoudsvenster en werk al uw integraties direct bij.

---

## Huidige sleutelmetadata ophalen

Geeft uw actieve sleutel terug: de volledige sleutel in `api_key` wanneer er een opvraagbaar exemplaar bestaat, een gemaskeerd voorbeeld (de eerste 4 en laatste 4 tekens), en, indien beschikbaar, de datum waarop deze is aangemaakt. `api_key` is `null` voor sleutels die zijn aangemaakt voordat opvraagbare exemplaren werden bewaard — roteer één keer en de nieuwe sleutel kan later opnieuw worden getoond.

`GET /api-keys/current`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/api-keys/current?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/api-keys/current", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/api-keys/current",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwoord**

```json
{
  "success": true,
  "api_key": "abcdEFGH1234ijkl5678MNOP9012qrst",
  "api_key_masked": "abcd...qrst",
  "created_at": "2026-06-01T10:00:00.000Z"
}
```

Als het account geen API-sleutel heeft, is het antwoord `404` met `{ "success": false, "error": "No API key found for this account" }`.

---

## Gebruik van snelheidslimiet ophalen

Geeft uw gebruik van de snelheidslimiet voor het huidige venster terug: de verzoeklimiet per venster, hoeveel verzoeken er tot nu toe zijn geteld, hoeveel er overblijven en wanneer het venster wordt gereset. Gebruik dit om client-side throttling op te bouwen, zodat uw integratie vertraagt voordat deze `429`-antwoorden bereikt.

`GET /api-keys/usage`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/api-keys/usage" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/api-keys/usage", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/api-keys/usage",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwoord**

```json
{
  "success": true,
  "usage": {
    "limit": 300,
    "window_seconds": 60,
    "used": 37,
    "remaining": 263,
    "window_resets_at": "2026-06-09T12:01:00.000Z"
  }
}
```

Als er nog geen verzoeken zijn geregistreerd in het huidige venster, wordt het gebruik als nul gerapporteerd en bevat het antwoord een `note`-veld waarin wordt uitgelegd waarom.

---

## De sleutel roteren

Genereert een nieuwe API-sleutel en maakt de vorige in dezelfde stap ongeldig. Gebruik dit als u vermoedt dat uw sleutel is gelekt, of als onderdeel van een beleid voor regelmatige rotatie van inloggegevens.

`POST /api-keys/rotate`

> **De nieuwe sleutel wordt eenmalig getoond.** Deze wordt in dit antwoord geretourneerd en kan daarna niet meer volledig worden opgehaald — sla deze veilig op zodra je hem ontvangt. De vorige sleutel werkt niet meer zodra deze aanroep slaagt, dus update elke integratie die deze gebruikte.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/api-keys/rotate?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/api-keys/rotate", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
// Save data.api_key now — it will not be shown again.
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/api-keys/rotate",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
# Save data["api_key"] now — it will not be shown again.
```

**Antwoord**

```json
{
  "success": true,
  "api_key": "abcdEFGH1234ijkl5678MNOP9012qrst",
  "message": "API key rotated. The previous key is no longer valid. Store this key now — it will not be shown again."
}
```

---

## De sleutel intrekken

Verwijdert permanent de API-sleutel van je account. Intrekking is onmiddellijk: elk volgend verzoek dat de ingetrokken sleutel gebruikt — inclusief integraties zoals Make, Zapier of aangepaste scripts — wordt geweigerd met een `401`. Om daarna de API-toegang te herstellen, genereer je een nieuwe sleutel in je accountinstellingen terwijl je bent aangemeld bij de app.

`DELETE /api-keys/current`

> **Dit kan niet ongedaan worden gemaakt.** In tegenstelling tot rotatie, levert intrekking je geen vervangende sleutel op. Trek de sleutel alleen in als je de API-toegang wilt stoppen (bijvoorbeeld bij een gelekte sleutel die je niet direct kunt vervangen).

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/api-keys/current" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/api-keys/current", {
  method: "DELETE",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/api-keys/current",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Antwoord**

```json
{
  "success": true,
  "revoked": true,
  "message": "API key revoked. All requests using it will be rejected immediately."
}
```

Als het account geen sleutel heeft om in te trekken, is het antwoord `404`.

---

## Scoped sleutels

Een scoped sleutel is een extra API-sleutel die u aanmaakt voor één specifieke taak, met alleen de toegang die die taak nodig heeft. Het klassieke voorbeeld: u wilt een klantendashboard, een rapportagetool of een intern script aan uw account koppelen zonder een sleutel af te geven waarmee ook berichten kunnen worden verzonden, AI-agents kunnen worden gewijzigd of een telefoonnummer kan worden gekocht.

De beperking reist mee met de sleutel zelf, dus wie de sleutel ook bezit, kan alleen doen wat u toestond toen u deze aanmaakte.

**Wat u kunt beperken**

| Veld | Wat het betekent |
|---|---|
| `read_only` | `true` (de standaard) betekent dat alleen leesverzoeken zijn toegestaan. Elke aanmaak-, update- of verwijderactie wordt geweigerd. |
| `tags` | De lijst met API-secties die de sleutel mag gebruiken, geschreven met dezelfde sectienamen die u in deze documentatie en in de [API explorer](reference.md) ziet — `Analytics`, `Campaigns`, `Contacts`, `Messages`, `Appointments`, enzovoort. Een lege lijst betekent elke sectie. |
| `sub_account_ids` | Op welke beheerde accounts de sleutel mag werken. Leeg betekent alleen uw eigen account; `["*"]` betekent elk account dat u daadwerkelijk beheert. Eigendom wordt nog steeds gecontroleerd bij elk verzoek. |
| `rate_limit_per_min` | Verzoeken per minuut voor deze sleutel, geteld binnen het eigen budget, zodat deze niet het quotum van uw andere integraties kan verbruiken. Standaard ingesteld op `60`, en kan niet hoger worden ingesteld dan `300`. |

U kunt een sleutel ook een `expires_at` datum geven (ISO 8601, en deze moet in de toekomst liggen). Na dat moment stopt de sleutel vanzelf met werken. Laat dit veld leeg en de sleutel verloopt nooit totdat u deze intrekt.

> **Weigeringen zijn standaard.** Als een verzoek buiten het bereik valt van wat de sleutel toestaat, wordt het geweigerd in plaats van toegestaan: een schrijfverzoek met een alleen-lezen sleutel retourneert `403` met `error_code: "key_read_only"`, en alles buiten de toegestane secties van de sleutel retourneert `403` met `error_code: "key_scope_denied"`. Als een scoped sleutel een onverwachte `403` krijgt, valt het aangeroepen endpoint simpelweg niet binnen de scopes — verruim de sleutel of gebruik uw hoofdsleutel.

> **Alleen de accounteigenaar beheert sleutels.** Deze vier endpoints vereisen uw hoofdsleutel of een eigenaar-sessie in de app. Een scoped sleutel kan nooit sleutels vermelden, aanmaken, bewerken of intrekken — inclusief zichzelf — dus een beperkte sleutel kan nooit worden gebruikt om een ruimere sleutel aan te maken. Pogingen hiertoe retourneren `403` met `error_code: "key_scope_denied"`. Om dezelfde reden is `API Keys` geen sectie die u kunt verlenen: erom vragen retourneert `400` met `error_code: "invalid_scopes"`.

### Scoped sleutels vermelden

Retourneert de scoped sleutels van het account, nieuwste eerst (tot 200), inclusief ingetrokken sleutels zodat u kunt zien wat er is ingetrokken en wanneer. Alleen gemaskeerde voorbeelden worden geretourneerd — de waarde van een scoped sleutel wordt één keer getoond, bij het aanmaken, en is daarna nooit meer opvraagbaar.

`GET /api-keys`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/api-keys" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Antwoord**

```json
{
  "success": true,
  "api_keys": [
    {
      "id": "key_9f2c1a7b4d6e8f0a1b2c3d4e5f60718a",
      "label": "Client dashboard - Acme",
      "key_preview": "abcd...qrst",
      "scopes": {
        "read_only": true,
        "tags": ["Analytics"],
        "sub_account_ids": [],
        "rate_limit_per_min": 60
      },
      "expires_at": null,
      "last_used_at": "2026-08-20T14:03:00.000Z",
      "created_at": "2026-08-14T09:12:00.000Z",
      "revoked_at": null,
      "revoked": false
    }
  ]
}
```

### Een scoped sleutel aanmaken

Maakt een nieuwe scoped key aan en geeft de waarde ervan **één keer** terug.

`POST /api-keys`

> **De key wordt slechts één keer getoond.** Deze staat in dit antwoord en nergens anders, ooit — er is geen manier om deze achteraf opnieuw op te zoeken. Sla de key op zodra je deze ontvangt. Als je de key verliest, trek deze dan in en maak een nieuwe aan.

**Body-velden** — allemaal optioneel:

| Veld | Type | Opmerkingen |
|---|---|---|
| `label` | string | Je eigen naam voor de key, getoond in de lijst en in Instellingen. |
| `scopes` | object | De vier velden in de tabel hierboven. Laat het hele object weg voor de veilige standaardinstelling: alleen-lezen, beperkt tot `Analytics`, alleen je eigen account, 60 verzoeken per minuut. |
| `expires_at` | ISO 8601-datum | Optionele vervaldatum, moet in de toekomst liggen. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/api-keys" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Client dashboard - Acme",
    "scopes": {
      "read_only": true,
      "tags": ["Analytics"],
      "sub_account_ids": [],
      "rate_limit_per_min": 60
    }
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/api-keys", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    label: "Client dashboard - Acme",
    scopes: { read_only: true, tags: ["Analytics"] },
  }),
});
const data = await res.json();
// Save data.api_key now — it will not be shown again.
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/api-keys",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "label": "Client dashboard - Acme",
        "scopes": {"read_only": True, "tags": ["Analytics"]},
    },
)
data = res.json()
# Save data["api_key"] now — it will not be shown again.
```

**Antwoord** — `201 Created`

```json
{
  "success": true,
  "api_key": "abcdEFGH1234ijkl5678MNOP9012qrst",
  "key": {
    "id": "key_9f2c1a7b4d6e8f0a1b2c3d4e5f60718a",
    "label": "Client dashboard - Acme",
    "key_preview": "abcd...qrst",
    "scopes": {
      "read_only": true,
      "tags": ["Analytics"],
      "sub_account_ids": [],
      "rate_limit_per_min": 60
    },
    "expires_at": null,
    "revoked": false
  },
  "message": "Store this key now — it is shown once and cannot be retrieved again."
}
```

Een paar details die de moeite waard zijn om te weten wanneer je hiertegen bouwt:

- **Het weglaten van `scopes` is niet hetzelfde als het sturen van een lege `tags` lijst.** Laat `scopes` volledig weg voor de veilige standaardinstelling (alleen-lezen, alleen `Analytics`). Stuur bewust `"tags": []` en de key mag elke sectie gebruiken — dit wordt gelezen als een expliciet verzoek voor een onbeperkte key.
- **`read_only` blijft `true` tenzij je expliciet `false` verstuurt.** Een typefout of een ontbrekende vlag kan nooit per ongeluk een key produceren die schrijfrechten heeft.

### Een scoped key bijwerken

Wijzigt het label, de scopes en/of de vervaldatum van een key. Stuur een willekeurige combinatie van deze drie; als je er geen stuurt, wordt `400` geretourneerd.

`PATCH /api-keys/{id}`

De `{id}` is de `id` van de key uit de lijst (de `key_...` waarde), nooit de key zelf.

> **Scopes worden vervangen, niet samengevoegd.** Wat je ook verstuurt, wordt de volledige machtigingsset van de key. Dit is bewust: het beperken van een key kan nooit stilletjes de oude, ruimere toegang laten bestaan. Stuur altijd het volledige `scopes` object dat je wilt, niet alleen het veld dat je wijzigt.

De waarde van de key verandert nooit. Er is geen 'rotate-in-place' voor een scoped key — om er een te vernieuwen, maak je een nieuwe key aan en trek je de oude in, zodat de toegang van een inloggegeven nooit kan veranderen onder een integratie die deze nog steeds gebruikt.

**cURL**

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/api-keys/key_9f2c1a7b4d6e8f0a1b2c3d4e5f60718a" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Client dashboard - Acme (read-only)",
    "scopes": {
      "read_only": true,
      "tags": ["Analytics", "Campaigns"],
      "sub_account_ids": [],
      "rate_limit_per_min": 30
    }
  }'
```

**Antwoord**

```json
{
  "success": true,
  "key": {
    "id": "key_9f2c1a7b4d6e8f0a1b2c3d4e5f60718a",
    "label": "Client dashboard - Acme (read-only)",
    "key_preview": "abcd...qrst",
    "scopes": {
      "read_only": true,
      "tags": ["Analytics", "Campaigns"],
      "sub_account_ids": [],
      "rate_limit_per_min": 30
    },
    "expires_at": null,
    "last_used_at": "2026-08-20T14:03:00.000Z",
    "created_at": "2026-08-14T09:12:00.000Z",
    "revoked_at": null,
    "revoked": false
  }
}
```

Als er geen key met die id op je account staat, is het antwoord `404`.

### Een scoped key intrekken

Intrekking is onmiddellijk: het eerstvolgende verzoek dat die sleutel gebruikt, wordt geweigerd met een `401`. Uw hoofdsleutel en alle andere scoped keys blijven onaangetast.

`DELETE /api-keys/{id}`

De sleutel blijft in uw lijst staan gemarkeerd als `"revoked": true`, zodat u een overzicht behoudt van wat er bestond en waar het toegang toe had. Het intrekken van een sleutel die al is ingetrokken, slaagt en verandert niets.

**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/api-keys/key_9f2c1a7b4d6e8f0a1b2c3d4e5f60718a" \
  -H "X-API-Key: YOUR_API_KEY"
```

**Antwoord**

```json
{
  "success": true,
  "revoked": true,
  "id": "key_9f2c1a7b4d6e8f0a1b2c3d4e5f60718a",
  "message": "API key revoked. All requests using it will be rejected immediately."
}
```

---

## API-sleutel API-fouten

API-sleutel-endpoints retourneren de standaard fouten-envelop:

```json
{
  "success": false,
  "error": "No API key found for this account"
}
```

Op een API-sleutel-endpoint retourneert een ontbrekende of ongeldige sleutel `401` en een account zonder geregistreerde sleutel retourneert `404`. De gedeelde codes die elk endpoint kan retourneren — `400`, `403` (uw abonnement bevat geen API-toegang), `429` (snelheidslimiet) en `500` — staan vermeld met richtlijnen voor opnieuw proberen in [Fouten & Paginering](errors-and-pagination.md).

De scoped-key-eindpunten voegen een paar benoemde codes toe in het `error_code`-veld, zodat u de gevallen van elkaar kunt onderscheiden:

| `error_code` | Status | Wat er is gebeurd |
|---|---|---|
| `key_read_only` | `403` | Een alleen-lezen sleutel probeerde een schrijfactie uit te voeren. |
| `key_scope_denied` | `403` | De sleutel is niet toegestaan op dat eindpunt of dat beheerde account — of een scoped key probeerde API-sleutels te beheren, wat nooit is toegestaan. |
| `invalid_scopes` | `400` | De aangevraagde scopes bevatten de `API Keys`-sectie. Sleutels kunnen geen sleutels beheren. |
| `404` | `404` | Geen sleutel met die id op uw account. |

---

## Volgende stappen

- [Authenticatie](authentication.md) — de vier manieren om een verzoek te authenticeren en hoe key-scopes worden afgedwongen.
- [Fouten & Snelheidslimieten](errors-and-pagination.md) — statuscodes en de limiet van 300 verzoeken/min.
