
# Bouw een integratie van begin tot eind

Deze handleiding leidt je door alles wat je nodig hebt om <span data-t="appName">Your AI Connector</span> vanuit je eigen code uit te voeren, zonder ooit het dashboard te openen. Aan het einde heb je een minimale integratie gebouwd die:

1. Authenticeert met een API-sleutel
2. Maakt een AI-agent aan en configureert het gedrag van de assistent
3. Verbindt een berichtkanaal (we gebruiken WhatsApp Web als voorbeeld) en koppelt dit aan de Agent
4. Importeert contacten
5. Verstuurt en leest berichten
6. Leest analyses
7. Abonneert zich op webhooks voor real-time gebeurtenissen

Elke stap linkt naar de volledige resourcegids, zodat je in de details kunt duiken wanneer dat nodig is. Deze pagina is de kaart; de resourcegidsen zijn het terrein.

> **Voordat je begint.** API-toegang is een betaalde functie. Als je abonnement dit niet bevat, retourneert elk verzoek `403`. Zie [API-toegang](../integrations/api-access.md) om te bevestigen dat het is ingeschakeld, en [Authenticatie](authentication.md) voor alle manieren om je sleutel door te geven.

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

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

---

## Stap 1 — Haal een API-sleutel op en doe je eerste verzoek

Je API-sleutel vind je in de app onder **Instellingen → Integraties → API-sleutel** — een eigen sectie onder Integraties, los van Webhooks, die pas verschijnt zodra API-toegang is geactiveerd in het abonnement. Genereer er een, kopieer deze en sla hem veilig op (in een server-side secret store of omgevingsvariabele — nooit in browsercode). Volledige instructies staan in [API-toegang](../integrations/api-access.md).

Zodra je een sleutel hebt, kun je controleren of deze werkt door het health-eindpunt aan te roepen. Er zijn verschillende manieren om de sleutel te verzenden; de eenvoudigste is de `?apiKey=` queryparameter, maar voor echte code heeft de `X-API-Key` header de voorkeur, zodat de sleutel nooit in serverlogs of browsergeschiedenis terechtkomt.

**cURL**

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

**JavaScript**

```javascript
const BASE = "https://api.youraiconnector.com/v1";
const headers = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" };

const res = await fetch(`${BASE}/health`, { headers });
const data = await res.json();
console.log(data); // { "success": true, ... }
```

**Python**

```python
import requests

BASE = "https://api.youraiconnector.com/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}

res = requests.get(f"{BASE}/health", headers=HEADERS)
print(res.json())  # { "success": true, ... }
```

Elk succesvol antwoord is verpakt in dezelfde envelop — een `success: true` veld plus de resultaatgegevens. Fouten retourneren `success: false` met een `error` bericht en een `error_code`. Zie [Fouten & Paginering](errors-and-pagination.md) voor de volledige lijst en voor hoe lijsteindpunten pagineren met `?limit` en `?cursor`.

> **Snelheidslimiet.** Geauthenticeerde verzoeken zijn beperkt tot **300 per minuut** (met een ruimer plafond van 1.200 per minuut per account). Overschrijding resulteert in `429`; wacht even en probeer het opnieuw.

---

## Stap 2 — Een AI-agent aanmaken

Een **AI-agent** is de entiteit die het gedrag van je assistent bevat: de instructies, het doel, de actieve uren en hoe deze met contacten communiceert. Dit is degene die een gesprek beantwoordt, dus dit is het logische eerste punt om aan te maken.

Maak er een aan met `POST /agents`. `name` is het enige veld dat je vooraf hoeft mee te sturen; al het andere kan worden ingesteld met de onderstaande bot-config-aanroep.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Inbound WhatsApp Leads",
    "language": "en"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/agents`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "Inbound WhatsApp Leads",
    language: "en",
  }),
});
const { agent_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/agents",
    headers=HEADERS,
    json={"name": "Inbound WhatsApp Leads", "language": "en"},
)
agent_id = res.json()["agent_id"]
```

Een succesvolle aanmaak retourneert `201` met het nieuwe ID:

```json
{
  "success": true,
  "agent_id": "abc123agent"
}
```

**Sla de `agent_id` op** — je zult hiernaar verwijzen bij het routeren van kanalen.

### De assistent configureren

`PUT /agents/{agentId}/bot-config` stelt het gedrag van de assistent in. Het *voegt* de velden die je verstuurt *samen* met de bestaande configuratie, dus alles wat je weglaat blijft behouden:

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/abc123agent/bot-config" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instructions": "Greet warmly, answer questions about our services, and offer to book a call.",
    "goal": "Book a discovery call.",
    "ai_speed": "balanced"
  }'
```

Stel actieve uren in met `PUT /agents/{agentId}/active-hours` zodat de assistent alleen tijdens kantooruren antwoordt; buiten die vensters antwoordt de assistent niet automatisch.

> **Kennisbank.** Om de assistent te laten antwoorden op basis van je eigen inhoud, kun je veelgestelde vragen (FAQ's) toevoegen. Zie de [FAQ-handleiding](faqs.md).

> **Legacy: klassieke campagnes.** Accounts die nog steeds een **Campagnes**-pagina hebben, creëren hetzelfde assistentgedrag op een campagne (`POST /campaigns` met een `type` en een `bot` object, daarna `PUT /campaigns/{campaignId}/bot-config`). De volledige lijst met campagnevelden en levenscycluscontroles staat in de [Campagne-handleiding](campaigns.md). Als je iets nieuws bouwt, maak dan een Agent aan.

---

## Stap 3 — Een kanaal verbinden

Een Agent heeft een manier nodig om berichten te verzenden en te ontvangen. Zeven verbindingsstromen kunnen worden aangestuurd via de API: WhatsApp Business, WhatsApp Web, Instagram en Messenger samen (één gedeelde Meta-stroom), persoonlijke Instagram-accounts, Telegram, LINE en Viber. De overige kanalen — waaronder sms, e-mail, de chatwidget en aangepaste kanalen — worden ingesteld in het dashboard in plaats van via REST. Zodra ze zijn verbonden, werken de eindpunten voor berichten, contacten en routering op precies dezelfde manier. `GET /channels` is de actuele bron van waarheid voor wat er voor een bepaald account daadwerkelijk is verbonden:

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

De volledige set verbindings-/verbindingsverbrekingsstromen voor elk kanaal staat gedocumenteerd in de [Kanaalgids](channels.md). Hieronder doorlopen we **WhatsApp Web** van begin tot eind, omdat dit het meest interessante patroon laat zien: een QR-code koppelingsstroom die je wrapper moet renderen en pollen.

### Uitgewerkt voorbeeld: WhatsApp Web koppelen via QR-code

Het koppelen van WhatsApp Web is een dans van drie aanroepen — **starten**, **de QR ophalen**, **pollen tot verbonden**.

**1. Start de koppelingssessie.** Geef het nummer dat je wilt verbinden door in E.164-formaat.

```bash
curl -X POST "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phone_number": "+15551230000" }'
```

```javascript
await fetch(`${BASE}/channels/whatsapp-web/connections`, {
  method: "POST",
  headers,
  body: JSON.stringify({ phone_number: "+15551230000" }),
});
```

```python
requests.post(
    f"{BASE}/channels/whatsapp-web/connections",
    headers=HEADERS,
    json={"phone_number": "+15551230000"},
)
```

**2. Haal de QR-code op en toon deze aan de gebruiker.** Pol deze elke 10–15 seconden. Het antwoord bevat de onbewerkte `qr_code`-payload (render deze zelf als een QR-afbeelding) en een `qr_data_url` die klaar is om weer te geven.

```bash
curl "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000/qr?apiKey=YOUR_API_KEY"
```

```json
{
  "success": true,
  "phone_number": "+15551230000",
  "status": "qr_pending",
  "qr_code": "2@abc...",
  "qr_data_url": "data:image/png;base64,iVBORw0KGgo..."
}
```

Plaats in de UI van je wrapper de `qr_data_url` direct in een `<img src="...">` en vraag de gebruiker om deze te scannen via **WhatsApp → Gekoppelde apparaten** op hun telefoon. Als de QR verloopt (een `410`-antwoord), begin dan opnieuw bij stap 1 om een nieuwe te krijgen.

**3. Pol de status totdat deze verbonden is.** Nadat de gebruiker heeft gescand, blijf je het statuseindpunt pollen totdat het `connected` rapporteert (de service kan ook `open` rapporteren). Behandel `disconnected` en `not_initialized` als terminale fouten.

```python
import time

PHONE = "+15551230000"
while True:
    res = requests.get(
        f"{BASE}/channels/whatsapp-web/connections/{PHONE}/status",
        headers=HEADERS,
    )
    status = res.json()["status"]
    if status in ("connected", "open"):
        print("Connected!")
        break
    if status in ("disconnected", "not_initialized"):
        raise RuntimeError(f"Pairing failed: {status}")
    time.sleep(5)
```

```javascript
async function waitForConnection(phone) {
  while (true) {
    const res = await fetch(
      `${BASE}/channels/whatsapp-web/connections/${encodeURIComponent(phone)}/status`,
      { headers }
    );
    const { status } = await res.json();
    if (status === "connected" || status === "open") return;
    if (status === "disconnected" || status === "not_initialized") {
      throw new Error(`Pairing failed: ${status}`);
    }
    await new Promise((r) => setTimeout(r, 5000));
  }
}
```

> **Let op.** Voor elk verbonden WhatsApp Web-nummer geldt een terugkerende maandelijkse onderhoudskost totdat je de verbinding verbreekt (`DELETE /channels/whatsapp-web/connections/{phoneNumber}`).

### Het kanaal routeren naar je Agent

Het verbinden van een kanaal zorgt ervoor dat het werkt; door het te routeren vertel je het platform *welke AI-agent* nieuwe inkomende gesprekken op dat kanaal moet beantwoorden. Stel het standaard-toegangspunt (Entry Point) voor het kanaal in en benoem de Agent die je in stap 2 hebt aangemaakt:

```bash
curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "whatsapp_web", "agent_id": "abc123agent" }'
```

Herhaal de aanroep één keer per kanaal — één kanaalstandaard per kanaal. Om een kanaal achter te laten zonder dat een Agent antwoordt, roep je `DELETE /entry-points/channel-defaults?channel=whatsapp_web` aan; om te controleren of de Entry Points-ladder live is voor het account, roep je `GET /entry-points/routing-status` aan. De oudere `POST /channels/campaign`-map is alleen behouden voor terugdraai-acties en wordt niet langer geraadpleegd voor inkomende routering. Zie de [Kanaalhandleiding](channels.md) voor de andere kanaaltypen en voor de WhatsApp Business OAuth-stroom.

---

## Stap 4 — Importeer je contacten

Zodra een kanaal live is, kun je de mensen laden die je wilt bereiken. Het import-eindpunt verwerkt maximaal **500 records per aanroep**. Elk record heeft een `phone_number` in internationaal formaat nodig; al het overige is optioneel. Records met ongeldige nummers, niet-ondersteunde kanalen of nummers die al bestaan worden overgeslagen — en elke overgeslagen record wordt gerapporteerd met de index en de reden, zodat je alleen de mislukte records opnieuw kunt proberen.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts/import" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee" },
      { "phone_number": "+12025551235", "first_name": "Bob" }
    ],
    "defaultChannel": "whatsapp_web"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/contacts/import`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    contacts: [
      { phone_number: "+12025551234", first_name: "Ann", last_name: "Lee" },
      { phone_number: "+12025551235", first_name: "Bob" },
    ],
    defaultChannel: "whatsapp_web",
  }),
});
const result = await res.json();
console.log(`${result.imported} imported, ${result.skipped.length} skipped`);
```

**Python**

```python
res = requests.post(
    f"{BASE}/contacts/import",
    headers=HEADERS,
    json={
        "contacts": [
            {"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee"},
            {"phone_number": "+12025551235", "first_name": "Bob"},
        ],
        "defaultChannel": "whatsapp_web",
    },
)
result = res.json()
print(f"{result['imported']} imported, {len(result['skipped'])} skipped")
```

Het antwoord vertelt je precies wat er is gebeurd:

```json
{
  "success": true,
  "imported": 2,
  "contact_ids": ["contactId1", "contactId2"],
  "skipped": []
}
```

Voor het aanmaken per stuk, opzoeken, lijsten, tags en aangepaste velden, zie de [Gids voor contacten](contacts.md).

---

## Stap 5 — Berichten verzenden en lezen

### Een bericht verzenden

De eenvoudigste manier van verzenden is **kanaalonafhankelijk**: geef de identiteit van de contactpersoon en de berichtinhoud op, en het platform bezorgt het via het kanaal waarop de contactpersoon zich bevindt. Je kunt targeten op `contact_id`, of op `channel` plus het bijbehorende identiteitsveld (`phone_number` voor WhatsApp/WhatsApp Web/SMS, `instagram_id` voor Instagram, enzovoort).

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/contacts/send" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "whatsapp_web",
    "phone_number": "+12025551234",
    "body": "Hi Ann! Thanks for reaching out."
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/contacts/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    channel: "whatsapp_web",
    phone_number: "+12025551234",
    body: "Hi Ann! Thanks for reaching out.",
  }),
});
const { message_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/contacts/send",
    headers=HEADERS,
    json={
        "channel": "whatsapp_web",
        "phone_number": "+12025551234",
        "body": "Hi Ann! Thanks for reaching out.",
    },
)
message_id = res.json()["message_id"]
```

Bezorging is **asynchroon** — een `201` betekent dat het bericht is *geaccepteerd en in de wachtrij geplaatst*, nog niet bezorgd. (Contacten met 'niet storen' of de privacymodus ingeschakeld worden geweigerd met een `422`.)

```json
{
  "success": true,
  "message_id": "aB3dE5fG7hI9jK1lM2nO",
  "contact_id": "contact123",
  "channel": "whatsapp_web"
}
```

### Een gesprek lezen

Om berichten terug te lezen, vermeld je ze per contactpersoon, nieuwste eerst, met cursor-paginering. Geef de `next_cursor` van het ene antwoord door als de `cursor` van het volgende om door de geschiedenis terug te bladeren.

```bash
curl "https://api.youraiconnector.com/v1/contacts/contact123/messages?limit=50&apiKey=YOUR_API_KEY"
```

```python
res = requests.get(
    f"{BASE}/contacts/contact123/messages",
    headers=HEADERS,
    params={"limit": 50},
)
page = res.json()
for msg in page["messages"]:
    print(msg)
next_cursor = page["next_cursor"]  # pass back as ?cursor= for the next page
```

Je kunt ook filteren op inhoudstype (`?filter=text|media|tool_use`) of richting (`?direction=inbound|outbound`). De [Gids voor berichten](messages.md) behandelt mediabijlagen, het markeren van berichten als gelezen en de berichtweergaven per sessie.

> **Poll niet voor antwoorden.** Berichten op een timer opvragen werkt wel, maar het verspilt verzoeken en zorgt voor vertraging. Gebruik voor inkomende berichten webhooks — dat is Stap 7.

---

## Stap 6 — Analytics lezen

Zodra er berichten worden verstuurd, geeft het analytics-overzicht geaggregeerde totalen over een datumbereik: verzonden, afgeleverd, gelezen, beantwoord, geboekt, aangemaakte contacten en verbruikte/opgewaardeerde credits. Je krijgt zowel totalen voor het bereik als een reeks per dag met nullen opgevuld — perfect voor een dashboardgrafiek. Je kunt dit optioneel beperken tot één campagne met `campaign_id` (de onderstaande voorbeelden gebruiken een tijdelijke campagne-ID, `abc123campaign`); laat de parameter weg voor totalen op accountniveau.

```bash
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&campaign_id=abc123campaign&apiKey=YOUR_API_KEY"
```

```javascript
const params = new URLSearchParams({
  from: "2026-05-01",
  to: "2026-05-31",
  campaign_id: "abc123campaign",
});
const res = await fetch(`${BASE}/analytics/summary?${params}`, { headers });
const { totals, by_date } = await res.json();
```

```python
res = requests.get(
    f"{BASE}/analytics/summary",
    headers=HEADERS,
    params={"from": "2026-05-01", "to": "2026-05-31", "campaign_id": "abc123campaign"},
)
data = res.json()
totals = data["totals"]
by_date = data["by_date"]
```

Het bereik staat standaard op de laatste 30 dagen en is gemaximeerd op 366. Voor gebruiksgegevens per credit en uitsplitsingen van AI-kosten, zie de [Analytics-handleiding](analytics.md).

---

## Stap 7 — Abonneer je op webhooks voor realtime gebeurtenissen

Polling is prima voor een snel script, maar een echte integratie moet **push-gebaseerd** zijn. Met webhooks kan het platform *jouw* server aanroepen op het moment dat er iets gebeurt — een nieuw contact, een antwoord, een geboekte afspraak, een afgesloten chat.

Ontdek eerst de exacte namen van de gebeurtenissen waarop je je kunt abonneren:

```bash
curl "https://api.youraiconnector.com/v1/webhooks/events?apiKey=YOUR_API_KEY"
```

```json
{
  "success": true,
  "events": [
    "Contact Created",
    "Human Alerted",
    "Appointment Booked",
    "Replies",
    "New Message",
    "Chat Concluded",
    "Task Created",
    "Daily Summary Created"
  ]
}
```

Maak vervolgens een abonnement aan dat verwijst naar een HTTPS-URL op jouw server. Gebruik de exacte gebeurtenis-strings uit de bovenstaande aanroep.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/webhooks" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "name": "Lead updates hook"
  }'
```

**JavaScript**

```javascript
const res = await fetch(`${BASE}/webhooks`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    url: "https://hooks.example.com/incoming",
    subscribed_to: ["Contact Created", "Replies"],
    name: "Lead updates hook",
  }),
});
const { webhook_id } = await res.json();
```

**Python**

```python
res = requests.post(
    f"{BASE}/webhooks",
    headers=HEADERS,
    json={
        "url": "https://hooks.example.com/incoming",
        "subscribed_to": ["Contact Created", "Replies"],
        "name": "Lead updates hook",
    },
)
webhook_id = res.json()["webhook_id"]
```

```json
{
  "success": true,
  "webhook_id": "1",
  "webhook": {
    "id": "1",
    "name": "Lead updates hook",
    "url": "https://hooks.example.com/incoming",
    "subscribed_to": ["Contact Created", "Replies"],
    "subscribed_to_tags": [],
    "created_at": "2026-06-09T12:00:00.000Z"
  }
}
```

De URL moet HTTPS gebruiken en publiekelijk bereikbaar zijn. Vanaf nu ontvangt jouw server een POST voor elke geabonneerde gebeurtenis. Je kunt een testbericht sturen, de status van een abonnement controleren en een abonnement opnieuw inschakelen dat na herhaalde fouten automatisch was uitgeschakeld — zie de [Webhooks-handleiding](webhooks.md) en de [Webhooks](../integrations/webhooks.md)-pagina op integratieniveau voor payload-structuren en verificatie.

---

## Alles op een rij

Hier is het volledige proces in één oogopslag:

| Stap | Doel | Belangrijkste aanroep |
|---|---|---|
| 1 | Authenticeren | `GET /health` |
| 2 | Assistent aanmaken + afstemmen | `POST /agents`, `PUT /agents/{id}/bot-config`, `PUT /agents/{id}/active-hours` |
| 3 | Kanaal verbinden en routeren | `POST /channels/whatsapp-web/connections` → QR scannen + status → `PUT /entry-points/channel-defaults` |
| 4 | Contacten laden | `POST /contacts/import` |
| 5 | Verzenden & lezen | `POST /contacts/send`, `GET /contacts/{id}/messages` |
| 6 | Meten | `GET /analytics/summary` |
| 7 | Realtime reageren | `POST /webhooks` |

Een minimale wrapper bestaat uit slechts deze zeven aanroepen die in je eigen UI zijn verwerkt. Voeg vanaf daar de per-resource handleidingen toe naarmate je meer nodig hebt:

- [Campagnes](campaigns.md) · [Contacten](contacts.md) · [Veelgestelde vragen](faqs.md) · [Berichten](messages.md) · [Afspraken](appointments.md)
- [Kanalen](channels.md) · [Sjablonen](templates.md) · [Analytics](analytics.md) · [Webhooks](webhooks.md) · [API-sleutels](api-keys.md)
- Nieuw hier? [Aan de slag](getting-started.md) · [Authenticatie](authentication.md) · [Fouten & Paginering](errors-and-pagination.md)

Stuck on something this guide does not cover? Email [<span data-t="supportEmail">hi@youraiconnector.com</span>](mailto:hi@youraiconnector.com).
