
# 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](../integrations/api-access.md). Alt der står der, gælder også her – du godkender med din **bureaukontos** API-nøgle.

::: note
**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](../integrations/connect-ai-clients.md) 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](sub-accounts.md)) 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:

```json
{
  "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](#set-per-client-ai-pricing-and-policy) og [chat-overvågnings-slutpunkterne](#read-a-sub-accounts-conversations) følger det samme mønster.
- **Kopiering af en Agent mellem konti** — `POST /v1/subaccounts/agents/copy` navngiver begge konti direkte og tager destinationen som `targetUserId`. Se [eksemplet](#worked-example-ship-a-template-agent-into-every-new-client) herunder. (Den ældre `POST /v1/subaccounts/campaigns/copy` fungerer på samme måde, men er forældet sammen med resten af [Campaigns API](../api/campaigns.md).)
- **Justering af kreditter og de to bureau-omfattende opsamlinger** — [`POST /v1/subaccounts/credits`](#grant-or-deduct-credits-directly) identificerer underkontoen via `email` i stedet; [`GET /v1/subaccounts/credit-usage`](#read-credit-usage-and-campaign-health-across-your-book) 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](#manage-your-pricing-tiers-over-the-api) 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.

::: master-only
<figure><img src="../.gitbook/assets/v2-api-access-key-section.png" alt="API-nøgleindstillingsside med maskeret nøgle og Regenerer-kontrol"><figcaption><p>Indstillinger → Integrationer → API-nøgle — dit bureau's nøgle findes her, sammen med linket til den fulde API-reference.</p></figcaption></figure>
:::

***

## 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**

```bash
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**

```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**

```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:**

```json
{
  "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**

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

**JavaScript**

```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**

```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:**

```json
{
  "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 `pending` → `token_received` → `pages_loaded` → `connected`. 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**

```bash
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**

```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**

```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:**

```json
{
  "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):**

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

**Køb (JavaScript):**

```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):**

```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:**

```json
{
  "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`

```bash
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](../api/agents.md#copy-an-agent-into-a-sub-account-agencies).

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.

```bash
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](#set-per-client-ai-pricing-and-policy) 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:

```bash
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](../api/entry-points.md#point-a-channel-at-an-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.

```bash
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`:

```bash
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**

```bash
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**

```json
{
  "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**

```bash
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**

```json
{
  "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](#turn-tasks-daily-summaries-or-the-media-library-off-for-a-client)).

***

## 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 |

```bash
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.

```bash
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](agency-accounts.md#step-3--set-up-pricing-tiers)), 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](#the-fields-on-a-tier) og [Begrænsning af hvad der overføres](sub-accounts.md#capping-what-rolls-over).

***

## 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**

```bash
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`:

```bash
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**

```bash
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](sub-accounts.md#a-holding-reply-while-a-client-is-out-of-credits).

**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:

```bash
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`:

```bash
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](https://skool.com/dm-champions), overfører `insider-rate` din 20 % rabat på Max/Lead Finder-prisen til én klient i stedet for at anvende den på hele bureauet:

```bash
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**

```bash
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**

```bash
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**

```bash
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**

```json
{
  "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](sub-accounts.md#blocking-pausing-a-sub-account)) — 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_block` på `GET /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](../integrations/connect-ai-clients.md) 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`](#set-an-exact-team-member-limit-for-a-client).

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**

```bash
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**

```json
{
  "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**

```bash
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**

```json
{
  "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**

```bash
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**

```json
{
  "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**

```bash
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. |

```json
{
  "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**

```bash
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. |

```json
{
  "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](snapshots.md) 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:

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

Indstil det derefter som standard:

```bash
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](snapshots.md).

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

```bash
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` på `/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` på `/{itemId}` opdaterer eller fjerner et.
5. **Tag et snapshot af det.**

```bash
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](../api/reference.md).

***

## 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

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

**Svar**

```json
{
  "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](white-labeling.md), planen sælges på.

### Tilføj et niveau

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

```bash
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.

```bash
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

```bash
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](agency-accounts.md#step-3--set-up-pricing-tiers). |
| `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](sub-accounts.md#capping-what-rolls-over). |
| `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](#choose-which-channel-types-a-client-can-connect). |
| `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](white-labeling.md#up-to-three-white-labels) 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](../api/reference.md) 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

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

**Svar**

```json
{
  "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

```bash
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.

```bash
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.

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

**Svar**

```json
{
  "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`](#list-your-tiers) og [`GET /v1/agency/credit-price`](#read-the-current-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](../integrations/api-access.md) — godkendelse, basis-URL, fejl, hastighedsbegrænsninger.
- [Underkonti](sub-accounts.md) — list og administrer de konti, du kan målrette.
- [Automatisk genopladning af underkonto](sub-account-auto-recharge.md) — tildel kreditter til en underkonto via webhook + API.
- [Kampagne-API](../api/campaigns.md) — opret, opdater og kopier kampagner, inklusive den fulde feltreference.
- [Kanalforbindelses-API](../api/channels.md) — 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](snapshots.md) — hvad et snapshot fanger, og hvordan man bygger et i dashboardet.
