> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Een toolintegratie bouwen (API)

> Laat je agent tijdens een gesprek je API's aanroepen — zoek in een database, maak een ticket aan, zoek een bestelling op.

Een **toolintegratie** is een herbruikbaar HTTP-eindpunt dat een agent
tijdens een gesprek kan aanroepen. Je geeft ThunderPhone een JSON-schemabeschrijving
van de tool plus een eindpunt-URL; de agent beslist op basis van het gesprek
wanneer deze moet worden aangeroepen, en ThunderPhone doet het uitgaande HTTP-verzoek
vanaf zijn servers en retourneert het antwoord aan de agent.

<Note>
  Het dashboard dekt de meeste toolbehoeften zonder deze API: **Verbindingen
  → Apps** verbindt Slack, HubSpot, Salesforce, Google Calendar,
  Google Sheets en Cal.com met enkele OAuth-klikken; **Verbindingen →
  API's** maakt van elke HTTP-API een agentactie (plak een cURL-opdracht
  en een AI-wizard maakt een opzet voor de tool, met een ingebouwde Testverzoek-functie); en
  **Verbindingen → MCP** voegt MCP-servers toe. Zie
  [Verbindingen](/nl/guides/concepts). Deze handleiding behandelt de onderliggende
  API achter de API-interface.
</Note>

Deze handleiding neemt je stap voor stap mee bij het bouwen van een tool voor het opzoeken van weergegevens.

## Anatomie van een tool

Twee onderdelen:

1. **Het schema** — een functiedefinitie in OpenAI-stijl
   (`{type: "function", function: {name, description, parameters}}`)
   die de LLM vertelt wat de tool doet en welke argumenten deze accepteert.
2. **Het eindpunt** — de URL die de servers van ThunderPhone aanroepen wanneer de
   LLM beslist de tool te gebruiken. Het verzoek is een JSON-POST met de
   door de LLM gekozen argumenten als hoofdtekst.

## 1. Kies een opslagstrategie

<CardGroup cols={2}>
  <Card title="Inline bij de agent" icon="paperclip">
    Koppel een eenmalige tool aan de `tools`-array van de agent. Eenvoudig, maar
    niet herbruikbaar.
  </Card>

  <Card title="Opgeslagen integratie" icon="plug">
    Sla de tool op als een herbruikbare [integratie](/api-reference/integrations)
    en koppel deze aan meerdere agents. Aanbevolen voor alles wat meer
    dan één keer wordt gebruikt.
  </Card>
</CardGroup>

Deze handleiding gebruikt de route met opgeslagen integraties.

## 2. Maak de integratie

```bash theme={null}
curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'
```

Sla de geretourneerde `id` (een UUID) op.

<Tip>
  Besteed serieuze aandacht aan de `description` van de tool en van elke
  parameter. De LLM gebruikt deze strings tijdens runtime om te beslissen
  of en hoe de tool moet worden aangeroepen. Vage beschrijvingen → vage
  toolaanroepen.
</Tip>

## 3. Test het eindpunt in de sandbox

Voordat je de integratie aan een agent koppelt, stuur je een ondertekend verzoek
vanaf de servers van ThunderPhone om de connectiviteit te bevestigen:

```bash theme={null}
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
```

```json Response theme={null}
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}
```

Deze test versterkt ook de SSRF-beveiliging van ThunderPhone — verzoeken naar
localhost of privé-IP-bereiken retourneren `400 code=url_not_allowed`.

## 4. Koppel de integratie aan een spraakagent

Koppel via `integration_ids` wanneer je een spraakagent maakt of bijwerkt:

```bash theme={null}
curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'
```

Je kunt meerdere integraties aan één spraakagent koppelen. De prompt van de spraakagent kan
ernaar verwijzen op naam — "gebruik `get_weather` wanneer de beller
naar de weersomstandigheden vraagt" — of ze impliciet herkennen aan de
schemabeschrijvingen.

## 5. Implementeer het endpoint

Wanneer de spraakagent de tool aanroept, stuurt ThunderPhone een ondertekende POST naar
je `endpoint_url`:

```
POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}
```

Je server antwoordt met JSON dat wordt teruggestuurd naar de LLM:

```json theme={null}
{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}
```

De LLM verwerkt dat antwoord en spreekt een begrijpelijke samenvatting uit voor de
beller.

<Warning>
  De handtekening wordt berekend over de onbewerkte aanvraagbody met dezelfde
  `secret` als je webhook-endpoint. **Verifieer deze** — tool-endpoints
  zijn toegankelijk via internet en onderhevig aan dezelfde risico's op spoofing als
  webhooks. Zie
  [Webhookhandtekeningen verifiëren](/nl/guides/verify-webhook-signatures).
</Warning>

## 6. Test de volledige stroom

Start een [micsessie](/api-reference/mic-sessions) met de spraakagent
en stel de vraag die je tool afhandelt ("Wat is het weer in
94110?"). Het transcript van het gesprek toont de volledige heen-en-terugcommunicatie:

```json theme={null}
{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}
```

Je kunt dit ophalen via
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript);
de onbewerkte eventstream (met timing per item en audio-offsets) vind je op
[`GET /v1/calls/{call_id}/history`](/api-reference/calls#get-history).

## Veelvoorkomende valkuilen

<AccordionGroup>
  <Accordion title="Spraakagent roept de tool nooit aan">
    De LLM beslist op basis van de beschrijving van de tool. Als de vraag van de beller
    niet overeenkomt met de beschrijving, roept het model
    de tool niet aan. Maak de beschrijving specifieker (voeg veelvoorkomende synoniemen en
    formuleringen toe) of vermeld dit expliciet in de prompt van de spraakagent ("Wanneer de
    beller naar het weer vraagt, gebruik dan `get_weather`.").
  </Accordion>

  <Accordion title="Tool retourneert te veel gegevens">
    Antwoorden groter dan 6 kB worden afgekapt in de transcriptvoorvertoning. Retourneer
    alleen de velden die de LLM nodig heeft — niet je volledige gegevensrecord.
  </Accordion>

  <Accordion title="Time-outs">
    Tool-endpoints hebben standaard een time-out van 10 seconden. Als je meer tijd nodig hebt,
    verwerk dit dan asynchroon: retourneer `{"status": "pending", "request_id": "..."}`
    en toon het resultaat via een afzonderlijke toolaanroep.
  </Accordion>

  <Accordion title="Versiebeheer">
    Elke `PATCH` van een integratie maakt een nieuwe revisie. Controleer
    [`GET /v1/integrations/{id}/versions`](/api-reference/integrations#version-history)
    om te zien wie wat heeft gewijzigd. Als je het schema van een tool beschadigt, kun je
    handmatig terugdraaien door een oudere snapshot opnieuw met PATCH toe te passen.
  </Accordion>
</AccordionGroup>

***

## Volgende stappen

<CardGroup cols={2}>
  <Card title="Integratiereferentie" icon="plug" href="/api-reference/integrations">
    CRUD, overdracht, versiegeschiedenis.
  </Card>

  <Card title="Specificatie voor functietools" icon="screwdriver-wrench" href="/nl/tools/overview">
    Volledige JSON-schema-grammatica en het contract voor ondertekende endpoints.
  </Card>

  <Card title="Handtekeningen verifiëren" icon="shield-check" href="/nl/guides/verify-webhook-signatures">
    Pas het patroon voor webhookhandtekeningen toe op tool-endpoints.
  </Card>

  <Card title="API voor transcript + geschiedenis" icon="phone" href="/api-reference/calls">
    Inspecteer de volledige retourgang van een toolaanroep.
  </Card>
</CardGroup>
