Endpoints med eksempler
Alle endpoints i API v1 — henvendelser, kontakter, opkald, viden og Noa Voice — med eksempler i curl og JavaScript.
Alle adresser starter med https://app.telenoa.com/api/v1. Den fulde, maskinlæsbare beskrivelse med alle felter står i openapi.json — den kan læses ind i fx Postman, Insomnia eller en kodegenerator.
Eksemplerne i JavaScript bruger denne lille hjælper (Node 18 eller nyere):
const TELENOA = "https://app.telenoa.com/api/v1";
const NOEGLE = process.env.TELENOA_API_KEY; // tln_live_…
async function telenoa(sti, { metode = "GET", krop, idempotens } = {}) {
const res = await fetch(TELENOA + sti, {
method: metode,
headers: {
Authorization: `Bearer ${NOEGLE}`,
...(krop ? { "Content-Type": "application/json" } : {}),
...(idempotens ? { "Idempotency-Key": idempotens } : {}),
},
body: krop ? JSON.stringify(krop) : undefined,
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.fejl.kode}: ${data.fejl.besked}`);
return data;
}Henvendelser
En henvendelse er en mail, en formular (også fra chat-widgetten) eller et opkald — det samme, som står i Henvendelser i appen.
| Felt | |
|---|---|
status | modtaget, i_gang, afventer eller loest |
mappe | indbakke, arkiv eller spam |
kanal | mail, formular eller opkald |
prioritet | lav, mellem eller hoej |
kategori | Kategorien (jeres mærke på henvendelsen), fx { "id": "…", "navn": "Tilbud" } |
tildelt_til | Medarbejderen, den er tildelt, eller null |
resume | Noas resumé |
ekstern_id | Jeres eget id, hvis I oprettede den med et |
List henvendelser
GET /henvendelser — kræver henvendelser:read.
Filtre: status, mappe (standard indbakke), kanal, tildelt_til (et bruger-id eller ingen), kategori_id, kontakt_id, oprettet_efter, oprettet_foer, opdateret_efter, q (fritekst), limit og cursor.
curl "https://app.telenoa.com/api/v1/henvendelser?status=modtaget&kanal=mail&limit=20" \
-H "Authorization: Bearer $TELENOA_API_KEY"// Alle henvendelser ændret siden sidste synkronisering
let cursor = null;
do {
const side = await telenoa(`/henvendelser?opdateret_efter=${sidst}&limit=100${cursor ? `&cursor=${cursor}` : ""}`);
for (const h of side.data) await gem(h);
cursor = side.naeste_cursor;
} while (cursor);Hent én henvendelse
GET /henvendelser/{id} — kræver henvendelser:read. Svaret har også beskeder: mailtråden, ældste først.
curl https://app.telenoa.com/api/v1/henvendelser/6f1c… \
-H "Authorization: Bearer $TELENOA_API_KEY"Opret en henvendelse
POST /henvendelser — kræver henvendelser:write.
Henvendelsen behandles præcis som en formular fra jeres hjemmeside: regler og fordeling, spamtjek, Noas resumé og udkast, kvittering til kunden og notifikationer. Den hører under kilden API under Opsætning → Kilder. Sætter I kilden på pause, kan API'et ikke oprette henvendelser.
Send mindst besked eller kontakt.email.
curl -X POST https://app.telenoa.com/api/v1/henvendelser \
-H "Authorization: Bearer $TELENOA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ordre-1001" \
-d '{
"emne": "Spørgsmål til ordre 1001",
"besked": "Hvornår bliver min ordre leveret?",
"kontakt": { "navn": "Anna Jensen", "email": "anna@firma.dk" },
"ekstern_id": "ORD-1001",
"felter": { "Ordrenummer": "1001" }
}'const ny = await telenoa("/henvendelser", {
metode: "POST",
idempotens: `ordre-${ordre.id}`,
krop: {
emne: `Spørgsmål til ordre ${ordre.id}`,
besked: ordre.kommentar,
kontakt: { navn: ordre.navn, email: ordre.email },
ekstern_id: String(ordre.id),
},
});felter er ekstra oplysninger som i en formular (højst 20). Noa ser dem, når hun skriver sit resumé og udkast.
Ret en henvendelse
PATCH /henvendelser/{id} — kræver henvendelser:write. Send kun de felter, der skal ændres: status, mappe, prioritet, tildelt_til, kategori_id, stjernemarkeret, vigtig og svarfrist (ÅÅÅÅ-MM-DD). null fjerner tildeling, kategori og svarfrist.
curl -X PATCH https://app.telenoa.com/api/v1/henvendelser/6f1c… \
-H "Authorization: Bearer $TELENOA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "loest" }'Ændringen står på henvendelsens tidslinje i appen med nøglens navn. Bliver en henvendelse løst, sendes tilfredshedsmålingen, hvis I har slået den til.
Svar kunden
POST /henvendelser/{id}/svar — kræver henvendelser:write.
Svaret sendes med det samme fra jeres mailkonto — den, kunden skrev til, ellers den første aktive. Det er samme afsendelse som Send på Noas udkast i appen, og svaret ligger bagefter i tråden. Tomme linjer i tekst bliver til afsnit.
curl -X POST https://app.telenoa.com/api/v1/henvendelser/6f1c…/svar \
-H "Authorization: Bearer $TELENOA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: svar-6f1c-1" \
-d '{ "tekst": "Hej Anna\n\nDin ordre bliver leveret på torsdag.\n\nVenlig hilsen\nButikken" }'Svaret er 409 med koden konflikt, hvis henvendelsen ikke har en mailadresse, eller hvis I ikke har en aktiv mailkonto under Forbindelser → Mail.
Brug altid en Idempotency-Key, når I sender svar. Så får kunden ikke den samme mail to gange, hvis jeres system prøver igen.
Kontakter
En kontakt er en kunde i jeres kundekartotek, med status: ny, i_gang, tilbud_sendt, vundet eller tabt.
List og find kontakter
GET /kontakter — kræver kontakter:read. Filtre: status, q, email, telefon, opdateret_efter, limit og cursor.
curl "https://app.telenoa.com/api/v1/kontakter?email=anna@firma.dk" \
-H "Authorization: Bearer $TELENOA_API_KEY"GET /kontakter/{id} henter én kontakt.
Opret en kontakt
POST /kontakter — kræver kontakter:write. En kontakt skal have email eller telefon. Findes der allerede en kontakt med samme mail eller telefon, får I den i stedet (200 og "oprettet": false) — så opstår der ikke dubletter.
const { kontakt, oprettet } = await telenoa("/kontakter", {
metode: "POST",
krop: { navn: "Anna Jensen", email: "anna@firma.dk", firma: "Firma ApS", status: "tilbud_sendt" },
});Ret en kontakt
PATCH /kontakter/{id} — kræver kontakter:write. Felter: navn, firma, cvr, email, telefon, adresse og status.
curl -X PATCH https://app.telenoa.com/api/v1/kontakter/91ab… \
-H "Authorization: Bearer $TELENOA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "vundet" }'Opkald
Opkald, Noa har taget på Noa Voice eller i «Tal med Noa».
GET /opkald — kræver opkald:read. Filtre: udfald (besked, booket, omstillet, ubesvaret), startet_efter, startet_foer, limit og cursor.
GET /opkald/{id} giver også udskrift: hvad kunden og Noa sagde, og hvad Noa gjorde undervejs.
curl "https://app.telenoa.com/api/v1/opkald?udfald=besked" \
-H "Authorization: Bearer $TELENOA_API_KEY"const opkald = await telenoa(`/opkald/${id}`);
console.log(opkald.resultat.titel, opkald.resume);
for (const tur of opkald.udskrift) console.log(tur.hvem, tur.tekst);Et opkald har samme id som den henvendelse, det er gemt som. Optagelser følger ikke med i API'et.
Viden til Noa
POST /viden/noter — kræver viden:write. Noten lægges i Videnbase, og Noa bruger den i mails, chat og telefon. titel højst 120 tegn, indhold højst 20.000.
curl -X POST https://app.telenoa.com/api/v1/viden/noter \
-H "Authorization: Bearer $TELENOA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "titel": "Levering i december", "indhold": "Bestillinger efter 20. december leveres først 2. januar." }'Er videnbasen fuld, svarer Telenoa 409.
Noa Voice
GET /noa/linje — kræver noa:read. Status, nummer og månedens tal.
{
"har_linje": true,
"status": "aktiv",
"nummer": "+45 35 15 37 20",
"nummer_e164": "+4535153720",
"viderestillet_fra": "+45 70 20 30 40",
"aktiveret": "2026-09-01T08:00:00.000Z",
"denne_maaned": { "opkald": 112, "minutter": 240, "klaret_af_noa": 71, "beskeder": 30, "omstillet": 11 }
}