API
Met de API koppel je een ander systeem aan je organisatie, zoals een supportdesk, een CRM of je eigen software. Dat systeem kan bijna alles wat je in het dashboard doet: toestellen en nummers inrichten, belgroepen en workflows beheren, gesprekken, opnames en voicemail ophalen, en het adresboek bijhouden.
Koppelen
- Ga naar Instellingen en dan API.
- Geef de sleutel een naam, zoals de naam van het systeem, en kies per onderdeel wat hij mag: niets, lezen, of lezen en schrijven, net als bij een rol. Je kunt alleen geven wat je zelf mag.
- Kopieer de sleutel en plak hem in het andere systeem. Je ziet hem maar één keer: kwijt is een nieuwe maken.
Wat een sleutel doet, staat in Activiteit onder zijn naam. Trek je hem in, dan werkt hij vanaf de volgende aanroep niet meer. Een sleutel kan nooit eigenaar zijn: de organisatie verwijderen, iemand eigenaar maken of een eigenaar wijzigen of verwijderen kan alleen in het dashboard.
De API
Alle aanroepen gaan naar https://api.talkip.nl/v1, met de sleutel als Bearer-token in de header Authorization. De sleutel hoort bij één organisatie, dus er staat geen organisatie in de paden. Wat je meestuurt en terugkrijgt is JSON, behalve audio en de pdf van een factuur. Tijden zijn ISO 8601 in UTC, bedragen in eurocent.
Alles hieronder staat ook in een OpenAPI-document, voor Swagger, Postman of om een client mee te maken: talkip-api.json downloaden. Het wordt uit de API zelf gemaakt, dus het loopt nooit achter. In de API-referentie bekijk je het hier, en probeer je aanroepen uit met je eigen sleutel.
curl https://api.talkip.nl/v1/me \ -H "Authorization: Bearer tkt_..."
- Sleutel
- Begint met tkt_ en is 44 tekens lang. Bewaar hem zoals je een wachtwoord bewaart.
- Limiet
- 600 aanroepen per minuut per sleutel. Voor wat geld of AI-credits kost of mail verstuurt, zoals nummers kopen, uitnodigen, transcripties en media maken of uploaden en AI-agents aanmaken of wijzigen, geldt daarnaast elk een limiet van 100 per uur.
- Fouten
- Een foutcode met een JSON-body, zoals
{ "error": "forbidden", "message": "API_KEY_PERMISSION_ERROR" }. Klopt de body, een parameter of de query niet, dan iserrorvalidationen staat inissueswat er mis is.
- 400
- De body of de parameters kloppen niet.
- 401
- Geen, een onbekende of een ingetrokken sleutel.
- 403
- Niet toegestaan.
API_KEY_PERMISSION_ERROR: de sleutel mist de toegang, of wie hem maakte heeft die niet meer.API_KEY_CREATOR_GONE_ERROR: wie de sleutel maakte, is geen lid meer van de organisatie.PLAN_FEATURE_UNAVAILABLE_ERROR: het abonnement heeft het niet, of heeft geen API meer.TENANT_INACTIVE_ERROR: de organisatie is opgeschort. - 404
- Bestaat niet, of is niet van deze organisatie.
- 409
- Kan nu niet, bijvoorbeeld een toestelnummer dat al bestaat of te weinig AI-credits.
- 429
- Te veel aanroepen. Wacht het aantal seconden uit Retry-After (ook in retryAfterSeconds) en probeer het dan opnieuw.
Toegang
Een sleutel heeft per onderdeel van het dashboard geen toegang, lezen, of lezen en schrijven, net als een rol. Elke aanroep vraagt lezen of schrijven op zijn onderdeel, zoals Belgroepen voor /ring-groups; dat staat hieronder bij elk deel. Mag wie de sleutel maakte iets niet meer, dan de sleutel ook niet. Zonder toegang kan een sleutel alleen GET /me, het verbruik, de AI-credits, de limieten en de opname-instellingen lezen.
Wat er in gesprekken is gezegd, zoals opnames, transcripties, samenvattingen en AI-gesprekken, vraagt lezen op Gespreksopnames. Zonder dat staan die velden in de gesprekshistorie op null.
Als reseller
Een reseller kan met zijn eigen sleutel, die met tk_ begint, de API van elke organisatie gebruiken die hij beheert. Zet dan in de header TalkIP-Tenant-Id het id van de organisatie. Zo'n sleutel mag alles hierboven, ook als het abonnement van de organisatie geen API heeft. Wat je zo doet, staat in de activiteit van de organisatie onder je naam.
curl https://api.talkip.nl/v1/calls/live \ -H "Authorization: Bearer tk_..." \ -H "TalkIP-Tenant-Id: 01a1..."
Zonder geldige header krijg je een 400 met TENANT_REQUIRED_ERROR. Een organisatie die niet van jou is of die je hebt beëindigd, geeft een 404.
De sleutel
GET /me
Bij welke organisatie de sleutel hoort en wat hij mag. Handig om een geplakte sleutel te controleren.
{
"tenant": {
"id": "01a1...",
"name": "Bakkerij Jansen",
"slug": "bakkerij-jansen",
"sipDomain": "bakkerij-jansen.<sip-domein>",
"plan": "pro",
"seats": 3,
"features": { "transcription": true, "aiAgents": true, "api": true, ... }
},
"apiKey": {
"id": "01a1...",
"name": "Loxxa",
"prefix": "tkt_dryEJS",
"access": { "devices": "write", "live-calls": "write", "call-history": "read" }
}
}Leden
Lezen vraagt Leden lezen, de rest Leden schrijven. Rollen maken en wijzigen kan alleen een eigenaar, in het dashboard.
GET /members- Leden en openstaande uitnodigingen, met
owneren hunrole. GET /roles- De rollen, met wat elk per onderdeel mag en hoeveel leden hem hebben.
POST /members- Nodigt iemand uit met
emailen eventueel eenroleId. De mail komt namens de organisatie. POST /members/:memberId/resend- Verstuurt een uitnodiging opnieuw.
PUT /members/:memberId/role- Geeft een lid een rol met
roleId, ofnullvoor geen. Niet bij een eigenaar en niet bij wie de sleutel maakte. DELETE /members/:memberId- Verwijdert een lid of trekt een uitnodiging in, geen eigenaar.
Toestellen, toestelnummers en nummers
Toestellen, agents en toestelnummers vallen onder Toestellen, nummers en aanvragen onder Nummers: lezen om te bekijken, schrijven voor de rest. De limieten lezen mag elke sleutel.
GET /devices- Alle toestellen.
POST /devices- Maakt een toestel met
name,userId(ofnullvoor een toestel van niemand) encallerId: een nummer van de organisatie of een dat TalkIP heeft goedgekeurd, anders409. Geeft de SIP-gegevens terug, met het wachtwoord, dat alleen nu te zien is. PATCH /devices/:deviceId- Wijzigt naam, eigenaar, nummerweergave of aan/uit.
POST /devices/:deviceId/password- Een nieuw SIP-wachtwoord. Het oude werkt meteen niet meer.
POST /devices/:deviceId/join-code- Een koppelcode voor de app.
DELETE /devices/:deviceId- Verwijdert een toestel.
GET /extensions- Alle toestelnummers met hun bestemming.
POST /extensions- Maakt een toestelnummer met
extensionendestination. PUT /extensions/:extensionId/destination- Waar het toestelnummer heen gaat.
DELETE /extensions/:extensionId- Verwijdert een toestelnummer.
GET /numbers- De nummers van de organisatie met hun bestemming.
GET /numbers/available- Nummers die je kunt kopen. Nummers schrijven.
POST /numbers- Koopt een nummer. Niet bij een organisatie die een reseller beheert.
PUT /numbers/:numberId/destination- Waar het nummer heen gaat.
PUT /numbers/:numberId/caller-rules- De bellerregels van het nummer, als
callerRules: hoogstens 20, op volgorde, elk metname,matchendestination. De regels staan ook inGET /numbers. DELETE /numbers/:numberId- Geeft een nummer op.
GET /number-requests- Aanvragen voor nummers die niet op voorraad zijn.
POST /number-requests- Vraagt nummers aan.
DELETE /number-requests/:requestId- Trekt een aanvraag in.
GET /limits- De limieten voor belminuten en het verbruik nu.
PUT /limits- Zet de limieten per gesprek, dag en maand. Instellingen schrijven.
Een destination is een object met type en het id dat erbij hoort, zoals { "type": "ringGroup", "ringGroupId": "01a1..." }. De types zijn user, device, ringGroup, ivr, workflow, voicemail, businessHours, aiAgent, queue, conferenceRoom en directory. Een aankondiging is { "type": "announcement", "mediaId": "01a1..." }: het fragment speelt één keer en dan wordt opgehangen. Een nummer buiten TalkIP is { "type": "externalNumber", "number": "06 1234 5678" }, getypt zoals je het kiest en bewaard als E.164. Een nummer buiten de belbestemmingen geeft 400 met EXTERNAL_NUMBER_NOT_ALLOWED_ERROR, een nummer van de organisatie zelf EXTERNAL_NUMBER_IS_OWN_ERROR.
PUT /numbers/01a1.../caller-rules
{
"callerRules": [
{ "name": "Anoniem", "match": { "type": "anonymous" }, "destination": null },
{
"name": "Amsterdam",
"match": { "type": "numbers", "numbers": ["020*", "0612345678"] },
"destination": { "type": "queue", "queueId": "01a1..." }
}
]
}Een regel geldt voor anonymous, bellers zonder nummer, of voor numbers: hoogstens 500, met een * aan het eind voor alles wat zo begint. De eerste regel die past telt. destination null weigert het gesprek.
Routering
Elk deel heeft zijn eigen onderdeel, zoals Belgroepen of Media: bekijken vraagt lezen, maken, wijzigen en verwijderen schrijven. De bodies zijn dezelfde als die het dashboard stuurt, met dezelfde limieten van het abonnement.
GET, POST /ring-groups- Belgroepen.
PUT, DELETE /ring-groups/:ringGroupId- Een belgroep wijzigen of verwijderen.
strategyissimultaneous,sequential,roundRobin,longestIdleofrandom, en metskipBusygaan leden die al in gesprek zijn niet over. GET, POST /queues- Wachtrijen, met hun leden en wie er is aangemeld. Maken vraagt Pro of Business.
PUT, DELETE /queues/:queueId- Een wachtrij wijzigen of verwijderen. Wie lid blijft, blijft aangemeld.
GET /queues/:queueId/statistics- Hoe de wachtrij liep, per dag en per collega, met wachttijden en
serviceLevelvan 0 tot 1. MetfromentoalsYYYY-MM-DDkies je de dagen, standaard de laatste zeven, hooguit 366. GET, POST /conference-rooms- Vergaderlijnen. Maken vraagt Pro of Business.
PUT, DELETE /conference-rooms/:conferenceRoomId- Een vergaderlijn wijzigen of verwijderen.
GET, POST /directories- Telefoonboeken.
PUT, DELETE /directories/:directoryId- Een telefoonboek wijzigen of verwijderen.
GET, POST /ivrs- Keuzemenu's.
PUT, DELETE /ivrs/:ivrId- Een keuzemenu wijzigen of verwijderen.
GET, POST /business-hours- Openingstijden.
PUT, DELETE /business-hours/:businessHoursId- Openingstijden wijzigen of verwijderen.
GET, POST /call-actions- Gespreksacties, ook parkeren met de actie park.
PUT, DELETE /call-actions/:callActionId- Een gespreksactie wijzigen of verwijderen.
GET, POST /ai-agents- AI-agents.
PUT, DELETE /ai-agents/:aiAgentId- Een AI-agent wijzigen of verwijderen. Wordt hij net al gewijzigd, dan krijg je
409metAI_AGENT_BUSY_ERROR: probeer het over een minuut opnieuw. GET, POST /workflows- Workflows. Maken vraagt de module Workflows.
GET, PUT, DELETE /workflows/:workflowId- Eén workflow, met de hele tekening. Opslaan kan AI-credits kosten voor nieuwe vragen.
GET /workflows/:workflowId/executions- Hoe de workflow is gelopen.
GET /workflows/:workflowId/executions/:executionId- Eén keer, stap voor stap. Wat de beller zei en intoetste alleen met Gespreksopnames lezen.
GET /media- Fragmenten.
POST /media- Uploadt een fragment als multipart, met
nameenfile. Gebruikt de organisatie al twee keer de opslag van haar abonnement, dan krijg je409metSTORAGE_FULL_ERROR. GET /media/:mediaId/audio- Het fragment als WAV.
DELETE /media/:mediaId- Verwijdert een fragment dat nergens meer wordt gebruikt.
GET /media/generation/options- Stemmen en soorten om met AI te maken. Media schrijven.
POST /media/generation- Maakt een fragment met AI, voor AI-credits.
Gesprekken
GET /calls/live- Wie er nu belt. Live gesprekken lezen.
GET /calls- De gesprekshistorie, met dezelfde filters als het dashboard. Gesprekshistorie lezen; opname, transcriptie en AI-gesprekken alleen met Gespreksopnames lezen.
GET /calls/:callRecordId/flow- Waar het gesprek heen ging: openingstijden, keuzemenu, wie er overging en wie opnam, de workflows onderweg. Gesprekshistorie lezen.
GET /calls/:callRecordId/ai-conversations- Wat een AI-agent in het gesprek heeft genoteerd.
GET, POST, DELETE /calls/:callRecordId/transcript- De transcriptie lezen, laten maken (voor AI-credits) of verwijderen.
GET, POST, DELETE /calls/:callRecordId/summary- De samenvatting lezen, laten maken (voor AI-credits) of verwijderen.
GET /recordings- Opnames.
GET /recordings/:recordingId/audio- Een opname als stereo-WAV: de beller links, de ander rechts.
DELETE /recordings/:recordingId- Verwijdert een opname.
GET /recording-settings- Of gesprekken standaard worden opgenomen, getranscribeerd en samengevat.
PUT /recording-settings- Zet die standaard. Instellingen schrijven.
GET /voicemail-boxes- Voicemailboxen.
POST, PUT, DELETE /voicemail-boxes[/:boxId]- Een voicemailbox maken, wijzigen of verwijderen.
GET /voicemail/messages- Voicemailberichten.
GET /voicemail/messages/:messageId/audio- Een bericht als WAV.
PUT /voicemail/messages/:messageId/read- Markeert een bericht als gelezen.
DELETE /voicemail/messages/:messageId- Verwijdert een bericht.
Adresboek
Lezen vraagt Contacten lezen, maken, wijzigen en verwijderen Contacten schrijven.
GET /contacts- Het gedeelde adresboek op naam, als
itemsmetnextCursor: geef die alscursormee voor de volgende pagina, tot hijnullis. Metsearchzoek je op naam, bedrijf of nummer, enlimitis 100 per pagina, hooguit 500. GET /contacts/:contactId- Eén contact.
POST /contacts- Maakt een contact met
name,company,numberenemail. PUT /contacts/:contactId- Wijzigt een contact.
DELETE /contacts/:contactId- Verwijdert een contact.
Bellen vanuit een ander systeem
Zo neemt een supportdesk, zoals Loxxa, de telefonie over: zijn medewerkers bellen en worden gebeld in zijn eigen scherm, via TalkIP.
- Maak een sleutel die Toestellen, Live gesprekken en API & webhooks mag lezen en schrijven, en plak hem in het andere systeem. Dat meldt met
POST /webhookszelf een webhook aan. - Het systeem maakt voor elke medewerker een agent met
POST /agents, met zijn eigen id inexternalId. Een agent is een toestel zonder TalkIP-account en neemt een gebruiker in, net als een lid. - Zet de agents in een belgroep en stuur een nummer naar die belgroep, of geef ze een toestelnummer. Inkomende gesprekken komen dan binnen in de softphone van het andere systeem, en
call.startedvertelt wie er belt. - In de browser van de medewerker bel je met de softphone-SDK
@talkip/softphone. De server van het andere systeem vraagt daarvoor een token metPOST /agents/:agentId/softphone, met deoriginvan de pagina, en geeft het aan de browser.
import { Softphone } from '@talkip/softphone';
const phone = new Softphone({
// Elke verbinding een nieuw token, via je eigen server.
getToken: () => fetch('/talkip/softphone-token', { method: 'POST' }).then((response) => response.json()),
autoAnswer: true,
});
await phone.connect();
phone.dial('0201234567');Klik-om-te-bellen, ophangen en doorverbinden
Met POST /calls gaat eerst het toestel van de agent over. Neemt die op, dan belt TalkIP de bestemming, alsof de agent zelf had gekozen: met zijn nummerweergave, de limieten en de opnames van de organisatie. Met autoAnswer neemt de SDK, of een bureautoestel dat het kan, meteen op. Naar 112 bel en verbind je zo nooit door: dat geeft 400. Het alarmnummer belt iemand zelf.
POST /calls
{ "deviceId": "01a1...", "destination": "0612345678", "autoAnswer": true }
202
{ "id": "01a1...", "kind": "originate", "status": "claimed", "error": null, "callRecordId": "01a1...", ... }- status
- pending, claimed (de centrale is ermee bezig), done of failed. Klik-om-te-bellen is done zodra de agent opneemt; doorverbinden zodra de bestemming overgaat.
- error
- Bij failed: waarom. not_registered: de agent is niet online. no_answer, busy, declined, unavailable of cancelled: de agent nam niet op. forbidden: dat nummer mag niet, of er is geen nummerweergave. limit_reached: de belminuten zijn op. not_bridged: doorverbinden kan alleen tijdens een gesprek. not_found, unsupported, congestion, timeout of expired: het lukte niet.
- callRecordId
- Het gesprek. Ook in de webhooks call.started, call.answered en call.ended.
GET /agents- De agents, als toestellen: online of niet. Met
externalIdzoek je er één. POST /agents- Maakt een agent met
name,externalId,callerIden eventueel eenextension. Kan niet als alle gebruikers in gebruik zijn. PATCH /agents/:agentId- Wijzigt een agent, of zet hem uit met enabled.
DELETE /agents/:agentId- Verwijdert een agent. Zijn gebruiker komt vrij.
POST /agents/:agentId/softphone- Een token voor de SDK.
POST /calls- Klik-om-te-bellen.
POST /calls/:callRecordId/hangup- Hangt een lopend gesprek op, voor iedereen.
POST /calls/:callRecordId/transfer- Verbindt blind door naar
destination. MetdeviceIdvertrekt die kant, zoals de agent; zonder vertrekt wie er gebeld werd. GET /call-commands/:commandId- Hoe een opdracht is gegaan.
Alles hier vraagt Live gesprekken schrijven; hoe een opdracht ging lezen vraagt Live gesprekken lezen.
Webhooks
Met een webhook hoort het andere systeem meteen wat er gebeurt, zonder steeds te vragen: een gesprek dat binnenkomt, wordt opgenomen of eindigt, een opname of transcriptie die klaar is, een nieuw voicemailbericht. TalkIP stuurt dan binnen een seconde een POST met JSON naar het adres dat je opgeeft. Je maakt een webhook in het dashboard, onder Instellingen en dan API, of met POST /webhooks, zodat een systeem zich bij het koppelen zelf aanmeldt. Een organisatie heeft er hoogstens 10.
{
"id": "01a1...",
"type": "call.started",
"createdAt": "2026-10-20T09:15:02.000Z",
"tenantId": "01a1...",
"data": {
"call": {
"id": "01a1...",
"direction": "inbound",
"from": { "number": "+31612345678", "name": "Jan Klant (Bakkerij)", "device": null, "deviceId": null },
"to": { "number": "+31201234567", "name": null, "device": null, "deviceId": null },
"contact": { "id": "01a1...", "name": "Jan Klant", "company": "Bakkerij", "email": null },
"startedAt": "2026-10-20T09:15:02.000Z",
"answeredAt": null,
"endedAt": null,
"durationSeconds": null,
"hangupCause": null
}
}
}- call.started
- Een gesprek begint. In
contactstaat het contact met het nummer van de ander, als dat er is. - call.answered
- Iemand neemt op. In to.deviceId staat het toestel dat opnam.
- call.ended
- Het gesprek is voorbij, met de duur en waarom het eindigde.
- recording.ready
- Een opname is klaar. Haal hem op met GET /recordings/:recordingId/audio.
- transcript.ready
- Een transcriptie is klaar. Haal hem op met GET /calls/:callRecordId/transcript.
- summary.ready
- Een samenvatting is klaar.
- voicemail.received
- Er is een voicemailbericht ingesproken.
- ai-conversation.ended
- Een AI-agent is klaar met een gesprek. Wat hij noteerde, staat bij GET /calls/:callRecordId/ai-conversations.
- webhook.test
- Alleen als je om een test vraagt.
Een webhook stuurt nooit wat er is gezegd: alleen wat er gebeurde en de id's om de rest op te halen, met een sleutel die Gespreksopnames mag lezen. Kies je geen gebeurtenissen, dan krijg je ze allemaal, ook die er later bij komen.
Controleren dat het van TalkIP komt
Elke webhook heeft een geheim dat begint met whsec_. Je ziet het alleen als hij wordt gemaakt of als je het vernieuwt. Elk bericht heeft de header TalkIP-Webhook-Signature, zoals t=1760951702,v1=5f2b...: v1 is de HMAC-SHA256 met het geheim van t, een punt en de body zoals die binnenkwam, in hex. Klopt hij niet, of is t meer dan vijf minuten oud, gooi het bericht dan weg.
import { createHmac, timingSafeEqual } from 'node:crypto';
const [t, v1] = signature.split(',').map((part) => part.split('=')[1]);
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
const valid = timingSafeEqual(Buffer.from(v1), Buffer.from(expected)) && Date.now() / 1000 - Number(t) < 300;Afleveren en opnieuw proberen
- Antwoord binnen 10 seconden met een 2xx. Een doorverwijzing wordt niet gevolgd.
- Lukt het niet, dan proberen we het opnieuw na 10 seconden, 1 minuut, 5 minuten, een half uur, 2, 6, 12 en 24 uur. Daarna geven we het op. In het dashboard of met
POST /webhooks/:id/deliveries/:id/retrystuur je een bericht opnieuw. - Berichten kunnen in een andere volgorde of twee keer aankomen. De header
TalkIP-Webhook-Idis hetzelfde alsidin de body. Daarmee herken je een bericht dat je al had. - Webhooks gaan alleen naar openbare adressen, en wat er is verstuurd bewaren we 30 dagen.
GET /webhooks- De webhooks, met hoe de laatste aflevering ging. API & webhooks lezen; de rest schrijven.
POST /webhooks- Maakt een webhook met
url,description,eventsenenabled. Het geheim staat alleen in dit antwoord. PATCH /webhooks/:webhookId- Wijzigt het adres, de gebeurtenissen of zet hem aan of uit.
DELETE /webhooks/:webhookId- Verwijdert een webhook.
POST /webhooks/:webhookId/secret- Een nieuw geheim. Het oude werkt meteen niet meer.
POST /webhooks/:webhookId/test- Stuurt een webhook.test, ook als hij uit staat.
GET /webhooks/:webhookId/deliveries- Wat er is verstuurd, nieuwste eerst.
POST /webhooks/:webhookId/deliveries/:deliveryId/retry- Stuurt een bericht opnieuw.
Verbruik, facturen en activiteit
GET /statistics- De cijfers van het overzicht, voor de hele organisatie. Overzicht lezen.
GET /credits- Het saldo AI-credits.
GET /usage- Het verbruik deze maand, en hoeveel de organisatie heeft van wat het abonnement begrenst.
GET /usage/storage/files- De grootste bestanden. Gespreksopnames lezen.
GET /billing- Het overzicht van Financieel. Financieel lezen.
GET /billing/invoices- Facturen. Financieel lezen.
GET /billing/invoices/:invoiceId- Eén factuur. Financieel lezen.
GET /billing/invoices/:invoiceId/pdf- De factuur als pdf. Financieel lezen.
GET /audits- De activiteit, met het abonnement Business. Instellingen lezen.
- Betalen, het abonnement, gebruikers en modules wijzigen en AI-credits kopen gaan via het dashboard, niet via de API.
- Beheert een reseller de organisatie, dan geven de facturen een 403: die staan bij de reseller.