DM Champ Docs

API for bureauer

Som bureau kan du bruge den samme REST API, som dine kunder bruger, men dirigere individuelle anmodninger til en af dine administrerede underkonti i stedet for din egen konto. Dette giver dig mulighed for at bygge værktøjer, der onboarder en kunde fra start til slut — opretter deres kampagner, træner deres AI på en vidensbase, importerer deres kontakter, forbinder deres beskedkanaler og køber telefonnumre — alt sammen uden at logge ind på hver underkonto manuelt.

Denne side dækker kun den bureau-specifikke adfærd: hvordan man handler på vegne af en underkonto med sub_account_id-parameteren. For det grundlæggende (generering af nøgle, godkendelse, basis-URL, fejlformat, hastighedsbegrænsninger), start med guiden API-adgang. Alt der står der, gælder også her – du godkender med din bureaukontos API-nøgle.

Bemærk: Denne side er teknisk. Hvis du ikke er udvikler, bør du dele den med den person, der bygger din integration.


Hvordan “at handle på vegne af” fungerer

Som standard handler enhver API-anmodning på den konto, der ejer API-nøglen – din bureaukonto. For at handle på vegne af en administreret kundekonto i stedet, skal du tilføje den valgfrie sub_account_id-parameter til anmodningen, sat til kundens konto-id.

  • Udelad sub_account_id → anmodningen handler på din egen bureaukonto.
  • Inkluder sub_account_id → anmodningen handler på den underkonto, men kun efter platformen har bekræftet, at underkontoen rent faktisk er din.

Du godkender altid med din bureaukontos API-nøgle. Du behøver aldrig underkontoens egen nøgle, og du håndterer aldrig underkontoens legitimationsoplysninger.

Hvor den skal placeres

  • GET / DELETE-slutpunkter → send det som en forespørgselsparameter: ?sub_account_id=THE_SUB_ACCOUNT_ID (sammen med din apiKey, hvis du godkender via forespørgsel).
  • POST / PUT / PATCH-slutpunkter → inkluder det i JSON-anmodningens brødtekst som "sub_account_id": "THE_SUB_ACCOUNT_ID".
  • AI-assistenter → intet at konfigurere. MCP-serveren bærer den samme indstilling på sine læseværktøjer, så én forbindelse med din bureau-nøgle kan rapportere om enhver klient: navngiv blot klienten i din anmodning (“hvor mange kontakter har Bella’s Bistro?”). Skrivehandlinger er også tilgængelige: ethvert slutpunkt, der accepterer sub_account_id, eksponeres som et værktøj, så du kan oprette, ændre og sende på vegne af en klient fra den samme forbindelse.

Find en underkontos id

sub_account_id er klientkontoens unikke id. Du kan få listen over dine underkonti og deres id’er fra SubAccounts API-slutpunkterne (se guiden Underkonti) eller fra siden Underkonti i sidepanelet.


Ejerskab bliver altid verificeret

Når du sender et sub_account_id, tjekker platformen, at kontoen er en rigtig underkonto, og at den tilhører dit bureau. Først derefter gennemføres anmodningen.

Hvis id’et er ukendt, ikke er en underkonto eller tilhører et andet bureau, fejler anmodningen med et 404-svar:

{
  "success": false,
  "error_code": 404,
  "error": "Sub-account not found."
}

Hvorfor 404 og ikke 403? Et “forbudt”-svar ville fortælle en udenforstående, at id’et eksisterer, men ikke tilhører dem. At returnere den samme 404 for “findes ikke” og “er ikke din” betyder, at slutpunktet ikke kan bruges til at opdage, hvilke konto-id’er der tilhører andre bureauer. Betragt en 404 her som “dette er ikke en underkonto, du administrerer.”


Hvor sub_account_id understøttes

sub_account_id accepteres på stort set alle ressource-slutpunkter — ethvert kald, der opretter, læser, opdaterer eller sletter en kontos egne data. I praksis kan du klargøre og køre en underkontos fulde opsætning med din bureau-nøgle:

  • AI-opsætning — kampagner, agenter, ofte stillede spørgsmål, vidensbasekilder (web-crawl og dokumentupload), vidensbasegrupper, udsendelser, brugerdefinerede funktioner, MCP-servere
  • Kontakter & CRM — kontakter (inklusive import), lister, tags, opgaver, handler, aftaler, begivenheder
  • Kanaler & numre — forbind WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE, søg / køb / administrer telefonnumre, WhatsApp-skabeloner, kanalrutning
  • Beskeder & indhold — send beskeder, chatsessioner, chat-eksport, daglige resuméer
  • Indstillinger & integrationer — webhooks, konfiguration af chat-widget, white-label-konfiguration, BYOK SMS og andre kontoindstillinger, analyse

På alle disse er parameteren valgfri — udelad den, og kaldet vil agere på din egen bureaukonto, så én integration tjener begge formål. Kreditter og forbrug trækkes altid fra den konto, du målretter: gebyrer for en underkontos kampagner, beskeder, tags og numre belaster underkontoens saldo.

Hvor det IKKE gælder

Et par slutpunkter er på bureau-niveau eller selvhenvendte og ignorerer sub_account_id:

  • Håndtering af selve underkonti — SubAccounts-slutpunkterne (opret / list / opdater en underkonto) og BYOK-slutpunktet for forbrugsgrænser navngiver allerede underkontoen i deres egen URL-sti. Prissætnings- og politik-slutpunkterne og chat-overvågnings-slutpunkterne følger det samme mønster.
  • Kopiering af en Agent mellem kontiPOST /v1/subaccounts/agents/copy navngiver begge konti direkte og tager destinationen som targetUserId. Se eksemplet herunder. (Den ældre POST /v1/subaccounts/campaigns/copy fungerer på samme måde, men er forældet sammen med resten af Campaigns API.)
  • Justering af kreditter og de to bureau-omfattende opsamlingerPOST /v1/subaccounts/credits identificerer underkontoen via email i stedet; GET /v1/subaccounts/credit-usage og GET /v1/subaccounts/campaign-status rapporterer om alle underkonti på én gang, så der er ikke én enkelt konto at målrette.
  • Dit bureaus egen konto — API-nøglehåndtering, rapportering af bureauforbrug, teamstyring og dine prisniveauer agerer altid på din bureaukonto.
  • Webhooks for indgående beskeder — slutpunkter, som eksterne systemer poster til, er knyttet til den konto, hvis legitimationsoplysninger konfigurerede dem, så der er intet at omdirigere.

Den altid opdaterede, maskinlæsbare liste over, hvilke parametre hvert slutpunkt accepterer, findes i din API-reference i dashboardet (Indstillinger → Integrationer → API-nøgle) og OpenAPI-specifikationen på GET /v1/docs/openapi.yaml. Vi frigiver ofte API-ændringer – betragt disse som den endelige kilde til sandhed.

API-nøgleindstillingsside med maskeret nøgle og Regenerer-kontrol

Indstillinger → Integrationer → API-nøgle — dit bureau's nøgle findes her, sammen med linket til den fulde API-reference.


Arbejdseksempel: forbind Instagram & Messenger for en underkonto

Forbindelse af Instagram & Messenger er et browserbaseret flow. Du starter det med API’et, giver den returnerede samtykke-URL til klienten (eller åbner den for dem), venter på, at de godkender i deres browser, og vælger derefter hvilken side, der skal forbindes — alt imens du målretter deres underkonto med sub_account_id.

Trin 1 — Start forbindelsen

Kald forbindelses-slutpunktet med klientens sub_account_id i body’en. Der sendes ingen legitimationsoplysninger her; platformen returnerer en samtykke-URL, som klienten skal åbne i en browser, samt et engangs-korrelationstoken.

cURL

curl -X POST "https://api.dmchamp.com/v1/channels/meta/connect?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sub_account_id": "abc123def456"
  }'

JavaScript

const res = await fetch("https://api.dmchamp.com/v1/channels/meta/connect", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    sub_account_id: "abc123def456",
  }),
});

const data = await res.json();
// data.oauth_url -> open this in the client's browser

Python

import requests

res = requests.post(
    "https://api.dmchamp.com/v1/channels/meta/connect",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "sub_account_id": "abc123def456",
    },
)

data = res.json()
# data["oauth_url"] -> open this in the client's browser

Svar:

{
  "success": true,
  "oauth_url": "https://www.facebook.com/v21.0/dialog/oauth?client_id=...&state=...",
  "state_token": "8sFq2yV0kQ7m4n1pZr3tWb6cXe9hJl2aD5gK7uN0oI",
  "expires_at": "2026-06-10T12:30:00.000Z"
}

Send klienten til oauth_url i en browser for at godkende. state_token korrelerer dette forsøg og er en kortlivet hemmelighed — log den ikke. Forsøget udløber ved expires_at; hvis det udløber, skal du starte forfra.

Trin 2 — Polling indtil siderne indlæses

Når klienten har givet tilladelse, skal du polle status-endpointet (med den samme sub_account_id, denne gang som en forespørgselsparameter), indtil de forbindbare sider vises.

cURL

curl "https://api.dmchamp.com/v1/channels/meta/status?apiKey=YOUR_API_KEY&sub_account_id=abc123def456"

JavaScript

const res = await fetch(
  "https://api.dmchamp.com/v1/channels/meta/status?sub_account_id=abc123def456",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);

const data = await res.json();
// Wait until data.status === "pages_loaded", then read data.pages

Python

import requests

res = requests.get(
    "https://api.dmchamp.com/v1/channels/meta/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"sub_account_id": "abc123def456"},
)

data = res.json()
# Wait until data["status"] == "pages_loaded", then read data["pages"]

Svar:

{
  "success": true,
  "status": "pages_loaded",
  "pages": [
    {
      "id": "1098765432101234",
      "name": "Acme Studio",
      "category": "Hair Salon",
      "instagram_business_account": {
        "id": "17841400000000000",
        "username": "acme.studio"
      }
    }
  ],
  "selected_page": null
}

status-feltet bevæger sig gennem pendingtoken_receivedpages_loadedconnected. Vent på pages_loaded, før du vælger en side. To terminale fejltyper kan også opstå i stedet for at gå videre: failed og expired (klienten afviste samtykke, eller statustokenets vindue på ca. 30 minutter er udløbet) — et reason-felt er inkluderet, når en af disse opstår. Stop polling og genstart ved trin 1, hvis du ser en af dem; vent ikke på pending for evigt. Sideadgangstokens returneres aldrig.

Trin 3 — Vælg siden, der skal forbindes

Vælg et af side-id’erne fra Trin 2 og vælg det. Ved at vælge en side forbindes både Instagram og Messenger for den pågældende side. Inkluder sub_account_id i brødteksten igen.

cURL

curl -X POST "https://api.dmchamp.com/v1/channels/meta/select-page?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "page_id": "1098765432101234",
    "sub_account_id": "abc123def456"
  }'

JavaScript

const res = await fetch("https://api.dmchamp.com/v1/channels/meta/select-page", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    page_id: "1098765432101234",
    sub_account_id: "abc123def456",
  }),
});

const data = await res.json();

Python

import requests

res = requests.post(
    "https://api.dmchamp.com/v1/channels/meta/select-page",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "page_id": "1098765432101234",
        "sub_account_id": "abc123def456",
    },
)

data = res.json()

Svar:

{
  "success": true,
  "page_id": "1098765432101234",
  "instagram_business_account_id": "17841400000000000"
}

Det var det — Instagram og Messenger er nu forbundet på klientens underkonto. Du har kun angivet page_id; den underliggende legitimation løses på serveren og videregives aldrig gennem din integration.


Arbejdseksempel: køb et nummer til en underkonto

Køb af et nummer fungerer på samme måde: søg med sub_account_id i forespørgslen, og køb derefter med det i brødteksten. Kreditter trækkes fra underkontoens saldo, og nummeret tildeles underkontoen.

Søg (cURL):

curl "https://api.dmchamp.com/v1/phone-numbers/available?apiKey=YOUR_API_KEY&country_code=US&sub_account_id=abc123def456"

Køb (JavaScript):

const res = await fetch("https://api.dmchamp.com/v1/phone-numbers", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phone_number: "+14155551234",
    country_code: "US",
    display_name: "Support line",
    sub_account_id: "abc123def456",
  }),
});

const data = await res.json();

Køb (Python):

import requests

res = requests.post(
    "https://api.dmchamp.com/v1/phone-numbers",
    headers={
        "X-API-Key": "YOUR_API_KEY",
        "Content-Type": "application/json",
    },
    json={
        "phone_number": "+14155551234",
        "country_code": "US",
        "display_name": "Support line",
        "sub_account_id": "abc123def456",
    },
)

data = res.json()

Svar:

{
  "success": true,
  "phone_number": "+14155551234",
  "channel": "whatsapp",
  "whatsapp_status": "PURCHASED",
  "outgoing_status": "PURCHASED",
  "status": "PURCHASED",
  "purchase_credits": 11.5,
  "monthly_credits": 11.5
}

Nummeret klargøres i PURCHASED-tilstanden, og registrering af WhatsApp-afsender fortsætter i baggrunden. Pol GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456, indtil status når ONLINE, før du sender.


Eksempel: send en skabelon-Agent til hver ny klient

Det sædvanlige bureau-mønster er at beholde én master-Agent på din bureaukonto, indstillet præcis som du ønsker, at hver klient skal starte, og stemple en kopi af den ind i hver ny underkonto ved klargøring. Det er tre kald, og intet behøver at blive gentaget bagefter: kopien beholder sine indstillinger, indtil du ændrer dem.

Trin 1 — Kopier Agenten ind

POST /v1/subaccounts/agents/copy

curl -X POST "https://api.dmchamp.com/v1/subaccounts/agents/copy?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "YOUR_TEMPLATE_AGENT_ID",
    "targetUserId": "abc123def456",
    "newName": "Inbound Instagram Leads",
    "copyFaqs": true
  }'

Svaret indeholder den nye Agents id ved data.agent_id. FAQ’er, vidensbase og mediebibliotek følger med; kildekontoens WhatsApp-skabeloner, forbundne sociale opslag og kontakter gør bevidst ikke. Fuld feltliste findes i AI Agents API.

Bemærk, at dette slutpunkt tager targetUserId i stedet for sub_account_id — det navngiver begge konti. De to kald nedenfor bruger den normale sub_account_id-parameter.

Trin 2 — Tænd for den

Kopien ankommer altid sat på pause, så den kan ikke sende beskeder til nogen, før du giver besked. Dette er også tidspunktet til at fastlåse det AI-niveau, du ønsker, at klienten skal være på; det forbliver der, så der er ingen grund til at genanvende det efter en tidsplan.

curl -X PATCH "https://api.dmchamp.com/v1/agents/NEW_AGENT_ID/active?apiKey=YOUR_API_KEY&sub_account_id=abc123def456" \
  -H "Content-Type: application/json" \
  -d '{ "active": true }'

curl -X PUT "https://api.dmchamp.com/v1/agents/NEW_AGENT_ID?apiKey=YOUR_API_KEY&sub_account_id=abc123def456" \
  -H "Content-Type: application/json" \
  -d '{ "anthropic_model": "max" }'

For at forhindre klienten i at ændre niveauet bagefter, lås de tilladte niveauer på underkontoen i stedet for at sende værdien igen.

Trin 3 — Ret klientens kanaler mod den

Kopien ankommer heller ikke med nogen routing, så intet når den, før du gør den til svareren på de kanaler, klienten har forbundet. Ét kald pr. kanal:

curl -X PUT "https://api.dmchamp.com/v1/entry-points/channel-defaults?apiKey=YOUR_API_KEY&sub_account_id=abc123def456" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "instagram", "agent_id": "NEW_AGENT_ID" }'

Herfra bliver en førstegangsbesked fra en ukendt kontakt på den kanal automatisk opfanget af den kopierede Agent. Se Peg en kanal mod en Agent for de andre kanaler og routing pr. nummer.

Indstil klientens tidszone, når du opretter underkontoen. Send time_zone_id via POST /v1/subaccounts. Kampagnens aktive timer evalueres i underkontoens egen tidszone, så en klient, der oprettes uden en, får sin tidsplan læst i forhold til UTC — hvilket i stilhed ændrer, hvornår assistenten må svare.


Spring opsætningsguiden over for en klient, du selv konfigurerer

POST /v1/subaccounts

Som standard bliver en ny underkonto-ejer guidet gennem Opsætningsguiden, første gang vedkommende logger ind. For klienter, hvor du gør arbejdet for dem — hvor du opretter kampagnen og forbinder kanalerne, før klienten nogensinde logger ind — skal du sende guided_onboarding: false, når du opretter kontoen. De lander på dashboardet i stedet, og Opsætningsguiden-punktet er skjult i deres sidepanel.

curl -X POST "https://api.dmchamp.com/v1/subaccounts" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@example.com",
    "first_name": "Alex",
    "last_name": "Client",
    "business_name": "Client Co",
    "guided_onboarding": false,
    "usage_limits": { "monthly_credits": 500 }
  }'

Udelad feltet (eller send true), og guiden opfører sig præcis, som den altid har gjort, så eksisterende integrationer behøver ingen ændringer. For at give en klient guiden tilbage senere, skal du vise guided_onboarding-elementet igen med PUT /v1/subaccounts/{subAccountUid}/menu-visibility (herunder) — menusynlighed styrer, om guiden er tilgængelig, guided_onboarding styrer kun omdirigeringen ved første login.


Deaktiver opgaver, daglige oversigter eller mediebiblioteket for en klient

POST /v1/subaccounts

Disse tre er aktiveret for alle nye klienter, medmindre du angiver andet, og de opfører sig anderledes end alle andre funktioner i denne vejledning: de er opt-out, ikke opt-in. At udelade dem fra features er ikke nok i sig selv, fordi en ældre integrations features-liste simpelthen aldrig nævnte dem — vi kan ikke kende forskel på “bureauet har slået dette fra” og “denne liste blev skrevet, før muligheden eksisterede”.

Så angiv det direkte med feature_settings:

curl -X POST "https://api.dmchamp.com/v1/subaccounts" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@example.com",
    "first_name": "Alex",
    "last_name": "Client",
    "business_name": "Client Co",
    "feature_settings": {
      "tasks": false,
      "daily_summaries": false,
      "ai_media_library": true
    }
  }'

Hver nøgle er valgfri; alt hvad du udelader, forbliver aktiveret. Med tasks: false stopper AI’en med at oprette opgaver for den klient, og der sendes ingen “Ny opgave oprettet”-e-mails; med daily_summaries: false bliver den daglige oversigt aldrig genereret eller sendt via e-mail.

feature_settings er det eneste, der slår disse tre fra ved oprettelse. At udelade dem fra features gør intet i sig selv, uanset hvordan resten af din liste ser ud — det er bevidst, så en ældre integration ikke lydløst mister alle tre.

For at ændre noget af dette efterfølgende skal du sende den fulde features-liste til PUT /v1/subaccounts/{subAccountUid}/features — her vil tilstedeværelse på listen aktivere en funktion, og fravær vil deaktivere den.


Log dine klienter automatisk ind på deres underkonto (SSO)

POST /v1/subaccounts/{subAccountUid}/sso-link

Et enkelt kald med din bureau-API-nøgle returnerer en URL, der er klar til at blive åbnet, og som logger klienten direkte ind på deres egen underkonto — ingen login-skærm, intet adgangskodetrin, intet du skal bygge ovenpå. Åbn den i en ny fane, som en omdirigering eller i en iframe inde i dit eget produkt.

Felt Påkrævet Beskrivelse
redirect Nej In-app-side, som du ønsker, at klienten skal ende på, f.eks. "/chats" eller "/agents". Returneres som deep_link_url i svaret.
app_base_url Nej Dashboard-vært for linket. Standard er dit white-label app-domæne (eller platformens domæne, hvis du ikke har et). Skal være https.

cURL

curl -X POST "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/sso-link" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "redirect": "/chats" }'

Svar

{
  "success": true,
  "url": "https://app.yourdomain.com/auth?redirect=%2Fchats#token=eyJhbGciOi…",
  "deep_link_url": "https://app.yourdomain.com/chats",
  "expires_at": "2026-07-22T15:04:05.000Z",
  "sub_account_uid": "SUB_ACCOUNT_UID"
}

Sådan bruger du det bedst:

  • Ét hop. Åbning af url logger klienten ind og sender dem direkte til redirect-siden på dashboardet — ingen login-skærm, ingen mellemliggende side. deep_link_url angiver den samme destination for integratorer, der foretrækker at navigere til en ramme eksplicit efter login; når sessionen eksisterer, fungerer enhver dashboard-sti i den browserkontekst.
  • Opret ved behov, åbn med det samme. Linket indeholder en login-legitimationsoplysning og udløber efter cirka en time. Anmod om det på serversiden i det øjeblik, klienten klikker, og gem eller e-mail det aldrig.
  • Login-tokenet sendes i URL-fragmentet (#…), som browsere aldrig sender til servere, og det fjernes fra adresselinjen i det øjeblik, det er blevet brugt.
  • Kun dine egne underkonti. Slutpunktet afviser enhver konto, som dit bureau ikke ejer.
  • Et udløbet link viser en tydelig fejl med en sti til at prøve igen — opret et nyt.

Skjul navigationspunkter på en underkonto

PUT /v1/subaccounts/{subAccountUid}/menu-visibility

Styrer hvilke elementer i sidepanelet og indstillingerne en underkonto kan se — nyttigt, når du integrerer dashboardet og kun ønsker de overflader, som dit produkt ikke allerede dækker. Alt, der ikke er angivet, forbliver synligt; send null som hele menuVisibility-værdien for at nulstille alt til synligt. At skjule et element skjuler menupunktet — kombiner det med de funktioner, du giver underkontoen adgang til, for streng adgangsstyring.

cURL

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/menu-visibility" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "menuVisibility": {
      "side_nav": { "Dashboard": false, "Campaigns": false, "Automations": false },
      "settings_nav": { "team": false }
    }
  }'

Svar

{
  "success": true,
  "data": {
    "subAccountUid": "SUB_ACCOUNT_UID",
    "menuVisibility": {
      "side_nav": { "Dashboard": false, "Campaigns": false, "Automations": false },
      "settings_nav": { "team": false }
    }
  }
}

side_nav accepterer disse 13 nøgler, som svarer til navnene på elementerne i sidepanelet: Dashboard, DailySummaries, Chats, Contacts, Deals, Tasks, Automations, Campaigns, Appointments, Settings, Help, CreditsCounter (kreditsaldoen vist i sidepanelet) og guided_onboarding (opsætningsguiden). Tre yderligere nøgler — AiInsights, Sub Accounts og Agency Reselling — accepteres, men gør intet: de gjaldt kun for det pensionerede klassiske dashboard, så indstilling af dem har ingen effekt på dine underkonti. Manglende nøgler betyder synlig; når du selv logger ind på underkontoen, vises skjulte elementer midlertidigt, så du altid kan ændre tingene tilbage.

At skjule en side fra menuen giver aldrig adgang til den. Automations kræver, at automations-funktionen er tildelt underkontoen — sæt nøglen til true uden den, og siden vil stadig ikke blive vist. Tasks og DailySummaries fungerer omvendt: de er aktiveret for alle klienter, medmindre du slår dem fra (se Deaktiver opgaver, daglige oversigter eller mediebiblioteket for en klient).


Vælg hvilke kanaltyper en klient kan forbinde

PUT /v1/subaccounts/{subAccountUid}/features

Kontakterne for Kanaltyper, som du ser på et abonnementsniveau, er almindelige funktions-id’er, så du kan indstille dem pr. klient via API’et i stedet for fra dashboardet. Dette er et af de slutpunkter, der navngiver underkontoen i sin egen URL, så det kræver ingen sub_account_id.

Funktions-id Kanal
channel_chat_widget Chat-widget til hjemmeside
channel_whatsapp_api WhatsApp Business API
channel_whatsapp_web WhatsApp Web (QR-linket nummer)
channel_instagram Instagram
channel_messenger Facebook Messenger
channel_telegram Telegram
channel_line LINE
channel_viber Viber
channel_email E-mail-postkasse
channel_sms SMS
channel_imessage iMessage
curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/features" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "features": [
      "channels_3",
      "channel_chat_widget",
      "channel_whatsapp_web",
      "channel_instagram",
      "image_understanding",
      "contact_tagging",
      "incoming_campaigns",
      "webhooks"
    ]
  }'

Tre ting du skal have styr på:

  • Kaldet erstatter hele funktionslisten. Send alle de funktioner, klienten skal beholde, ikke kun dem, du ændrer. De samme id’er fungerer som features i POST /v1/subaccounts, når du opretter kontoen.
  • Kanaltype og kanalantal er separate begrænsninger, og begge gælder. channels_1 / channels_3 / channels_unlimited styrer hvor mange forbindelser; channel_*-id’erne styrer hvilke typer. Eksemplet ovenfor betyder “op til 3 forbindelser, og kun Chat Widget, WhatsApp Web eller Instagram”.
  • Hvis du slet ikke sender nogen channel_*-id’er, betyder det ingen kanalbegrænsning. Det er den oprindelige opførsel, hvilket er grunden til, at eksisterende klienter ikke blev påvirket, da dette blev lanceret. Send ét eller flere, og alt andet vises som låst på klientens kanalside med en opgraderingsnote i stedet for en Forbind-knap. Kanaler, som klienten allerede har forbundet, fortsætter med at fungere.

Indstilling af kanallisten på et abonnementsniveau, så enhver klient, der køber det niveau, arver den, gøres i dashboardet under dine bureau-abonnementsindstillinger. Dette slutpunkt indstiller det på én specifik underkonto.


Angiv en nøjagtig grænse for teammedlemmer for en klient

PUT /v1/subaccounts/{subAccountUid}/limits

team_seats_*-funktionerne tilbyder kun forudindstillede trin (3 / 5 / 10 / ubegrænset). For at give en klient et nøjagtigt antal teampladser — 2, 7, 15 eller hvad som helst andet — skal du i stedet indstille usage_limits.team_seats_limit. Den tilsidesætter de forudindstillede trin, og platformen håndhæver den ved hver invitation, direkte tilføjelse og accept af invitation: Når grænsen er nået, afvises yderligere invitationer på serversiden.

  • Et positivt heltal er den nøjagtige grænse.
  • 0 betyder, at teammedlemmer ikke er inkluderet — klienten kan ikke invitere nogen.
  • -1 betyder ubegrænset.
  • null rydder den brugerdefinerede grænse og falder tilbage på den team_seats_*-forudindstilling, der er på funktionslisten.

Sænkning af grænsen fjerner aldrig eksisterende teammedlemmer; det forhindrer kun, at nye tilføjes.

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/limits" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "usageLimits": { "team_seats_limit": 7 }
  }'

Du kan også indstille det ved oprettelsen: POST /v1/subaccounts accepterer usage_limits.team_seats_limit med samme semantik. For at læse den aktuelle værdi skal du hente underkontoen med GET /v1/subaccounts?email=... og se på usage_limits.team_seats_limit (fraværende/null = forudindstillingerne bestemmer). Det samme slutpunkt opdaterer også credits, monthly_credits, roll_over_to_next_month, rollover_cap_months, rollover_expiry_days og byok_monthly_limit_usd — send kun de nøgler, du ønsker at ændre.

Hvordan dette interagerer med pladsbegrænsninger i SaaS-abonnementer. Dine SaaS-abonnementer kan have deres egen tildeling af pladser (angivet i abonnementseditoren — se Teampladser i et abonnement), som anvendes automatisk, når en kunde tegner et abonnement. En grænse, du angiver via dette endpoint, tæller som en manuel tildeling: køb af et abonnement erstatter den med abonnementets egen pladstildeling (dette køb er et eksplicit valg af abonnement), men automatiske månedlige fornyelser overskriver aldrig en manuel grænse — så en engangsundtagelse, du giver en kunde, overlever deres faktureringscyklus. Rydning af den manuelle grænse med null giver feltet tilbage til abonnementet ved dets næste fornyelse.

Begræns hvad en klient tager med mellem fornyelser. To yderligere usage_limits-nøgler findes ved siden af roll_over_to_next_month. Begge accepteres også af POST /v1/subaccounts ved oprettelsen, og null rydder begge.

Nøgle Hvad den gør
rollover_cap_months Antal måneders kvote, som klienten må beholde. Et tal fra 0 til 120, brøker er tilladt (0.5 = en halv måned). Ved hver fornyelse beskæres den ubrugte saldo til højst dette antal gange den kvote, som fornyelsen giver, før de nye kreditter tilføjes; 0 overfører intet.
rollover_expiry_days Et heltal af dage, 1 til 3650. Kreditter, der forbliver ubrugte så længe, slettes ved den første fornyelse, efter de når den alder. Forbrug trækkes altid fra de ældste kreditter først, så en klient, der bruger sin kvote hver måned, mister aldrig noget.

Hvis de ikke indstilles, falder begge tilbage til klientens plan; en værdi sendt her vinder over planens. Kun tilbagevendende kreditter (den månedlige kvote og plankreditter) er underlagt dem: top-ups, automatisk genopfyldning og engangstilføjelser bliver aldrig begrænset eller udløber. Hver beskæring skrives til klientens kredithistorik som en Rollover Cap Credit Adjustment eller en Expired Credits Credit Adjustment og tæller aldrig som forbrug. Modstykkerne på planniveau er rollover_cap_months og rollover_expiry_days på et prissætningstrin — se Felterne på et trin og Begrænsning af hvad der overføres.


Indstil AI-prissætning og -politik pr. klient

PUT /v1/subaccounts/{subAccountUid}/max-tier · /ai-tiers · /max-rate · /action-pricing · /insider-rate · /locked-bot-fields · /notifications · /zero-credit-reply

Otte yderligere kontakter pr. klient, ved siden af /limits, /features og /menu-visibility ovenfor. Hver tager underkontoens uid i URL’en (ingen sub_account_id body/query-parameter — målet er allerede navngivet i stien) og er begrænset på samme måde: din agenturnøgle, og underkontoen skal tilhøre dit bureau.

Hvilke AI-modeller en klient kan bruge

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/max-tier" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'

{ "enabled": boolean } tilmelder klienten (eller framelder) Max AI-niveauet — vores infrastruktur til platformens listepris. At aktivere dette for en BYOK-klient ændrer deres AI-omkostning fra “gratis på min egen nøgle” til “opkrævet mod min kreditpulje”, så det er en bevidst beslutning pr. klient frem for en bureau-dækkende standard.

For at begrænse HVILKE niveauer en klients kampagner og agenter overhovedet må vælge fra (i stedet for blot at begrænse Max), skal du bruge ai-tiers:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/ai-tiers" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "allowed_ai_tiers": ["standard", "economy"] }'

allowed_ai_tiers er et array trukket fra standard, economy, max, mini — det ERSTATTER klientens tilladelsesliste. Send null (eller []) for at rydde begrænsningen og lade dem vælge et hvilket som helst niveau. Dette er vigtigt, fordi en underkonto, der vælger sit eget AI-niveau, bruger af din kreditpulje, så det er håndtaget til at fastlåse, hvilke modeller en forhandlerklient må køre op på din regning.

Et ventende svar, mens klienten er løbet tør for kreditter

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/zero-credit-reply" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "message": "Thanks for your message, we will get back to you shortly." }'

Når klientens saldo (eller din pulje) er tom, kan AI’en ikke svare, og kontakten hører intet. Med enabled: true får enhver kontakt, der skriver ind under nedbruddet, message én gang (maks. 500 tegn, sendt som den er på alle kanaler), og AI’en besvarer disse samtaler for alvor, når kreditterne er tilbage. enabled: false gemmer den gemte tekst til senere; enabled: false uden message fjerner indstillingen. Samme kontakt som Ventende svar når der ikke er flere kreditter i underkontoens Rediger-modal — se Et ventende svar, mens en klient er løbet tør for kreditter.

Hvad en klient betaler pr. AI-handling, og WhatsApp-gebyrtillægget

To måder at indstille din klient-vendte sats på, fra den enkleste til den mest detaljerede:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/max-rate" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "rate": 0.35 }'

rate er prisen i kreditter, som underkontoens EGEN saldo brænder pr. Max-model AI-handling — dit klient-vendte tillæg oven i det, som din pulje faktisk betaler. null rydder tilsidesættelsen tilbage til platformens listepris. Satsen skal være mindst, hvad en Max-handling koster din egen pulje (så du aldrig kan prissætte en klient under din kostpris) og højst 10 kreditter; en anmodning uden for det vindue afvises med den beregnede bundgrænse i fejlmeddelelsen.

For prissætning pr. handlingstype i stedet for én flad Max-sats, skal du bruge action-pricing:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/action-pricing" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "actionPricing": {
      "AI_MESSAGE": 0.6,
      "CHAT_SUMMARY": 0.15,
      "wa_carrier_multiplier": null
    }
  }'

actionPricing er en SAMMENFØJNING med klientens eksisterende kort — en nøgle, du ikke nævner, efterlades som den var, og null fjerner den nøgle tilbage til dens standard. De genkendte nøgler:

Nøgle Priser
AI_MESSAGE Et AI-svar
AI_TOOL_USE Et AI-værktøjskald
EVALUATION_CALL En chat-evalueringsgennemgang
INTERRUPTION_HANDLING Håndtering af en afbrydelse midt i et svar
CONTACT_TAG Et AI-tildelt kontakt-tag
CHAT_SUMMARY Et chat-resumé
wa_carrier_multiplier En tillægsmultiplikator anvendt på ethvert ikke-AI WhatsApp-gebyr, som klienten betaler: månedlig leje af nummer, leveringsgebyrer for administrerede baner og Meta/Twilio-skabelonomkostninger.

Priser pr. handling skal være et tal større end 0 og op til 10; wa_carrier_multiplier skal være mindst 1 (ingen rabat under kostpris) og op til 10. Afsendelse af en ukendt nøgle eller en værdi uden for området afviser HELE anmodningen og navngiver hver fejlbehæftet nøgle, så en slåfejl aldrig kan gemme en pris, der ikke rent faktisk bliver anvendt.

Hvis du er medlem af Champions Circle, overfører insider-rate din 20 % rabat på Max/Lead Finder-prisen til én klient i stedet for at anvende den på hele bureauet:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/insider-rate" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'

Aktivering kræver, at din egen bureaukonto rent faktisk har et Circle-medlemskab; deaktivering gør aldrig, så et tidligere medlem kan altid nedjustere en klient igen.

Lås sektioner af en klients playbook

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/locked-bot-fields" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "locked_bot_fields": ["instructions", "rules"] }'

locked_bot_fields er et array trukket fra instructions, goal, rules, personality, conclude_unless — det ERSTATTER klientens låste liste. En låst sektion afvises på serversiden, hvis selve UNDERKONTOEN forsøger at ændre den (direkte eller via API-nøgle), mens du (via sub_account_id) og klientens egen administratorvisning i dashboardet stadig kan redigere alt. Send null (eller []) for at låse alt op. Nyttigt for “done-for-you”-klienter, hvor du ejer playbooken og bliver bedømt på resultatet.

Angiv en klients notifikationspræferencer på deres vegne

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/notifications" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "notifications": {
      "settings": {
        "credit_alerts": { "enabled": true, "channels": ["email", "in_app"] },
        "new_contacts": { "enabled": false }
      }
    }
  }'

notifications erstatter hele klientens sæt af notifikationspræferencer (ikke en fletning pr. nøgle — send alle kategorier, du ønsker at beholde, svarende til hvordan underkontoens egen indstillingsside gemmer dem). Hver kategori under settings accepterer enabled (boolean) og op til tre channels fra email, in_app, webhook. Send null for at nulstille til platformens standardindstillinger.

Alle syv endpoints svarer med { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } } og bliver audit-logget med før/efter-værdien. Almindelige fejl: 403 hvis din konto ikke er Bureau/Dev, eller underkontoen ikke er din at administrere, 400 hvis det ikke er en bureau-underkonto, eller en værdi er uden for området.


Sæt en klient på pause, der har suspenderet sit abonnement

POST /v1/subaccounts/{subAccountUid}/pause · POST /v1/subaccounts/{subAccountUid}/unpause

Når en klient suspenderer sit abonnement hos dig, kan du sætte deres konto på pause i stedet for at slette den: Alt, hvad de sender, stopper øjeblikkeligt — udgående beskeder, udsendelser, AI-svar på alle kanaler — og når de logger ind, ser de en Konto sat på pause-låseskærm (med din valgfrie besked) i stedet for appen. Intet slettes eller afbrydes: agenter, kampagner, tilsluttede kanaler, kontakter og chathistorik forbliver præcis, som de er, så når pausen ophæves, fortsætter klienten præcis, hvor de slap — ingen opsætning skal gøres om.

Felt Påkrævet Beskrivelse
message Nej Vises til klienten på deres låseskærm. Udelad det for at bruge standardteksten.
reason Nej Agentur-intern note, der gemmes sammen med pausen og i revisionsloggen — vises aldrig til klienten.

cURL

curl -X POST "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/pause" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Your account is on hold — contact us to reactivate it.", "reason": "Subscription suspended per client email" }'

Svar

{
  "success": true,
  "data": {
    "subAccountUid": "SUB_ACCOUNT_UID",
    "paused": true,
    "level": "hard_blocked"
  }
}

Når klienten vender tilbage, fjerner POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (ingen brødtekst) låsen — afsendelse og AI-svar genoptages med det samme.

Værd at vide:

  • Det er den samme tilstand som dashboardets “Hard blocked”-kontakt (Blokering / Sæt underkonto på pause) — en klient, der er sat på pause via API’et, vises som blokeret i dashboardet og omvendt, og ophævelse af pausen fjerner en blokering foretaget fra begge sider. Den aktuelle tilstand kan læses fra feltet agency_blockGET /v1/subaccounts (level af "none", "soft_blocked" eller "hard_blocked").
  • Begge kald er idempotente. At sætte en klient, der allerede er på pause, på pause igen opdaterer blot beskeden, årsagen og tidsstemplet; at ophæve pausen for en aktiv klient ændrer intet.
  • Klienten får ikke automatisk besked via e-mail — mange bureauer benytter white-label, så det er op til dig at informere klienten.
  • Din egen DM Champ-fakturering forbliver uberørt. At sætte en klient på pause påvirker kun dit forhold til dem.
  • AI-assistenter kan også gøre dette: MCP-serveren eksponerer disse endpoints som værktøjerne pause_subaccount og unpause_subaccount.

Tildel eller fratræk kreditter direkte

POST /v1/subaccounts/credits

Tilføjer eller fjerner et præcist beløb af kreditter fra én underkontos saldo — API-ækvivalenten til dashboardets manuelle kreditjustering. Dette er en engangsændring af saldoen, forskellig fra de tilbagevendende monthly_credits, roll_over_to_next_month, rollover_cap_months og rollover_expiry_days-indstillinger på PUT /v1/subaccounts/{subAccountUid}/limits.

Dette er det eneste endpoint på denne side, der identificerer underkontoen via e-mail i stedet for sub_account_id.

Felt Påkrævet Beskrivelse
email Ja Underkontoens e-mail, som den findes under dit bureau.
amount Ja Antal kreditter (ikke-nul). Positivt tal tilføjer, negativt tal fratrækker.
description Nej Vises ud for justeringen i klientens kredithistorik. Standard er en generisk “Justeret af bureau via API”-linje.

cURL

curl -X POST "https://api.dmchamp.com/v1/subaccounts/credits" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "client@example.com", "amount": 500, "description": "Q3 bonus credits" }'

Svar

{
  "success": true,
  "data": {
    "email": "client@example.com",
    "previous_balance": 1200,
    "adjustment": 500,
    "new_balance": 1700
  }
}

En negativ amount, der ville bringe saldoen under nul, afvises med 400, som fortæller dig den tilgængelige saldo og hvad du forsøgte at fratrække. Hvis klienten er på sin egen Stripe-fakturering (forhandlertilstand), tæller et tilføjet beløb også som kreditter, de har købt, så det overlever deres næste månedlige nulstilling på samme måde som en rigtig top-up ville; på en standard allokeret klient behandles det som en del af deres tilbagevendende kvote i stedet. Uanset hvad er de en engangstilføjelse, så en overførselsgrænse eller en udløbsdato indstillet på kontoen (eller dens plan) beskærer dem aldrig — kun den tilbagevendende kvote og plankreditter er underlagt dem.


Læs en underkontos samtaler

GET /v1/subaccounts/{subAccountUid}/chats · GET /v1/subaccounts/{subAccountUid}/chats/{contactId}/messages

Giver dig mulighed for at opbygge en overvågnings- eller supportvisning af en klients samtaler uden at logge ind på deres konto. List først deres kontakter med en forhåndsvisning af den seneste besked, og læs derefter en kontakts fulde beskedhistorik.

List kontakter

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
Forespørgselsparameter Påkrævet Beskrivelse
pageSize Nej Kontakter pr. side. Standard 25, maksimum 50.
lastActivityAt Nej Sideringsmarkør — indsæt den forrige sides lastActivityAt for at fortsætte.
searchQuery Nej Filtrer efter kontaktnavn eller telefonnummer.

Svar

{
  "success": true,
  "data": {
    "contacts": [
      {
        "contactId": "contact456",
        "firstName": "Jamie",
        "lastName": "Lee",
        "phoneNumber": "+14155551234",
        "email": "jamie@example.com",
        "channel": "whatsapp",
        "lastActivityAt": "2026-08-30T14:22:00.000Z",
        "lastMessage": { "body": "Thanks, that fixed it!", "direction": "inbound", "timestamp": "2026-08-30T14:22:00.000Z" },
        "isBotActive": true,
        "markChatClosed": false
      }
    ],
    "subAccountName": "Client Co",
    "subAccountEmail": "client@example.com",
    "hasMore": true,
    "lastActivityAt": "2026-08-30T14:22:00.000Z"
  }
}

Kontakter er sorteret efter seneste aktivitet først. Fortsæt med at bladre med lastActivityAt, mens hasMore er true.

Læs en kontakts beskeder

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
Forespørgselsparameter Påkrævet Beskrivelse
pageSize Nej Beskeder pr. side. Standard 30, maksimum 100.
beforeTimestamp Nej Sideringsmarkør — hent beskeder ældre end dette ISO-tidsstempel.

Svar

{
  "success": true,
  "data": {
    "messages": [
      {
        "messageId": "msg789",
        "body": "Thanks, that fixed it!",
        "direction": "inbound",
        "timestamp": "2026-08-30T14:22:00.000Z",
        "status": "received",
        "channel": "whatsapp",
        "botReply": false,
        "mediaUrl": null,
        "mediaContentType": null,
        "name": "Jamie Lee",
        "role": null
      }
    ],
    "contactInfo": { "firstName": "Jamie", "lastName": "Lee", "phoneNumber": "+14155551234", "channel": "whatsapp" },
    "hasMore": false,
    "oldestTimestamp": "2026-08-30T14:22:00.000Z"
  }
}

Beskeder returneres med de nyeste først; bladre bagud gennem historikken med beforeTimestamp.


Læs kreditforbrug og kampagnesundhed på tværs af din portefølje

GET /v1/subaccounts/credit-usage · GET /v1/subaccounts/campaign-status

To dashboard-lignende opsummeringer over alle de underkonti, du administrerer, så du kan opbygge din egen bureau-rapportering i stedet for at klikke ind på hver klient én ad gangen.

Kreditforbrug

curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
Forespørgselsparameter Påkrævet Beskrivelse
from / to Ja ISO-datointerval.
subAccountId Nej Udelad for en bureau-dækkende oversigt, én række pr. underkonto. Inkluder for at skifte til detaljeret tilstand: den underkontos oversigt plus dens rå, paginerede forbrugsregistreringer.
limitCount Nej Kun detaljeret tilstand. Standard 500, maksimum 2000.
startAfterTimestamp Nej Kun detaljeret tilstand — sideringsmarkør.
{
  "success": true,
  "data": {
    "subAccounts": [
      {
        "subAccountId": "abc123def456",
        "subAccountName": "Client Co",
        "subAccountEmail": "client@example.com",
        "totalCreditsUsed": 842,
        "totalCostUsd": 3.15,
        "byReason": { "AI reply": 620, "Chat summary": 80 },
        "topCampaigns": [{ "campaignName": "Inbound Leads", "creditsUsed": 500 }]
      }
    ],
    "totals": { "totalCreditsUsed": 842, "totalCostUsd": 3.15, "totalRecords": 214 },
    "dateRange": { "from": "2026-08-01", "to": "2026-08-31" },
    "hasMore": false,
    "lastTimestamp": null
  }
}

Indsæt subAccountId, og det samme svar indeholder også records: individuelle gebyrer med amount, reason, campaignName, contactName og timestamp. En klient, der bruger sin egen BYOK-nøgle i stedet for dine kreditter, får tilbageholdt tal for omkostninger/tokens (costsRedacted: true) — det er telemetri for platformomkostninger, ikke noget, der skal vises til en forhandler.

Kampagnestatus

curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
Forespørgselsparameter Påkrævet Beskrivelse
pageSize Nej Underkonti pr. side. Standard 10, maksimum 50.
lastDocumentId Nej Sidetalsmarkør (cursor).
searchQuery Nej Filtrer efter underkontonavn eller e-mail.
{
  "success": true,
  "data": {
    "totalSubAccounts": 34,
    "subAccountsWithIssues": 3,
    "totalLiveCampaigns": 51,
    "totalPausedCampaigns": 6,
    "subAccounts": [
      {
        "userId": "abc123def456",
        "email": "client@example.com",
        "displayName": "Jamie Lee",
        "businessName": "Client Co",
        "totalCampaigns": 2,
        "liveCampaigns": 1,
        "pausedCampaigns": 1,
        "hasIssues": true,
        "issueDetails": ["1 campaign paused"],
        "lastCampaignActivity": "2026-08-29T09:00:00.000Z"
      }
    ],
    "hasMore": true,
    "lastDocumentId": "abc123def456",
    "pageSize": 20
  }
}

hasIssues / issueDetails markerer underkonti, der er værd at holde øje med — f.eks. en kampagne, der er sat på pause, eller en kampagne uden tilknyttet kanal. Brug dette til at opbygge et dashboard til sundhedstjek på tværs af hele porteføljen i stedet for at åbne hver enkelt klient for at opdage en gået i stå kampagne.

For tidsserier af beskeder og kreditaktivitet på tværs af alle klienter (en serie klar til grafer frem for et øjebliksbillede), se GET /analytics/agency-rollup i guiden til Analytics API.


Lever en klientkonto, der allerede er opsat

PUT /v1/snapshots/default · POST /v1/snapshots/{snapshotId}/apply

Et snapshot er en genanvendelig skabelon: en eller flere AI-agenter plus deres vidensbase, værktøjer og medier, taget fra din egen konto. To slutpunkter placerer det i dit klargøringsflow.

Automatisk — enhver ny klient fødes med det. Marker et snapshot som din standard én gang, og enhver konto, du opretter derefter, ankommer med det installeret. Dette dækker konti oprettet via POST /v1/subaccounts, konti du opretter i dashboardet, og konti oprettet automatisk, når en klient betaler via dit betalingslink.

Find først snapshot-id’et:

curl "https://api.dmchamp.com/v1/snapshots" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

Indstil det derefter som standard:

curl -X PUT "https://api.dmchamp.com/v1/snapshots/default" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "snapshot_id": "SNAPSHOT_ID" }'

Det er hele integrationen. Send {"snapshot_id": null} for at slå det fra igen. Du kan gøre det samme fra dashboardet ved at klikke på stjernen på siden Snapshots.

For at læse hvad der i øjeblikket er markeret med stjerne (f.eks. før et klargøringsskript beslutter, om det skal indstille en), returnerer GET /v1/snapshots/default { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } }null når intet er markeret med stjerne. GET /v1/snapshots (bruges til at finde id’et ovenfor) returnerer det samme default_snapshot_id sammen med det fulde snapshots array, så de fleste integrationer behøver kun dette ene kald. Felter for det fulde snapshot-objekt findes i guiden Snapshots.

On-demand — installer på én konto. Nyttigt til onboarding af en eksisterende klient, eller til at give en klient en ekstra skabelon senere.

curl -X POST "https://api.dmchamp.com/v1/snapshots/SNAPSHOT_ID/apply" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "sub_account_id": "SUB_ACCOUNT_UID" }'

Udelad sub_account_id, og det installeres i stedet på din egen bureaukonto. Ligesom /subaccounts-slutpunkterne navngiver disse målkontoen i stien eller brødteksten i stedet for via den omgivende sub_account_id-parameter.

Værd at vide, før du bygger videre på det:

  • Installerede agenter starter på pause. Forbind klientens kanaler først, og aktivér derefter agenten. Dette gælder for både den automatiske og on-demand-stien.
  • Klargøring fejler aldrig på grund af et snapshot. Hvis installationen ikke kan fuldføres, oprettes klientkontoen stadig og er brugbar — den ankommer bare tom, og du kan anvende snapshotet bagefter.
  • Kanaler, kalendere og OAuth-forbindelser kopieres aldrig. Hver konto forbinder sine egne. Værktøjer, der bruger en almindelig API-nøgle, fortsætter med at fungere med det samme.
  • Hvis du anvender det to gange, oprettes en kopi mere. Intet bliver overskrevet.

Byg selve skabelonen via API’et

POST /v1/snapshots · agenter, brugerdefinerede funktioner og medier via API’et

Afsnittet ovenfor distribuerer et snapshot, som nogen har bygget i dashboardet. Forfatterdelen er også eksponeret, så hele loopet — saml master-opsætningen én gang, tag et snapshot, og giv det til alle klienter — kan køres fra kode.

Delene, i den rækkefølge et provisioning-script bruger dem:

  1. Opret dine brugerdefinerede funktioner. POST /v1/custom-functions opretter en; GET /v1/custom-functions viser, hvad du har, og GET, PUT og DELETE/v1/custom-functions/{customFunctionId} læser, opdaterer og fjerner en. POST /v1/custom-functions/test tester en definition, før du gemmer den.
  2. Opret og form agenten. POST /v1/agents opretter den, PUT /v1/agents/{agentId} opdaterer den, og PATCH /v1/agents/{agentId}/active med { "active": false } holder den pauset, mens du arbejder (det samme kald med true gør den aktiv). GET /v1/agents viser dem.
  3. Giv agenten dens evner. POST /v1/agents/{agentId}/custom-functions med { "custom_function_id": "..." } tilknytter en funktion til agenten; det tilsvarende DELETE /v1/agents/{agentId}/custom-functions/{customFunctionId} fjerner den igen.
  4. Fyld mediebiblioteket. POST /v1/agents/{agentId}/media-library uploader et element (JSON med base64Data, mimeType, title, description); GET viser agentens elementer, og PATCH/DELETE/{itemId} opdaterer eller fjerner et.
  5. Tag et snapshot af det.
curl -X POST "https://api.dmchamp.com/v1/snapshots" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Master setup v1",
    "agent_ids": ["AGENT_ID"],
    "include_knowledge": true,
    "include_tools": true,
    "include_media": true
  }'

Derfra er det som i det forrige afsnit: marker det som standard, så enhver ny klient bliver oprettet med det, eller anvend det efter behov. Vedligeholdelse findes ved siden af: PATCH /v1/snapshots/{snapshotId} med { "name": "..." } omdøber et, DELETE /v1/snapshots/{snapshotId} sletter et (og fjerner markeringen som standard, hvis det var det), og GET /v1/snapshots/apply-targets viser alle konti, du kan installere i.

Agent-, brugerdefineret funktion- og medie-endpoints accepterer alle sub_account_id, så de samme kald kan også vedligeholde en agent direkte inde i en klients konto. Snapshot-kald fungerer altid på din bureaukonto — skabelonen ligger hos dig. Fuldstændige anmodnings- og svar-skemaer for alle disse findes i API-referencen.


Administrer dine prisniveauer via API’et

GET /v1/agency/pricing-tiers · POST /v1/agency/pricing-tiers · PATCH /v1/agency/pricing-tiers/{tierIndex} · DELETE /v1/agency/pricing-tiers/{tierIndex}

De planer, du sælger i SaaS-tilstand → Prisniveauer, kan læses og ændres fra kode, så dit eget admin-panel eller provisioning-script kan tilføje en plan, justere en pris eller udlevere et checkout-link, uden at nogen behøver at åbne dashboardet. Autentificer med din bureau-API-nøgle ligesom ved alle andre kald på denne side; disse slutpunkter er på bureau-niveau, så de kræver ingen sub_account_id. Hver skrivehandling kører den samme validering og den samme Stripe-produkt-og-pris-synkronisering som lagring i dashboardet, så en plan, der er oprettet her, er ikke til at skelne fra en, du har oprettet manuelt.

List dine niveauer

curl "https://api.dmchamp.com/v1/agency/pricing-tiers" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

Svar

{
  "success": true,
  "data": {
    "tiers": [
      {
        "tierIndex": 0,
        "credits": 1000,
        "price_cents": 2900,
        "currency": "usd",
        "label": "Starter",
        "billing_interval": "month",
        "trial_days": 14,
        "trial_credits": 250,
        "trial_card_required": false,
        "trial_hard_expiry": true,
        "stripe_price_id": "price_1PxAbC…",
        "stripe_product_id": "prod_QxAbC…",
        "checkout_url": "https://app.yourdomain.com/v1/checkout?id=YOUR_AGENCY_UID&tierIndex=0"
      }
    ],
    "count": 1,
    "max_tiers": 20
  }
}

Hvert niveau returneres med sit tierIndex — dets position på din liste over planer, hvilket er måden, de tre andre kald adresserer det på — og et checkout_url, der er klar til deling. Det er det samme link, som fanen Betalinger giver dig, og som allerede peger på det white label-domæne, planen sælges på.

Tilføj et niveau

Brødteksten er ét niveau-objekt; det tilføjes til slutningen af din liste.

curl -X POST "https://api.dmchamp.com/v1/agency/pricing-tiers" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Starter",
    "credits": 1000,
    "price_cents": 2900,
    "currency": "usd",
    "billing_interval": "month",
    "trial_days": 14,
    "trial_credits": 250,
    "trial_card_required": false,
    "trial_hard_expiry": true,
    "features": ["channels_3", "channel_whatsapp_web", "webhooks"]
  }'

Svaret indeholder det oprettede niveau, inklusive det tierIndex, det landede på, og dets checkout_url.

Rediger et niveau

Send kun de felter, du ønsker at ændre; alt andet på planen forbliver, som det var.

curl -X PATCH "https://api.dmchamp.com/v1/agency/pricing-tiers/0" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "price_cents": 3900, "trial_hard_expiry": true }'

Et felt, som API’et ikke genkender, afvises i stedet for at blive ignoreret, og fejlen navngiver det — så en slåfejl kan aldrig i stilhed skrive en indstilling, der ser aktiv ud, men ikke gør noget. Ændring af prisen, kreditterne, valutaen eller faktureringsfrekvensen opretter en ny pris i din Stripe; kunder, der allerede har abonneret, bliver på det, de tilmeldte sig.

Slet et niveau

curl -X DELETE "https://api.dmchamp.com/v1/agency/pricing-tiers/2" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

Samme regel som i dashboardet: en plan, der stadig har aktive abonnenter, kan ikke slettes. Anmodningen returneres som afvist med besked om, hvor mange abonnenter der er på den — annuller eller migrer dem først. En vellykket sletning svarer med dine resterende niveauer, som allerede er omnummereret.

Felterne på et niveau

Felt Hvad det er
label / description Planens navn og den valgfrie linje, der vises på din betalingsside.
credits Kreditter klienten får pr. måned på en månedlig eller årlig plan, og pr. faktureringsperiode på en ugentlig.
price_cents Pris pr. faktureringsinterval i den mindste valutaenhed (2900 = $29.00). På en årlig plan er dette prisen for hele året.
currency ISO-kode med små bogstaver — usd, eur, gbp og så videre.
billing_interval / billing_interval_count month (standard), year eller week med et antal på 1–52 for “hver N. uge”.
trial_days Gratis prøveperiode, 0 til 90. 0 (eller at udelade den) betyder ingen prøveperiode.
trial_credits Kreditter klienten starter prøveperioden med. Standard er planens credits.
trial_card_required false lader klienten starte prøveperioden uden at indtaste et kort. Standard er true.
trial_hard_expiry true returnerer ubrugte prøvekreditter til din pulje og låser klientens konto, når en prøveperiode slutter uden en opgradering. Standard er false — se Hård udløb efter prøveperiode.
rollover_cap_months Antal måneders kvote, som klienter på denne plan må overføre mellem fornyelser — et tal fra 0 til 120, brøker er tilladt. 0 overfører intet; null (standard) betyder ingen grænse. Se Begrænsning af hvad der overføres.
rollover_expiry_days Dage efter hvilke ubrugte kreditter slettes ved næste fornyelse — et heltal fra 1 til 3650. null (standard) betyder, at de aldrig udløber.
features / feature_settings Hvad klienter på denne plan får — de samme funktions-ID’er som Vælg hvilke kanaltyper en klient kan forbinde.
team_seats_limit Teampladser planen giver: et præcist antal, 0 for ingen, -1 for ubegrænset.
white_label_config Hvilket af dine white label-domæner planen sælges på.

Felterne for prøveperiode betyder kun noget for en plan, der har en prøveperiode: gem et niveau med trial_days: 0, og de fjernes. Planens Stripe-produkt- og pris-id’er administreres for dig og kan ikke indstilles manuelt.

Tre ting du skal have styr på:

  • Niveauindekser er positioner, ikke permanente id’er. Sletning af en plan flytter alle efterfølgende planer ét trin ned, så hent listen igen efter enhver ændring — og kopier de betalingslinks, du har offentliggjort, på samme måde som du ville gøre efter at have slettet en plan i kontrolpanelet.
  • SaaS-tilstand skal konfigureres først. Disse slutpunkter kræver en bureaukonto med white labeling og en Stripe-nøgle, der allerede er gemt; uden en sådan findes der ingen Stripe-konto, som planens produkt og pris kan tilknyttes.
  • Tyve planer er maksimumgrænsen, det samme som i kontrolpanelet. Feltet max_tiers i listesvaret angiver den aktuelle grænse.

Fuldstændige anmodnings- og svar-skemaer findes i API-referencen under Bureau.


Angiv din pris pr. kredit via API’et

GET /v1/agency/credit-price · PATCH /v1/agency/credit-price

Den pris, som kunder betaler for ad-hoc-opfyldninger (SaaS-tilstand → Prissætning pr. kredit), kan også læses og ændres via kode. Dette er bygget til situationer, hvor prisen skal kunne justeres automatisk: et bureau, der sælger kreditter i én valuta, men fakturerer i en anden, kan lade et planlagt job revidere prisen, efterhånden som valutakursen ændrer sig, i stedet for at nogen skal redigere den manuelt hver uge.

Læs den aktuelle pris

curl "https://api.dmchamp.com/v1/agency/credit-price" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY"

Svar

{
  "success": true,
  "data": {
    "price_per_credit_cents": 125,
    "price_per_credit_currency": "brl",
    "note": "USD 0.25 per credit at our reference rate",
    "minimum_cents": 60
  }
}

minimum_cents er den laveste pris, som platformen tillader i den pågældende valuta, så et job kan kontrollere en ny pris, før den sendes. Alle tre værdier er null, indtil en pris er blevet angivet.

Skift den

curl -X PATCH "https://api.dmchamp.com/v1/agency/credit-price" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "price_per_credit_cents": 130, "currency": "brl" }'

Send kun det, du ønsker at ændre. price_per_credit_cents er prisen i den mindste valutaenhed (130 = R$1,30); currency er en ISO-kode med små bogstaver; note er en valgfri linje på op til 200 tegn, der vises til kunder direkte under prisen pr. kredit på deres faktureringsside – praktisk til en referencepris i en anden valuta, såsom “USD 0,25 pr. kredit til vores referencekurs”. Send "note": "" for at fjerne den. Svaret har samme form som læsningen ovenfor, så et job kan sammenligne og springe skrivningen over, når intet er ændret.

De samme regler gælder som i dashboardet: prisen kan ikke komme under platformens minimum for den pågældende valuta, og kontoen skal have white labeling. I modsætning til slutpunkterne for prisniveauer kræves der ingen Stripe-nøgle for at læse eller ændre denne værdi.

Giv et job en nøgle, der ikke kan andet

At indsætte din fulde bureau-nøgle i en planlægger giver mere adgang, end en prisopdatering kræver. Opret i stedet en begrænset nøgle (scoped key), der er begrænset til området Agency Credit Price: denne nøgle kan læse og ændre prisen pr. kredit og intet andet — den kan ikke røre underkonti, planer, kreditter eller din Stripe-forbindelse.

curl -X POST "https://api.dmchamp.com/v1/api-keys" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "label": "FX price updater", "scopes": { "read_only": false, "tags": ["Agency Credit Price"] } }'

Svaret indeholder den nye nøgle i api_key én gang — den vises aldrig igen, så gem den med det samme. Indstil "read_only": true for en nøgle, der kun skal læse prisen, og tilføj "expires_at" (en ISO-dato), hvis du vil have den til at ophøre med at fungere automatisk. Kun kontoejerens nøgle kan oprette begrænsede nøgler; list eller tilbagekald dem med GET /v1/api-keys og DELETE /v1/api-keys/{id}.


Lad en underkonto læse din prissætning

GET /v1/subaccounts/agency-pricing

Alle andre slutpunkter på denne side kaldes med din bureau-nøgle, eventuelt målrettet en klient via sub_account_id. Dette er det modsatte: det kaldes med underkontoens egen API-nøgle, uden sub_account_id, så en klients egen side til påfyldning (eller en integration, du bygger til dem) kan vise, hvad du opkræver dem, uden nogensinde at se din bureau-konto.

curl "https://api.dmchamp.com/v1/subaccounts/agency-pricing" \
  -H "X-API-Key: THE_SUB_ACCOUNTS_OWN_API_KEY"

Svar

{
  "success": true,
  "data": {
    "tiers": [{ "credits": 1000, "price_cents": 2900, "currency": "usd" }],
    "price_per_credit_cents": 125,
    "price_per_credit_currency": "brl",
    "price_per_credit_note": "USD 0.25 per credit at our reference rate",
    "agency_display_name": "Client Co's Growth Partner"
  }
}

Dette afspejler præcis, hvad GET /v1/agency/pricing-tiers og GET /v1/agency/credit-price returnerer til dig som bureau, minus alt det, klienten ikke behøver at se (Stripe-id’er, max_tiers, osv.). Det virker kun for en konto, der rent faktisk er en underkonto med et tilknyttet bureau — hvis du kalder det fra din egen bureau-konto, returneres en tilladelsesfejl.


Ting du skal være opmærksom på

  • Brug din bureau-nøgle. Godkend hvert kald med din bureau-kontos API-nøgle — ikke underkontoens. sub_account_id-parameteren er det, der omdirigerer handlingen.
  • Kreditter trækkes fra underkontoen. Køb og tilbagevendende gebyrer trækkes fra den målrettede underkontos kreditbalance, ikke din egen.
  • En 404 betyder “ikke din underkonto”. Dobbelttjek id’et og at kontoen er en, du administrerer.
  • Parameteren er valgfri, hvor den accepteres. Udelad den, og det samme slutpunkt vil agere på din bureau-konto, så du kan genbruge én integration til begge dele.

Relateret

  • API-adgang — godkendelse, basis-URL, fejl, hastighedsbegrænsninger.
  • Underkonti — list og administrer de konti, du kan målrette.
  • Automatisk genopladning af underkonto — tildel kreditter til en underkonto via webhook + API.
  • Kampagne-API — opret, opdater og kopier kampagner, inklusive den fulde feltreference.
  • Kanalforbindelses-API — forbind en klients kanaler og rut dem til en kampagne.
  • Guide til Analytics API (i API-sektionen) — bureauets underkonto-rollup og alle andre rapporteringsslutpunkter.
  • Snapshots — hvad et snapshot fanger, og hvordan man bygger et i dashboardet.