API-referentie
Elk endpoint van de REST-API, met wat je meestuurt, wat je terugkrijgt en welk bereik je sleutel nodig heeft.
Alle paden zijn relatief ten opzichte van https://chatterlab.ai/api/v1. Authenticatie, fouten, limieten en paginering staan één keer beschreven, in het overzicht van de API.
| Methode en pad | Bereik | Wat het doet |
|---|---|---|
GET /workspace | read | De sleutel, en het abonnement en het verbruik van de werkruimte |
GET /models | read | De modellen die een agent kan gebruiken |
GET /setup-guide | read | Hoe je een agent inricht voor waar hij voor dient |
GET /agents | read | De lijst van agents |
POST /agents | manage | Een agent aanmaken |
GET /agents/{id} | read | Eén agent |
PATCH /agents/{id} | manage | Een agent wijzigen |
DELETE /agents/{id} | manage | Een agent verwijderen, met alles wat erbij hoort |
PUT /agents/{id}/branding/{image} | manage | Het logo of de afbeelding op de launcher instellen vanaf een adres |
DELETE /agents/{id}/branding/{image} | manage | Het logo of de afbeelding op de launcher weghalen |
GET /agents/{id}/embed | read | De installatiesnippets |
GET /agents/{id}/sources | read | De lijst van bronnen |
POST /agents/{id}/sources | manage | Een website, een bestand, een tekst of een vraag-antwoordpaar toevoegen |
GET /agents/{id}/sources/{sourceId} | read | Eén bron, met de inhoud |
DELETE /agents/{id}/sources/{sourceId} | manage | Een bron verwijderen |
GET /agents/{id}/crawl | read | De voortgang van de laatste crawl |
DELETE /agents/{id}/crawl | manage | De laatste crawl stoppen |
POST /agents/{id}/retrain | manage | Elke bron opnieuw laten lezen |
POST /agents/{id}/chat | chat | Een vraag stellen |
GET /agents/{id}/conversations | read | De lijst van gesprekken |
GET /agents/{id}/conversations/{conversationId} | read | Eén gesprek met de berichten |
DELETE /agents/{id}/conversations/{conversationId} | manage | Eén gesprek wissen |
GET /agents/{id}/conversations/export | read | Een link naar een PDF van de gesprekken in een periode |
GET /agents/{id}/visitor-files/{fileId} | read | Een bestand dat een bezoeker stuurde, met de tekst die eruit is gelezen |
DELETE /agents/{id}/visitor-files/{fileId} | manage | Een bestand dat een bezoeker stuurde wissen |
GET /agents/{id}/leads | read | De contactgegevens die bezoekers achterlieten |
GET /agents/{id}/leads/{leadId} | read | Eén lead |
DELETE /agents/{id}/leads/{leadId} | manage | Eén lead wissen |
GET /agents/{id}/tickets | read | De lijst van tickets |
GET /agents/{id}/tickets/{ticketId} | read | Eén ticket met wat er na de vraag kwam |
PATCH /agents/{id}/tickets/{ticketId} | manage | De status van een ticket wijzigen |
POST /agents/{id}/tickets/{ticketId}/notes | manage | Een notitie aan een ticket toevoegen |
GET /agents/{id}/client | read | De klant voor wie een agent draait |
PUT /agents/{id}/client | manage | Een klant vastleggen, of wijzigen wat is vastgelegd |
DELETE /agents/{id}/client | manage | De klant van een agent halen |
POST /agents/{id}/client/report-link | manage | De klant een nieuwe rapportlink geven |
POST /agents/{id}/messages/{messageId}/correction | manage | Eén antwoord corrigeren |
GET /agents/{id}/analytics | read | Cijfers over een periode |
Werkruimte en modellen
GET /workspace geeft key terug (id, name, prefix, scope, agentId) en workspace: de naam, het abonnement, de standaardtaal, het aantal agents en de limiet, de credits die deze maand zijn gebruikt, de inbegrepen credits, de gekochte credits, overage (altijd false: overschrijding bestaat niet meer, extra credits komen uit pakketten), en de opslag per agent. Een sleutel die aan één agent is gekoppeld, krijgt alleen key.
GET /models geeft de modellen terug met hun id, provider, creditsPerAnswer en contextSize. available zegt of het abonnement van de werkruimte het model kan gebruiken. Een sleutel die aan één agent is gekoppeld, krijgt available alleen als zijn bereik manage is.
Agents
GET /setup-guide is waar je begint voor je een agent aanmaakt. Het geeft presets terug, één per toepassing: het purpose, instructions en een welcomeMessage om aan te passen, met elk deel [tussen haken] voor jou om in te vullen, de instellingen voor temperature en retrieval die erbij passen, features (of booking en visitorFiles recommended, optional of not_needed zijn, en waarom), de sources om te verzamelen, tien testQuestions waarvan de agent de laatste twee hoort te weigeren, en de checks waar de antwoorden aan moeten voldoen. ?useCase=support geeft alleen die ene; een toepassing met een hoog risico wordt geweigerd met high_risk_use_case, en elke andere waarde met invalid_request. Daarbij komt plan: het id, agents (count, limit en left, null waar er geen limiet is), storagePerAgentBytes, visitorFiles, of bezoekers op dit abonnement bestanden mogen sturen, en brandingRemoval. Een sleutel die aan één agent is gekoppeld, krijgt alleen presets. De presets zijn in het Engels geschreven: schrijf de instructies van de agent zelf in de taal van zijn bezoekers.
POST /agents
| Veld | ||
|---|---|---|
name | verplicht | 1 tot 80 tekens |
useCase | verplicht | general, support, sales of docs. De waarden met een hoog risico, hr_recruitment, credit_scoring en healthcare, worden geweigerd met high_risk_use_case. Waarom |
description | hoogstens 300 tekens | |
instructions | hoogstens 20.000 tekens | |
welcomeMessage | hoogstens 300 tekens | |
language | en, nl, fr, de of es | |
website | Een adres dat meteen wordt gecrawld, als eerste bron. Het antwoord bevat dan ook crawl (het id en de status), of crawlError als de crawl niet kon starten. De agent wordt in beide gevallen aangemaakt. |
curl -X POST https://chatterlab.ai/api/v1/agents \
-H "Authorization: Bearer cl_your_key" \
-H "Content-Type: application/json" \
-d '{"name":"Support","useCase":"support","language":"en","website":"https://example.com"}'
Het agent-object heeft id, name, description, useCase (waarvoor hij bij het aanmaken werd opgegeven, null voor sommige agents van voor 23 september 2026), instructions, welcomeMessage, language, languages (de talen die de widget mag spreken, language eerst: in de andere volgt hij de browser van een bezoeker), model, temperature (0 tot 1), retrieval (topK 1 tot 10, minSimilarity 0 tot 1), allowedOrigins, calendlyUrl, attachmentsEnabled, branding, proactive (de begroeting en het tweede bericht: greeting, nudge, pages, paths en mobile, met elke standaardwaarde ingevuld), leadCapture (het contactformulier: enabled, fields, timing, skippable, afterQuestions, afterWeakAnswer, button, intro, thanks, privacyUrl en marketing, met elke standaardwaarde ingevuld), tickets (de tickets in de chat: enabled, answerTime, leeg voor de standaardzin, en privacyUrl), status (active of paused), lastTrainedAt, createdAt en updatedAt.
PATCH /agents/{id} accepteert name, description, instructions, welcomeMessage, language, languages, model, temperature, retrieval, allowedOrigins, calendlyUrl, attachmentsEnabled, branding, proactive, leadCapture en tickets, in elke combinatie. Alleen wat je meestuurt, verandert, ook binnen branding, proactive, leadCapture en tickets. branding.translations geeft het welkomstbericht, messagePlaceholder en launcherLabel een versie per taal van de widget, zoals { "fr": { "welcomeMessage": "Bonjour !" } }, en een lege tekst verwijdert die versie. languages vervangt de lijst, en language blijft er altijd in staan. allowedOrigins vervangt de hele lijst, en een lege lijst zet de agent open voor elke site. Een regel zoals https://*.example.com dekt elk subdomein, en een regel over een publiek achtervoegsel, zoals *.com, wordt geweigerd met invalid_request. Een model dat niet in het abonnement zit, wordt geweigerd met model_not_allowed. Met attachmentsEnabled kunnen bezoekers bestanden sturen in de widget. Een leadCapture die aanstaat, heeft een privacyUrl nodig die met https:// begint, en een e-mailadres of telefoonnummer bij zijn fields; zonder die wordt hij geweigerd met invalid_request. tickets die aanstaan, hebben een privacyUrl nodig die met https:// begint; zonder die worden ze geweigerd met invalid_request. Wie elke lead of elk ticket gemaild krijgt, wijzig je alleen in het dashboard.
DELETE /agents/{id} verwijdert de agent met zijn bronnen, gesprekken, bestanden en tickets. Dat kan niet ongedaan worden gemaakt.
PUT /agents/{id}/branding/logo stelt het logo in de kop van het chatvenster in vanaf een afbeelding op een adres, { "url": "https://..." }, en PUT /agents/{id}/branding/icon doet hetzelfde voor de afbeelding op de launcher. De afbeelding moet een PNG, JPEG, GIF of WebP zijn van hoogstens 512 KB. Onderweg wordt niets bijgesneden of verkleind, dus een grotere afbeelding wordt geweigerd met file_too_large: upload ze dan in het dashboard, waar ze wordt bijgesneden. Een SVG wordt alleen als upload in het dashboard aangenomen. DELETE op hetzelfde adres haalt de afbeelding weg. Elk antwoordt met de agent.
GET /agents/{id}/embed geeft script en iframe terug, de twee snippets van de pagina Implementeren, en allowedOrigins.
Bronnen
POST /agents/{id}/sources accepteert een van vier body's. Het veld type bepaalt welke:
{ "type": "website", "url": "https://example.com", "mode": "links", "excludePaths": ["/blog"] }
{ "type": "text", "title": "Delivery times", "content": "We deliver within..." }
{ "type": "qa", "question": "Can I still cancel?", "answer": "Yes, until the order ships." }
{ "type": "file", "url": "https://example.com/downloads/manual.pdf", "name": "Manual" }
mode is links (links op dezelfde site volgen, de standaard), sitemap of single. De limieten zijn die van het dashboard. Zie Websites, Bestanden en Tekst en vraag & antwoord.
Een bestand wordt opgehaald van zijn adres, want hier is geen browser om het te uploaden. Het moet een PDF, een Word-document (.docx), Markdown of platte tekst zijn, en dat wordt uit het bestand zelf afgeleid, niet uit de naam. Het moet binnen 20 seconden binnen zijn, en mag zo groot zijn als de opslag per agent van het abonnement, hoogstens 50 MB. name is optioneel; zonder is het het laatste deel van het adres. Een bestand dat alleen op iemands computer staat, upload je onder Bronnen in het dashboard. Een geweigerd bestand zegt waarom: unsupported_file_type, storage_limit_reached, file_too_large, unsafe_url of fetch_failed.
Een tekst, een vraag-antwoordpaar of een bestand komt terug als een bron met de status pending. Blijf GET .../sources/{sourceId} opvragen tot de status ready of failed is. Dat duurt meestal een paar seconden, en voor een lang bestand een minuut of meer. Een website komt terug als een crawl: volg die met GET /agents/{id}/crawl.
Het bron-object heeft id, type (website, file, text of qa), name, url, status, error, turnedAway (login_page of too_little_content voor een pagina die een latere crawl afkeurde, anders null), sizeBytes, chunkCount, createdAt en processedAt. Eén opgevraagde bron heeft ook content. De lijst laat dat weg, om pagina's klein te houden. Bij een mislukte bron is error een van file_unreadable, no_content, too_large, never_finished, temporary en file_too_complex, de laatste voor een bestand dat meer geheugen of tijd kostte om te lezen dan een bron mag gebruiken.
Het crawl-object heeft id, status (queued, running, completed, failed of cancelled), processed, discovered, pending, failed en stopReason. Dat laatste is ingevuld als de crawl stopte voordat de hele site was gedaan, bijvoorbeeld bij de opslaglimiet.
DELETE /agents/{id}/crawl stopt de laatste crawl waar die is, en antwoordt met { "id": ..., "cancelled": true, "processed": ... }. De pagina's die al gelezen zijn, blijven staan: het zijn bronnen, en er een verwijderen is een apart verzoek. Je krijgt een 404 als de agent nooit is gecrawld, of als de laatste crawl al was afgelopen.
POST /agents/{id}/retrain laat elke bron opnieuw lezen vanuit wat werd bewaard toen ze werd toegevoegd, zoals Agent opnieuw trainen doet. Het antwoordt met 202 en { "id": ..., "queued": true, "sourceCount": ... }, en de bronnen gaan terug naar pending en worden in de minuten daarna verwerkt. De website wordt niet opnieuw opgehaald, en het kost geen credits. Zolang een bron nog wordt geüpload, wacht of wordt gelezen, of een crawl bezig is, krijg je een 409 met agent_busy, zoals de knop dan grijs is. Wanneer het helpt
Chat
POST /agents/{id}/chat
| Veld | ||
|---|---|---|
message | verplicht | De vraag, hoogstens 4.000 tekens |
conversationId | Zet een eerder gesprek voort. Laat het weg om een nieuw gesprek te beginnen. | |
userId | Je eigen vaste id voor de persoon die de vraag stelt: letters, cijfers en streepjes, hoogstens 64. Het groepeert gesprekken in Activiteit. Zet er geen e-mailadres in. | |
language | en, nl, fr, de of es: de taal van het antwoord, in welke taal de vraag ook is. Zonder dit veld, of met een andere waarde, antwoordt de agent in de taal van de vraag, en in zijn eigen taal als aan de vraag geen taal te zien is. | |
stream | true voor een stream in plaats van één JSON-antwoord | |
test | true zet de vraag bij je testgesprekken (kanaal playground) in plaats van bij api, zodat ze buiten het Overzicht en klantrapporten blijft | |
page | { "url": "..." }, de pagina van je site waar de persoon naar kijkt. Heeft de agent haar als bron gelezen, dan komen de passages ervan eerst. Het deel na ? of # wordt nooit gelezen, en een adres dat niet http of https is, wordt genegeerd. |
curl -X POST https://chatterlab.ai/api/v1/agents/ag_123/chat \
-H "Authorization: Bearer cl_your_key" \
-H "Content-Type: application/json" \
-d '{"message":"Do you deliver to Belgium?"}'
{
"data": {
"conversationId": "conv_...",
"messageId": "msg_...",
"answer": "Yes. Delivery to Belgium takes two working days.",
"confidence": 84,
"grounding": "supported",
"sources": [ { "id": "src_...", "name": "Delivery", "similarity": 0.61 } ],
"model": "gpt-oss-120b",
"credits": 1
}
}
confidence loopt van 0 tot 100. grounding is supported (onderbouwd), partial (deels onderbouwd), unsupported (niet onderbouwd), of null als er geen controle is gedaan. Wat ze betekenen. Gebruik ze: een backend die confidence 20 krijgt, kan ervoor kiezen om "ik verbind je door met een collega" te tonen in plaats van het antwoord.
Een antwoord kost credits, precies zoals in de widget, test of niet. De agent onthoudt de laatste 10 berichten van een gesprek.
Streaming. Met stream: true is het antwoord een stream van server-sent events in het formaat van de UI message stream van de Vercel AI SDK, dezelfde die onze widget leest. De betrouwbaarheid en de bronnen komen aan het begin binnen. De onderbouwing kan dat niet, omdat die een tekst beoordeelt die nog niet geschreven is: lees die achteraf uit het gesprek.
Gesprekken
GET /agents/{id}/conversations accepteert ?channel= (widget, iframe, api of playground), ?from= en ?to= (datums als YYYY-MM-DD, de grenzen inbegrepen, gefilterd op het laatste bericht), ?limit= en ?cursor=. Elk item heeft id, channel, userId, startedAt, lastMessageAt, messageCount, firstMessage, lastConfidence en openedBy: launcher, greeting of nudge voor een gesprek in een chat die de knop opende, volgens waarop de bezoeker klikte, anders null.
DELETE /agents/{id}/conversations/{conversationId} wist het gesprek met alle berichten erin, de lead die de bezoeker erin achterliet en het ticket dat erbij hoort. Daarmee beantwoord je een bezoeker die vraagt vergeten te worden. Wat de agent deed blijft in het auditlog staan en het verbruik van de maand verandert niet; analyse en klantrapporten worden uit de gesprekken berekend, dus die veranderen wel.
GET /agents/{id}/conversations/{conversationId} voegt messages toe. Elk bericht heeft id, role, content en createdAt. Een vraag heeft ook attachments, de bestanden die de bezoeker erbij stuurde, meestal geen. Elk bestand heeft id, fileName, kind, mediaType, sizeBytes, pages, truncated, dat true is als de agent alleen het eerste deel las, en ocrPages, de pagina's van een scan die met tekstherkenning zijn gelezen, of null. Wat er in een bestand stond, zit er niet bij. Een vraag heeft ook page, de pagina waarop ze werd gesteld, als { "url", "title" } of null; title is de naam van de pagina als de agent haar als bron kent. Een antwoord heeft ook confidence, grounding, sources, feedback (1, -1 of null) en model.
POST /agents/{id}/messages/{messageId}/correction accepteert question en answer: wat een antwoord van de agent had moeten zeggen, zoals Verbeter antwoord in Activiteit doet. messageId is dat van het antwoord: uit het antwoord op een chatverzoek, of het id van een antwoord in een gesprek. Het antwoordt met 201 en een vraag-antwoordbron, pending tot de agent ze heeft geleerd. Het gesprek zelf verandert niet. Een antwoord wordt één keer gecorrigeerd: de tweede keer krijg je een 409 met already_corrected, en het paar pas je aan onder Bronnen. Een antwoord op een vraag met een bestand kan niet worden gecorrigeerd, want een paar kan het bestand niet dragen: dan krijg je een 422 met asked_with_file. Zwakke antwoorden verbeteren
GET /agents/{id}/visitor-files/{fileId} geeft één bestand terug dat een bezoeker stuurde, via het id waaronder een vraag het in attachments vermeldt: dezelfde velden, zijn conversationId, stored, en text, wat de agent eruit te lezen kreeg. text is null voor een afbeelding, die de agent bekeek in plaats van las, en na de 30 dagen van het bestand, wanneer ook stored false is. Het bestand zelf wordt niet meegegeven: dat download je in Activiteit. Het lezen van de tekst wordt in de audittrail vastgelegd, zoals een download. DELETE op hetzelfde adres wist het bestand en zijn tekst en laat het gesprek staan, voor wie een gesprek mag wissen. Bestanden van bezoekers
GET /agents/{id}/conversations/export geeft een link terug naar een PDF van de gesprekken in een periode, de export op de pagina Activiteit: url, die 15 minuten werkt en de PDF zonder sleutel downloadt, en expiresAt. Het accepteert ?from= en ?to= als YYYY-MM-DD, in UTC-dagen, zonder die de laatste 30 dagen, en ?channel=. Er gaan hoogstens 500 gesprekken in, de recentste. De export wordt in de audittrail vastgelegd wanneer de link wordt geopend, niet wanneer hij wordt gemaakt. De link is de sleutel, dus geef hem door zoals je een wachtwoord zou doorgeven; hij werkt meteen niet meer wanneer de sleutel die hem vroeg wordt ingetrokken.
Leads
GET /agents/{id}/leads geeft de contactgegevens die bezoekers in het formulier van de chat achterlieten, de nieuwste eerst, met ?limit= en ?cursor=. Leads die achtergelaten zijn voor een overstap naar een abonnement zonder het formulier, kun je nog lezen.
Het lead-object heeft id, conversationId, name, email, phone en company (null als het niet gevraagd of leeg gelaten werd), companyDomain (het domein van een zakelijk adres als hint van het bedrijf, null voor een adres bij een mailprovider), marketing (of de bezoeker het vakje voor nieuws en aanbiedingen aanvinkte), moment (before, questions, weak_answer of button: wat het formulier liet verschijnen), page ({ "url", "title" } of null), language, shown (de woorden die de bezoeker las toen die het verstuurde: intro, consent, privacyUrl, en marketing, null als er geen vakje was), createdAt en expiresAt, wanneer de lead verwijderd wordt als dat niet eerder gebeurt.
GET /agents/{id}/leads/{leadId} geeft één lead. DELETE op hetzelfde adres wist hem, voor wie een gesprek mag wissen, en laat het gesprek staan.
Tickets
GET /agents/{id}/tickets geeft de tickets die bezoekers in de chat openden, de meest recente activiteit eerst, met ?status= (open, waiting of solved), ?limit= en ?cursor=.
Het ticket-object heeft id, number (per agent geteld: zo noemen de bezoeker en het team het), status, email, name (null als die niet is opgegeven), question, language (die van de widget toen het geopend werd, waarin elke mail aan de bezoeker is), signedIn (of het adres van een ingelogde bezoeker kwam), page ({ "url" } of null), conversationId (null voor een ticket dat voor het eerste bericht geopend werd), createdAt, lastActivityAt, solvedAt, en expiresAt, wanneer een opgelost ticket verwijderd wordt als dat niet eerder gebeurt, null zolang het niet opgelost is.
GET /agents/{id}/tickets/{ticketId} geeft één ticket met entries, wat er na de vraag kwam, het oudste eerst. Elk heeft id, kind (visitor voor een antwoord van de bezoeker per e-mail, team voor een antwoord aan de bezoeker, note voor een notitie die alleen het team ziet, held voor een mail die tegengehouden wordt tot iemand hem in het dashboard toevoegt of weggooit), body, from (het adres waar een antwoord van de bezoeker of een tegengehouden mail vandaan kwam, anders null), mailError (waarom een antwoord aan de bezoeker niet gemaild kon worden, anders null) en createdAt.
PATCH /agents/{id}/tickets/{ticketId} neemt status: open, waiting of solved. De bezoeker krijgt niets gemaild. Het antwoordt met het ticket.
POST /agents/{id}/tickets/{ticketId}/notes neemt body, hoogstens 10.000 tekens, en antwoordt 201 met de notitie, een item met kind note.
Een bezoeker antwoorden, een ticket apart verwijderen en wie elk ticket gemaild krijgt, doe je alleen in het dashboard. Wie een gesprek verwijdert, verwijdert ook het ticket ervan, en wie een agent verwijdert, al zijn tickets.
Klanten
Deze zijn voor de eigen sleutels van een agency, vanaf Agency; daaronder worden ze geweigerd met clients_not_in_plan. Een sleutel die aan één agent vastzit, wordt alle vier geweigerd, want dat is het soort dat je aan een klant geeft, en de tarieven staan in hetzelfde record. Klanten
GET /agents/{id}/client geeft client terug (name, email, language, since, en serviceFeeEur en setupFeeEur, weggelaten voor wie tarieven niet mag zien) en report (link, de eigen link van de klant naar zijn archief, enabled, day, transcripts, holdForReview, intro en signature), of client: null voor een agent die de werkruimte voor zichzelf draait.
PUT /agents/{id}/client accepteert name, email, language, serviceFeeEur, setupFeeEur, intro, signature, reportDay (1 tot 28), transcripts, reportsEnabled en holdForReview, in elke combinatie. Wat je weglaat, blijft zoals het is, en een eerste klant heeft name en email nodig. Zolang reportsEnabled aanstaat, krijgt de klant elke maand op reportDay een rapport per e-mail. Voor een eerste klant staat het uit tenzij je true stuurt, zodat geen adres post begint te krijgen na één aanroep die niemand bevestigde; het scherm Klanten, waar je de schakelaar ziet voor je opslaat, zet het aan. De eerste keer gaan antwoorden op rapporten naar het adres van de eigenaar van de werkruimte. Een rapport meteen versturen hoort niet bij de API. Het antwoordt zoals GET.
DELETE /agents/{id}/client haalt de klant eraf: de link naar zijn archief werkt niet meer en er worden geen rapporten meer verstuurd. De agent en zijn gesprekken blijven.
POST /agents/{id}/client/report-link maakt een nieuwe link naar het archief van de klant en zet de oude stop, ook in rapporten die al verstuurd zijn. Het antwoordt met de klant en de nieuwe report.link.
Analyse
GET /agents/{id}/analytics accepteert ?from= en ?to= als YYYY-MM-DD. Zonder die twee gaat het over de laatste 30 dagen. Een periode beslaat hoogstens 366 dagen. Een datum is hier een UTC-dag, en dat zijn de schermen in het dashboard juist niet: die volgen de klok van de lezer, dus dezelfde periode kan een paar uur schelen met wat iemand op het Overzicht ziet. Je krijgt terug wat de pagina Overzicht toont: conversations, questions, helpful, notHelpful, averageConfidence, weakShare, een series per dag, de drie bands, topQuestions en weakest, en widget: de opened en conversations van de chatknop, elk ook verdeeld volgens wat de chat opende in openedBy en conversationsBy (launcher, greeting, nudge), leads, leadFormsDeclined, en startPages, tot 10 keer { "url", "title", "conversations" }. Testgesprekken tellen in geen van die cijfers mee. Een sleutel die niet aan één agent is gekoppeld, krijgt ook testConversations: het aantal dat is weggelaten.