Guider
Ring ut og styr samtalen
POST /v1/calls starter en samtale. Hvem som er med, bestemmer du: et telefonnummer, en eller flere brukere i appen din, eller begge. Mens samtalen pågår, kan du legge til og ta ut deltakere, lese opp tekst og lytte etter tastetrykk.Ring og les opp en tekst
Den enkleste samtalen ringer et nummer og leser opp en tekst når noen svarer. from må være et av profilens aktive numre.
curl -X POST "https://api.telkit.no/v1/calls" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: time-8812-oppringing" \ -d '{ "profileId": "0199e4a2-7c1b-7d3e-9a41-5f2c8b6d1e07", "to": "+4791234567", "from": "+4721234567", "text": "Hei, dette er en påminnelse om timen din i morgen klokken ti.", "voice": "no_female", "externalRef": "time-8812"}'const response = await fetch("https://api.telkit.no/v1/calls", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "time-8812-oppringing", }, body: JSON.stringify({ profileId: "0199e4a2-7c1b-7d3e-9a41-5f2c8b6d1e07", to: "+4791234567", from: "+4721234567", text: "Hei, dette er en påminnelse om timen din i morgen klokken ti.", voice: "no_female", externalRef: "time-8812", }),});const answer = await response.json();I stedet for text kan du spille et lydklipp med audioClipId. repeat: true spiller meldingen to ganger. Svaret er samtalen med id, state og deltakerne.
Koble en selger i nettleseren til kunden
Et CRM som ringer mange kunder om dagen, vil at selgeren snakker fra nettleseren. Legg selgeren til som en app-deltaker med din egen id i externalRef:
curl -X POST "https://api.telkit.no/v1/calls" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: lead-5521-forsok-1" \ -d '{ "profileId": "0199e4a2-7c1b-7d3e-9a41-5f2c8b6d1e07", "to": "+4791234567", "from": "+4721234567", "participants": [ { "kind": "app", "externalRef": "selger-17", "displayName": "Kari i salg" } ], "recording": true, "transcription": true, "amd": { "mode": "detect" }, "maxMinutes": 30, "externalRef": "lead-5521", "metadata": { "kampanje": "host-2026" }}'const response = await fetch("https://api.telkit.no/v1/calls", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "lead-5521-forsok-1", }, body: JSON.stringify({ profileId: "0199e4a2-7c1b-7d3e-9a41-5f2c8b6d1e07", to: "+4791234567", from: "+4721234567", participants: [ { kind: "app", externalRef: "selger-17", displayName: "Kari i salg", }, ], recording: true, transcription: true, amd: { mode: "detect", }, maxMinutes: 30, externalRef: "lead-5521", metadata: { kampanje: "host-2026", }, }),});const answer = await response.json();- Hver app-deltaker i svaret har
connectionmedurlogtoken. Gi dem til selgerens nettleser, som kobler seg til samtalen med en LiveKit-klient, for eksempellivekit-client. Lyden går gjennom LiveKit. - Trenger nettleseren en ny nøkkel, etter en omlasting eller et brudd, henter du den slik:
curl -X POST "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants/0199e4a3-2b7e-7c90-b1d4-6a8f2e5c3d10/token" \ -H "Authorization: Bearer $TELKIT_API_KEY"const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants/0199e4a3-2b7e-7c90-b1d4-6a8f2e5c3d10/token", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, },});const answer = await response.json();Opptak, tekst og telefonsvarer
recording: truetar opp samtalen. Du fårcall.recording.readynår opptaket er lagret.transcription: truegjør opptaket om til tekst etter samtalen. Du fårcall.transcript.ready, og teksten ligger påGET /v1/calls/:id/transcript.amdgjetter om et menneske eller en telefonsvarer tok telefonen, og sendercall.machineDetected. Medhangup_on_machinelegger vi på hos en telefonsvarer. Medvoicemail_dropventer vi til hilsenen er ferdig og legger igjen et lydklipp (clipId) eller en opplest tekst (text). Dette virker bare på en samtale uten automatisk melding.
curl "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/transcript" \ -H "Authorization: Bearer $TELKIT_API_KEY"const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/transcript", { headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, },});const answer = await response.json();Dine egne referanser
externalRef og metadata kommer tilbake i alle hendelser om samtalen, så CRM-et vet hvilken kunde og kampanje den gjelder. Når samtalen er over, kan selgeren sette resultatet:
curl -X PATCH "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "metadata": { "kampanje": "host-2026", "resultat": "mote-booket" }}'const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21", { method: "PATCH", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ metadata: { kampanje: "host-2026", resultat: "mote-booket", }, }),});const answer = await response.json();Har nummeret en selgerreferanse (assignedTo), står den i call.ended.
Konferanse: flere i samme samtale
En samtale kan ha flere deltakere: telefoner, app-brukere og medarbeidere. Ring opp en kollega inn i samtalen:
curl -X POST "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: lead-5521-kollega" \ -d '{ "participant": { "kind": "phone", "to": "+4798765432", "displayName": "Per" }}'const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "lead-5521-kollega", }, body: JSON.stringify({ participant: { kind: "phone", to: "+4798765432", displayName: "Per", }, }),});const answer = await response.json();Du kan dempe en deltaker, sette den på vent (held) eller endre hva den hører og sier (audioMode: talk, listen eller whisper):
curl -X PATCH "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants/0199e4a3-2b7e-7c90-b1d4-6a8f2e5c3d10" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "muted": true}'const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants/0199e4a3-2b7e-7c90-b1d4-6a8f2e5c3d10", { method: "PATCH", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ muted: true, }),});const answer = await response.json();Å ta ut én deltaker avslutter ikke samtalen for de andre:
curl -X DELETE "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants/0199e4a3-2b7e-7c90-b1d4-6a8f2e5c3d10" \ -H "Authorization: Bearer $TELKIT_API_KEY"const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants/0199e4a3-2b7e-7c90-b1d4-6a8f2e5c3d10", { method: "DELETE", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, },});const answer = await response.json();Hver endring gir call.participant.joined, call.participant.left eller call.participant.updated.
Samtaler mellom app-brukere
Uten to og med bare app-deltakere er samtalen en samtale mellom brukerne i plattformen din. Ingen telefon blir ringt. conference: true holder samtalen åpen så lenge noen er i den.
curl -X POST "https://api.telkit.no/v1/calls" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: rom-301-302" \ -d '{ "profileId": "0199e4a2-7c1b-7d3e-9a41-5f2c8b6d1e07", "participants": [ { "kind": "app", "externalRef": "bruker-301", "displayName": "Ola" }, { "kind": "app", "externalRef": "bruker-302", "displayName": "Nora" } ], "conference": true, "maxMinutes": 60}'const response = await fetch("https://api.telkit.no/v1/calls", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "rom-301-302", }, body: JSON.stringify({ profileId: "0199e4a2-7c1b-7d3e-9a41-5f2c8b6d1e07", participants: [ { kind: "app", externalRef: "bruker-301", displayName: "Ola", }, { kind: "app", externalRef: "bruker-302", displayName: "Nora", }, ], conference: true, maxMinutes: 60, }),});const answer = await response.json();Prisen er per deltaker og minutt.
Din egen bot i samtalen
Har du din egen bot, for eksempel en stemmeassistent, kan den være deltaker i samtalen. Legg den til med kind satt til bot:
curl -X POST "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: lead-5521-bot" \ -d '{ "participant": { "kind": "bot", "displayName": "Kundebot", "externalRef": "bot-okt-42", "maxMinutes": 20 }}'const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/participants", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "lead-5521-bot", }, body: JSON.stringify({ participant: { kind: "bot", displayName: "Kundebot", externalRef: "bot-okt-42", maxMinutes: 20, }, }),});const answer = await response.json();- Svaret har
connectionmedurlogtoken. Boten kobler seg til samtalen fra serveren din med en LiveKit-klient, for eksempel@livekit/rtc-node. Lyden går direkte mellom boten og LiveKit, ikke gjennom oss. - Boten kan snakke med mikrofonlyd og høre alle som snakker i samtalen. Den kan ikke sende datameldinger, så den kan aldri utgi seg for å være telkit overfor brukerne i appen din.
- Nøkkelen virker så lenge boten har betalt tid, pluss 5 minutter til å koble seg til, og aldri mer enn 2 timer. En ny nøkkel til samme bot henter du med
POST /v1/calls/:id/participants/:participantId/token. - Boten er med til den kobler seg fra, til du tar den ut, eller til den betalte tiden er brukt opp. Da blir den koblet fra, og nøkkelen slutter å virke.
- I en konferanse eller en samtale mellom app-brukere holder en bot ikke samtalen åpen alene: når den siste personen går, er samtalen over. Det samme gjelder en AI-agent.
- Du får
call.participant.joinedogcall.participant.leftmedkindbot.
Eksempel med @livekit/rtc-node
import { AudioFrame, AudioSource, AudioStream, LocalAudioTrack, Room, RoomEvent, TrackKind, TrackPublishOptions, TrackSource,} from "@livekit/rtc-node"; const sampleRate = 16000; /** `connection` is the bot's { url, token } from POST /v1/calls/:id/participants. */export async function runBot(connection) { const room = new Room(); await room.connect(connection.url, connection.token, { autoSubscribe: true, dynacast: false }); // Hear: every voice in the call, as 16-bit samples at 16 kHz. room.on(RoomEvent.TrackSubscribed, async (track, _publication, participant) => { if (track.kind !== TrackKind.KIND_AUDIO) return; for await (const frame of new AudioStream(track, sampleRate, 1)) { // frame.data is an Int16Array from participant.identity: hand it to your recognizer. } }); // Speak: one microphone track. The token allows nothing else (no camera, no data). const source = new AudioSource(sampleRate, 1); const track = LocalAudioTrack.createAudioTrack("bot-voice", source); const options = new TrackPublishOptions({ source: TrackSource.SOURCE_MICROPHONE }); await room.localParticipant?.publishTrack(track, options); // Send audio in 20 ms frames (here: silence); your speech synthesis fills them. const samples = sampleRate / 50; await source.captureFrame(new AudioFrame(new Int16Array(samples), sampleRate, 1, samples)); room.on(RoomEvent.Disconnected, () => { // The call ended, you removed the bot, or its paid time ran out. });} Pris og grenser
- Boten koster per påbegynte minutt den er i samtalen, i tillegg til samtalens egne minutter. Minuttene reserveres når du legger den til: inntil
maxMinutes, høyst 60 minutter og aldri lenger enn samtalens betalte tid. - Opptak og transkripsjon av alle stemmer tar med det boten sier.
- Med en testnøkkel er boten gratis og med i høyst ett minutt. Da finnes det ikke noe ekte rom, så
connectionernull.
Styr samtalen mens den pågår
| Kall | Betyr |
|---|---|
POST /v1/calls/:id/say | Les opp en tekst for alle eller én deltaker. |
POST /v1/calls/:id/play | Spill et lydklipp, eventuelt om og om igjen. |
POST /v1/calls/:id/gather | Spør og lytt etter tastetrykk eller tale. Se menyer. |
POST /v1/calls/:id/dtmf | Send tastetoner inn i samtalen. Ikke åpnet ennå: til vi har bekreftet at tonene høres på en ekte telefon, svarer API-et capability_unavailable. |
POST /v1/calls/:id/media/stop | Stopp lyden som spilles. |
POST /v1/calls/:id/recording/start | Start et opptak midt i samtalen. |
POST /v1/calls/:id/transcription/start | Skriv ned samtalen mens den pågår. |
POST /v1/calls/:id/hangup | Legg på for alle. |
curl -X POST "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/say" \ -H "Authorization: Bearer $TELKIT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: lead-5521-opptaksvarsel" \ -d '{ "text": "Samtalen blir tatt opp.", "voice": "no_female"}'const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/say", { method: "POST", headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "lead-5521-opptaksvarsel", }, body: JSON.stringify({ text: "Samtalen blir tatt opp.", voice: "no_female", }),});const answer = await response.json();Handlinger som går til telefonnettet eller lydsystemet, blir utført etter at svaret er sendt. Utfallet kommer som call.command.completed, call.command.failed eller call.command.uncertain (vi fikk ikke vite om den ble utført). Du kan også spørre:
curl "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/commands/0199e4a3-3c8f-7da1-82e5-7b9a3f6d4e21" \ -H "Authorization: Bearer $TELKIT_API_KEY"const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21/commands/0199e4a3-3c8f-7da1-82e5-7b9a3f6d4e21", { headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, },});const answer = await response.json();Når en opplesning eller et lydklipp er ferdig, får du call.playback.ended.
Pris og slutt
Alt du ber om i POST /v1/calls prises og reserveres samlet når samtalen starter, for inntil maxMinutes minutter eller så lenge saldoen rekker. Når samtalen er over, får du call.ended med varighet, tellede minutter og pris, og ubrukt reservasjon går tilbake til saldoen. Hent samtalen når som helst:
curl "https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21" \ -H "Authorization: Bearer $TELKIT_API_KEY"const response = await fetch("https://api.telkit.no/v1/calls/0199e4a3-1f6d-7a2b-8c55-3e9d0a7b4c21", { headers: { Authorization: `Bearer ${process.env.TELKIT_API_KEY}`, },});const answer = await response.json();