
# Brugerdefinerede kanaler

Forbind enhver beskedplatform eller kommunikationsværktøj til platformen ved hjælp af brugerdefinerede kanaler. Dette lader dig bringe beskeder fra platforme som live chat-widgets på hjemmesider, e-mailsystemer, CRM-systemer eller enhver anden tjeneste ind i din indbakke — og svare på dem med din AI-agent.


---

## Hvad er brugerdefinerede kanaler?

Brugerdefinerede kanaler udvider platformen ud over dens indbyggede beskedplatforme ([WhatsApp](whatsapp-business.md), [SMS](sms.md), [Instagram](instagram-dms.md), [Messenger](facebook-messenger.md)). Med brugerdefinerede kanaler kan du:

- **Modtage beskeder** fra enhver ekstern platform til platformens samlede indbakke.
- **Sende svar** fra appen tilbage til din eksterne platform automatisk.
- **Bruge en AI-agent** til at svare på beskeder fra enhver kilde.
- **Spore alle samtaler** sammen med dine andre kanaler i en enkelt indbakke.

Dette er ideelt for virksomheder, der bruger specialiserede kommunikationsværktøjer, har en specialbygget platform eller ønsker alle kundebeskeder samlet ét sted.

::: note
**Bemærk:** Brugerdefinerede kanaler kræver en vis teknisk opsætning. Hvis du eller dit team ikke er trygge ved tekniske integrationer, kan det være en god idé at bede din webudvikler eller it-afdeling om hjælp til dette afsnit.
:::


---

## Hvordan det fungerer

Brugerdefinerede kanaler fungerer ved at sende beskeder frem og tilbage mellem din eksterne platform og platformen ved hjælp af **webhooks** (automatiserede beskeder sendt mellem systemer over internettet). Her er flowet:

```
Your Platform  ──(sends message to)──>  The App
                                           |
                                       AI Agent responds
                                       Contact saved
                                       Message stored
                                           |
The App  ──(sends reply to)──>  Your Platform
```

1. **Indgående beskeder:** Din eksterne platform sender beskeder til en webadresse (URL). Tænk på det som din platform, der "poster" en besked til platformens postkasse.
2. **Behandling:** Platformen opretter eller opdaterer kontakten, gemmer beskeden og får en AI-agent til at generere et svar (hvis aktiveret).
3. **Udgående beskeder:** Når platformen sender et svar (uanset om det er fra AI'en eller skrevet af dig), sender den beskeden til en URL på din platform, hvor dit system kan levere den til slutbrugeren.

---

## Opsætning af indgående beskeder (Din platform til appen)

For at sende beskeder fra din eksterne platform ind i appen, skal din platform sende data til følgende URL. Din udvikler vil genkende dette som en standard POST-anmodning (en almindelig måde for ét system at sende data til et andet over internettet).

### Hvor beskeder skal sendes hen

```
POST https://api.youraiconnector.com/v1/incoming_custom_channel_message?apiKey=YOUR_API_KEY
```

Erstat `YOUR_API_KEY` med din API-nøgle (en privat kode, der beviser over for platformen, at din platform har tilladelse til at sende den beskeder). Find eller generer den under **Indstillinger → Integrationer → API-nøgle**.

### Beskedformat

Send meddelelsesdataene i følgende format (JSON):

```json
{
  "customData": {
    "messageSid": "unique-message-id-123",
    "fromId": "user-456",
    "toId": "your-business-id",
    "body": "Hello, I have a question about your service.",
    "status": "received",
    "channel": "my-live-chat",
    "campaignId": "optional-campaign-id",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com",
    "mediaUrl": null,
    "mediaContentType": null
  },
  "messageType": "text"
}
```

**Hvad hver del betyder:**
- `messageSid` - Et unikt ID for denne specifikke meddelelse (dit system opretter dette). Bruges til at forhindre, at den samme meddelelse behandles to gange.
- `fromId` - Hvem der sendte meddelelsen (kan være et bruger-ID, en e-mail eller et telefonnummer fra dit system).
- `toId` - Din virksomheds-id (kan være en valgfri etiket).
- `body` - Selve meddelelsesteksten.
- `channel` - En etiket, du vælger for at identificere, hvor meddelelsen kom fra (f.eks. "website-chat", "email").

### Fuld feltreference

| Felt | Påkrævet? | Hvad det gør |
|---|---|---|
| `customData.messageSid` eller `customData.id` | Ja | Et unikt ID for denne besked (forhindrer dubletter) |
| `customData.fromId` | Ja | Identificerer hvem der sendte beskeden (f.eks. et bruger-ID, e-mail eller telefonnummer fra dit system) |
| `customData.toId` | Ja | Identificerer modtagersiden (din virksomhed). Kan være enhver tekst, du vælger. |
| `customData.body` | Ja | Selve beskedteksten. Må ikke være tom. |
| `customData.status` | Nej | Beskedstatus. Udelad dette for at bruge standarden (`"received"`). |
| `customData.channel` | Nej | En etiket for kilden (f.eks. `"live-chat"`, `"email"`, `"my-crm"`). Hjælper dig med at identificere, hvor beskeder kom fra i din indbakke. |
| `customData.campaignId` | Nej | Et kampagne-/Agent-ID. Brug dette til at dirigere beskeden til en specifik AI-konfiguration. |
| `customData.firstName` | Nej | Kontaktens fornavn. Inkluderes ved oprettelse af en ny kontaktpost. |
| `customData.lastName` | Nej | Kontaktens efternavn. Inkluderes ved oprettelse af en ny kontaktpost. |
| `customData.email` | Nej | Kontaktens e-mailadresse. Inkluderes ved oprettelse af en ny kontaktpost. |
| `customData.mediaUrl` | Nej | Et link til en vedhæftet fil (billede, video, lyd eller dokument). Kan også være en base64-kodet fil (se nedenfor). |
| `customData.mediaContentType` | Nej | Filtypen (f.eks. `"image/jpeg"`, `"video/mp4"`, `"audio/ogg"`, `"application/pdf"`). Påkrævet hvis du inkluderer `mediaUrl`. |
| `messageType` | Nej | Type af besked. Udelad for almindelig tekst. Sæt til `"reaction"` for emoji-reaktioner. |

### Emoji-reaktioner

Hvis din platform understøtter emoji-reaktioner (f.eks. en tommelfinger op på en besked), skal du sende dem som en reaktion i stedet for som en tekstbesked: sæt `messageType` til `"reaction"` og indsæt kun emojien i `customData.body`.

```json
{
  "messageType": "reaction",
  "customData": {
    "messageSid": "reaction-123",
    "fromId": "user-42",
    "toId": "my-business",
    "body": "👍"
  }
}
```

Assistenten behandler den derefter, som du ville forvente:

- En reaktion på et spørgsmål, som assistenten har stillet (f.eks. "Passer torsdag?"), behandles som svaret, og assistenten svarer.
- En reaktion på en afslutningsbesked (f.eks. "Vi tales ved!") afslutter samtalen stille. Der sendes intet svar.

Hvis din platform omdanner reaktioner til tekst såsom "Reagerede med: 👍", ser assistenten en almindelig tekstbesked og beslutter selv, om den skal svare. Ved at sende reaktionstypen undgår du dette.

### Hvad du får tilbage

En succesfuld anmodning returnerer:

```json
{
  "success": true,
  "messageId": "1234567890"
}
```

Hvis noget går galt, får du en fejlmeddelelse, der forklarer problemet:

```json
{
  "error": "Message body cannot be empty"
}
```

### Statuskoder

| Kode | Hvad det betyder |
|---|---|
| `200` | Succes - besked modtaget og bliver behandlet |
| `400` | Der er noget galt med din anmodning - tjek for manglende påkrævede felter eller en tom beskedtekst |
| `401` | Ugyldig API-nøgle - dobbelttjek nøglen under **Indstillinger → Integrationer → API-nøgle** |
| `405` | Forkert anmodningsmetode - sørg for, at du bruger POST, ikke GET |
| `500` | Noget gik galt på platformens side - prøv igen om et øjeblik |

> Hvis du angiver `customData.status`, er den eneste accepterede værdi `"received"` — udelad den helt for at bruge standardværdien i stedet for at sende noget andet, ellers får du en `400`.

---

## Afsendelse af vedhæftede medier (billeder, videoer, filer)

Du kan inkludere vedhæftede filer (billeder, videoer, lyd, dokumenter) i dine meddelelser. Der er to måder at gøre dette på:

### Mulighed 1: Link til en fil

Hvis filen allerede er hostet online, skal du angive URL'en (webadressen), hvor platformen kan downloade den:

```json
{
  "customData": {
    "messageSid": "msg-789",
    "fromId": "user-456",
    "toId": "business-1",
    "body": "Here is a photo of the issue.",
    "channel": "support-portal",
    "mediaUrl": "https://example.com/uploads/photo.jpg",
    "mediaContentType": "image/jpeg"
  },
  "messageType": "text"
}
```

### Mulighed 2: Indlejring af filen direkte (Base64)

Hvis filen ikke er hostet online, kan du indlejre den direkte i beskeden som kodet tekst (base64-format). Dette er almindeligt i tekniske integrationer, hvor dit system genererer filer løbende. Platformen vil automatisk afkode og gemme filen:

```json
{
  "customData": {
    "messageSid": "msg-790",
    "fromId": "user-456",
    "toId": "business-1",
    "body": "Screenshot attached.",
    "channel": "support-portal",
    "mediaUrl": "data:image/png;base64,iVBORw0KGgo...",
    "mediaContentType": "image/png"
  },
  "messageType": "text"
}
```

::: note
**Bemærk:** Vedhæftning af filer direkte gør beskeddataene meget større. For store filer er det bedre at hoste filen online og sende et link (Mulighed 1) i stedet.
:::


---

## Opsætning af udgående beskeder (platformen til din platform)

Når platformen sender et svar på en brugerdefineret kanal (uanset om det er fra AI'en eller skrevet af dig), sender den automatisk svaret til en URL på din platform, så dit system kan levere det til slutbrugeren.

> **Indstil webhook-URL'en først.** Du skal gemme webhook-URL'en for den brugerdefinerede kanal, før nogen svar kan leveres. Hvis ingen URL er gemt, genereres og gemmes svarene stadig, men de sendes aldrig ud — og de vil **ikke** vise en "Fejlet"-status, så intet i din indbakke markerer problemet. Konfigurer altid webhook-URL'en, før du går live.

### Fortæl appen, hvor svar skal sendes hen

1. Klik på **Indstillinger** nær bunden i venstre sidepanel.
2. I venstre side af Indstillinger, under **Kanaler**, skal du klikke på **Kanaler**.
3. Find kortet **Brugerdefineret kanal** nederst på siden (efter Android SMS Gateway, iMessage, chat-widgetten til hjemmesiden, Twilio-konto og Overholdelse af regler).
4. Indtast **Webhook-URL** — den URL på din platform, hvor AI'en skal sende udgående beskeder (din udvikler opsætter dette til at modtage og behandle svar). Det skal være en **offentlig HTTPS-URL** — `http://`-adresser og ikke-offentlige værter afvises.
5. Klik på **Gem**.



### Hvad platformen sender til din platform

Når platformen sender et svar, vil din platform modtage følgende data:

```json
{
  "contactId": "abc123",
  "messageId": "msg-456",
  "userId": "your-user-id",
  "body": "Thank you for your message! Here is the information you requested...",
  "toId": "user-456",
  "channel": "my-live-chat"
}
```

### Hvad hvert felt betyder

| Felt | Hvad det indeholder |
|---|---|
| `contactId` | Platformens interne ID for denne kontakt |
| `messageId` | Det unikke ID for denne besked i appen |
| `userId` | Dit bruger-ID |
| `body` | Svarteksten |
| `toId` | Kontaktens ID på din platform (dette matcher det `fromId`, du sendte i den indgående besked) |
| `channel` | Navnet på den brugerdefinerede kanal, du har tildelt |

Din platform modtager disse data og bruger dem til at levere svaret til slutbrugeren gennem dit eget system.

### Hvordan platformen sporer levering

Efter at have sendt svaret til din platform, opdaterer platformen beskedstatus:

- **Sendt** - Din platform modtog beskeden korrekt.
- **Fejlet** - Din platform returnerede en fejl eller kunne ikke nås. Platformen gemmer fejldetaljerne sammen med beskeden, så du kan foretage fejlfinding.

---

## Afsendelse af beskeder fra dit system til appen

Udover at modtage beskeder kan du også sende udgående beskeder via en brugerdefineret kanal direkte fra dit eget system. Dette er nyttigt, når du vil starte en samtale eller sende en proaktiv besked.

> **Abonnementskrav.** Afsendelse og synkronisering af beskeder via API'et kræver et abonnement, der inkluderer API-adgang og mindst én beskedkanal. Hvis du modtager en `403` "permission denied / feature not enabled"-fejl, inkluderer dit nuværende abonnement ikke dette – opgrader dit abonnement eller kontakt support.

### Hvor der skal sendes til

```
POST https://api.youraiconnector.com/v1/send_custom_channel_message?apiKey=YOUR_API_KEY
```

### Beskedformat

```json
{
  "customData": {
    "fromId": "user-456",
    "customChannel": "my-live-chat",
    "body": "Hello! How can I help you today?",
    "campaignId": "optional-campaign-id",
    "firstName": "John",
    "lastName": "Doe",
    "email": "john@example.com"
  }
}
```

### Påkrævede felter

| Felt | Hvad det gør |
|---|---|
| `customData.fromId` | Kontaktens ID på din platform |
| `customData.customChannel` | Navnet på din brugerdefinerede kanal (f.eks. "my-live-chat") |
| `customData.body` | Beskedteksten, der skal sendes |

De valgfrie felter (`campaignId`, `firstName`, `lastName`, `email`) fungerer på samme måde som ved indgående beskeder — de hjælper platformen med at oprette eller opdatere kontaktposten.

### Hvad du får tilbage

```json
{
  "success": true,
  "messageId": "generated-message-id",
  "contactId": "contact-id",
  "message": "Message sent successfully"
}
```

---

## Registrering af beskeder sendt fra et andet system

Nogle gange har du allerede sendt en besked til en kontakt fra et andet værktøj (for eksempel et workflow i en anden platform), og du vil blot have, at platformen skal vide det, så AI'en har den fulde kontekst. Dette er anderledes end at sende: platformen registrerer beskeden, men videresender den **ikke** til kontakten.

### Hvor der skal sendes til

```
POST https://api.youraiconnector.com/v1/sync_custom_channel_message?apiKey=YOUR_API_KEY
```

Inkluder `customData.fromId` (kontaktens ID på din platform) og `customData.body` (beskedteksten, der allerede er sendt).

### Hvordan det fungerer

- **Beskeden registreres, ikke videresendt.** Platformen gemmer den kun i samtalen for kontekst.
- **AI'en sættes som standard på pause for den kontakt.** Dette forhindrer botten i at svare oven i en besked, som et menneske allerede har håndteret. For at holde botten aktiv, send `customData.pauseAi: false`.
- **Nye kontakter kan oprettes automatisk.** Inkluder `customData.customChannel`, og kontakten oprettes, hvis den ikke allerede findes.
- **Dubletter ignoreres.** Hvis du genbruger det samme `messageSid`, genkender platformen, at beskeden allerede er blevet registreret, og foretager ingen ændringer.

> **Abonnementskrav.** Ligesom afsendelse kræver optagelse af beskeder via API'et et abonnement, der inkluderer API-adgang og mindst én beskedkanal. En `403` "permission denied / feature not enabled"-fejl betyder, at dit nuværende abonnement ikke inkluderer dette.

---

## Eksempler fra den virkelige verden

### Live chat på hjemmeside

Forbind en live chat-widget på din hjemmeside til platformen, så din AI-agent kan besvare spørgsmål fra besøgende:

1. En besøgende skriver en besked i din hjemmesides chat-widget.
2. Din chat-widget sender beskeden til platformen.
3. AI-agenten genererer et svar.
4. Svaret sendes tilbage til din chat-widget, som viser det til den besøgende.

**Hvorfor er dette nyttigt:** Dine besøgende på hjemmesiden får øjeblikkelige, AI-drevne svar på deres spørgsmål, uden at du behøver at være online.

### E-mail

Ruter e-mail-samtaler gennem platformen, så din AI-agent kan besvare e-mails:

1. Opsæt et system, der videresender indgående e-mails til platformen (ved at bruge e-mail-afsenderens adresse som `fromId`, e-mail-emnet og brødteksten som `body`, og `"email"` som `channel`).
2. AI-agenten læser e-mailen og genererer et svar.
3. Svaret sendes tilbage til dit e-mail-system, som sender det som et normalt e-mail-svar.

**Hvorfor dette er nyttigt:** Almindelige e-mail-spørgsmål (priser, åbningstider, tilgængelighed) bliver besvaret øjeblikkeligt af din AI-agent.

> Hvis dit e-mail-system understøtter IMAP/SMTP eller OAuth, kan den indbyggede [E-mail-kanal](email.md) være enklere end en brugerdefineret integration.

### CRM-integration

Forbind dit eksisterende CRM-system (Customer Relationship Management) til platformen:

1. Når en kundeemne sender en besked via dit CRM, videresendes den til platformen.
2. AI-agenten svarer og sporer samtalen.
3. AI-svaret sendes tilbage til dit CRM til levering.
4. Den fulde samtalelogg er tilgængelig både på platformen og i dit CRM.

**Hvorfor er dette nyttigt:** Dit salgsteam får AI-assisterede svar til leads uden at forlade deres CRM.

### Support-ticketsystem

Brug platformen som en AI-drevet førstelinjesupport til kundeservice:

1. Dit billetsystem videresender nye supportbilletter til platformen.
2. AI-agenten sender et indledende svar (f.eks. ved at anerkende billetten og stille opklarende spørgsmål).
3. Svaret vedhæftes billetten i dit supportsystem.
4. Dit supportteam kan gennemgå, hvad AI'en har skrevet, og tage over, når det er nødvendigt.

**Hvorfor er dette nyttigt:** Kunder får en øjeblikkelig bekræftelse og indledende hjælp, selv uden for åbningstiden.

---

## Fejlfinding

### Beskeder modtages ikke af platformen

- Bekræft, at din API-nøgle er korrekt og aktiv (tjek **Indstillinger → Integrationer → API-nøgle**).
- Sørg for, at du sender en POST-anmodning (ikke GET). Din udvikler vil kende forskellen.
- Tjek, at feltet `customData.body` ikke er tomt eller kun indeholder mellemrum.
- Bekræft, at feltet `customData.fromId` er inkluderet.
- Læs svarmeddelelsen for specifikke fejldetaljer.

### Svar når ikke frem til din platform

- Sørg for, at du har indtastet din platforms URL i kortet **Brugerdefineret kanal** på siden Kanaler. Hvis der ikke er gemt nogen URL, genereres og gemmes svar, men de sendes aldrig ud — og de vil **ikke** blive markeret som "Fejlet", så tjek dette først.
- Bekræft, at URL'en er offentligt tilgængelig (ikke bag et login eller en firewall) og returnerer et succes-svar.
- Kun svar (udgående beskeder) sendes til din URL — indgående beskeder udløser ikke dette.
- Tjek for fejldetaljer på beskeden i din indbakke.

### Kontakt oprettes ikke

- Sørg for, at værdien `fromId` er konsistent for den samme bruger på tværs af alle deres beskeder. Platformen bruger denne værdi til at identificere kontakter — hvis den ændrer sig mellem beskeder, opretter platformen en ny kontakt hver gang.
- Inkluder `firstName`, `lastName` og `email` i den første besked fra en ny kontakt for at oprette en komplet kontaktprofil.

### Vedhæftede filer virker ikke

- For fillinks (URL'er), sørg for, at filen er offentligt tilgængelig (intet login påkrævet for at få adgang til den).
- Inkluder altid `mediaContentType`, når du inkluderer `mediaUrl`.
- For indlejrede filer (base64), bekræft, at formatet er `data:MIME_TYPE;base64,ENCODED_DATA`.
- Sørg for, at den filtype, du angiver, matcher det faktiske filindhold.

---

## Bedste praksis

- **Brug konsistente `fromId`-værdier.** Hver bruger på din platform bør altid have den samme `fromId`. Dette sikrer, at platformen grupperer alle deres beskeder i en enkelt samtale i stedet for at oprette dublerede kontakter.
- **Vælg et klart `channel`-navn.** Vælg noget beskrivende som `"website-chat"`, `"email"` eller `"zendesk"`, så du nemt kan se, hvor beskederne kom fra, når du ser din indbakke.
- **Inkluder kontaktoplysninger** (`firstName`, `lastName`, `email`) i den første besked fra en ny kontakt. Dette skaber en komplet og nyttig kontaktprofil med det samme.
- **Indbyg logik for genforsøg.** Få din platform til at forsøge at sende beskeder igen, hvis platformen ikke svarer ved første forsøg (netværksproblemer kan forekomme).
- **Brug unikke `messageSid`-værdier** for hver besked. Dette forhindrer, at den samme besked behandles to gange, hvis dit system sender den mere end én gang.
- **Brug `campaignId`** til at rute beskeder til forskellige AI-agenter, når du har flere anvendelsesscenarier (f.eks. salgshenvendelser vs. supportspørgsmål).
- **Test før du går live.** Send testbeskeder i begge retninger og bekræft, at kontakter, samtaler og AI-svar alle fungerer korrekt, før du lancerer til rigtige brugere.
