
# API för byråer

Som byrå kan du använda samma REST-API som dina klienter använder, men rikta enskilda förfrågningar mot ett av dina hanterade **underkonton** istället för ditt eget konto. Detta låter dig bygga verktyg som onboardar en klient från början till slut — skapa deras kampanjer, träna deras AI på en kunskapsbas, importera deras kontakter, ansluta deras meddelandekanaler och köpa telefonnummer — allt utan att logga in i varje underkonto manuellt.

Denna sida täcker endast det byråspecifika beteendet: hur man agerar å ett underkontos vägnar med parametern `sub_account_id`. För grunderna (generering av nyckel, autentisering, bas-URL, felformat, hastighetsbegränsningar), börja med guiden [API-åtkomst](../integrations/api-access.md). Allt där gäller även här – du autentiserar dig med **ditt byråkontos** API-nyckel.

::: note
**Observera:** Den här sidan är teknisk. Om du inte är utvecklare, dela den med personen som bygger din integration.
:::


***

## Hur "agera å någons vägnar" fungerar

Som standard agerar varje API-förfrågan på kontot som äger API-nyckeln – ditt byråkonto. För att istället agera på ett hanterat kundkonto, lägg till den valfria parametern `sub_account_id` i förfrågan, inställd på kundens konto-id.

- **Utelämna `sub_account_id`** → förfrågan agerar på ditt eget byråkonto.
- **Inkludera `sub_account_id`** → förfrågan agerar på det underkontot, men först efter att plattformen bekräftat att underkontot faktiskt tillhör dig.

Du autentiserar dig alltid med **ditt byråkontos** API-nyckel. Du behöver aldrig underkontots egen nyckel, och du hanterar aldrig underkontots inloggningsuppgifter.

### Var den ska placeras

- **GET / DELETE-slutpunkter** → skicka det som en frågeparameter: `?sub_account_id=THE_SUB_ACCOUNT_ID` (tillsammans med din `apiKey`, om du autentiserar via fråga).
- **POST / PUT / PATCH-slutpunkter** → inkludera det i JSON-förfrågekroppen som `"sub_account_id": "THE_SUB_ACCOUNT_ID"`.
- **AI-assistenter** → inget att konfigurera. [MCP-servern](../integrations/connect-ai-clients.md) har samma inställning för sina läsverktyg, så en anslutning med din byrånivånyckel kan rapportera om varje klient: namnge bara klienten i din förfrågan ("hur många kontakter har Bella's Bistro?"). Skrivåtgärder är också tillgängliga: varje slutpunkt som accepterar `sub_account_id` exponeras som ett verktyg, så att du kan skapa, ändra och skicka för en klients räkning från samma anslutning.

### Hitta ett underkontos id

`sub_account_id` är klientkontots unika id. Du kan hämta listan över dina underkonton och deras id:n från API-slutpunkterna för **SubAccounts** (se guiden [Sub-Accounts](sub-accounts.md)) eller från sidan **Sub Accounts** i sidofältet.

***

## Ägarskap verifieras alltid

När du skickar med ett `sub_account_id` kontrollerar plattformen att kontot är ett riktigt underkonto **och** att det tillhör din byrå. Först då går förfrågan igenom.

Om id:t är okänt, inte är ett underkonto eller tillhör en annan byrå, misslyckas förfrågan med ett **`404`**-svar:

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

> **Varför 404 och inte 403?** Ett "forbidden"-svar skulle tala om för en utomstående att id:t existerar men inte tillhör dem. Att returnera samma `404` för "finns inte" och "är inte ditt" innebär att slutpunkten inte kan användas för att upptäcka vilka konto-id:n som tillhör andra byråer. Betrakta ett `404` här som "detta är inte ett underkonto som du hanterar."

***

## Var `sub_account_id` stöds

`sub_account_id` accepteras på i princip varje **resursslutpunkt** — alla anrop som skapar, läser, uppdaterar eller tar bort ett kontos egen data. I praktiken kan du etablera och köra hela konfigurationen för ett underkonto med din byrånivånyckel:

- **AI-konfiguration** — kampanjer, agenter, FAQ:er, kunskapsbaskällor (webbgenomsökning **och** dokumentuppladdning), kunskapsbasgrupper, sändningar, anpassade funktioner, MCP-servrar
- **Kontakter & CRM** — kontakter (inklusive import), listor, taggar, uppgifter, affärer, möten, händelser
- **Kanaler & nummer** — anslut WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE, sök / köp / hantera telefonnummer, WhatsApp-mallar, kanaldirigering
- **Meddelanden & innehåll** — skicka meddelanden, chattsessioner, chattexporter, dagliga sammanfattningar
- **Inställningar & integrationer** — webhooks, konfiguration av chattwidget, white-label-konfiguration, BYOK SMS och andra kontoinställningar, analys

För var och en av dessa är parametern **valfri** — utelämna den så agerar anropet på ditt eget byråkonto, så att en integration fungerar för båda. Krediter och användning dras alltid från det konto du riktar dig mot: avgifter för ett underkontos kampanjer, meddelanden, taggar och nummer belastar **underkontots** saldo.

### Var det INTE gäller

Ett fåtal slutpunkter är på byrånivå eller självriktade och ignorerar `sub_account_id`:

- **Hantera själva underkontona** — SubAccounts-slutpunkterna (skapa / lista / uppdatera ett underkonto) och slutpunkten för BYOK-utgiftsgräns namnger redan underkontot i sin egen URL-sökväg. [Slutpunkterna för prissättning och policy](#set-per-client-ai-pricing-and-policy) och [slutpunkterna för chattövervakning](#read-a-sub-accounts-conversations) följer samma mönster.
- **Kopiera en agent mellan konton** — `POST /v1/subaccounts/agents/copy` namnger båda kontona, där målet anges som `targetUserId`. Se [exemplet](#worked-example-ship-a-template-agent-into-every-new-client) nedan. (Den äldre `POST /v1/subaccounts/campaigns/copy` fungerar på samma sätt men är utfasad tillsammans med resten av [Campaigns API](../api/campaigns.md).)
- **Justera krediter och de två byråövergripande sammanställningarna** — [`POST /v1/subaccounts/credits`](#grant-or-deduct-credits-directly) identifierar underkontot med `email` istället; [`GET /v1/subaccounts/credit-usage`](#read-credit-usage-and-campaign-health-across-your-book) och `GET /v1/subaccounts/campaign-status` rapporterar om varje underkonto samtidigt, så det finns inget enskilt konto att rikta sig mot.
- **Din byrås eget konto** — API-nyckelhantering, rapportering av byråanvändning, teamhantering och dina [prisnivåer](#manage-your-pricing-tiers-over-the-api) agerar alltid på ditt byråkonto.
- **Webhooks för inkommande meddelanden** — slutpunkter som externa system postar *till* är kopplade till det konto vars autentiseringsuppgifter konfigurerade dem, så det finns inget att omdirigera.

> Den alltid aktuella, maskinläsbara listan över vilka parametrar varje slutpunkt accepterar finns i din API-referens i kontrollpanelen (**Settings → Integrations → API Key**) och i OpenAPI-specifikationen på `GET /v1/docs/openapi.yaml`. Vi lanserar ofta API-ändringar – betrakta dessa som den primära källan till information.

::: master-only
<figure><img src="../.gitbook/assets/v2-api-access-key-section.png" alt="API-nyckelinställningssida med maskerad nyckel och kontroll för att återskapa"><figcaption><p>Inställningar → Integrationer → API-nyckel — din byrås nyckel finns här, tillsammans med länken till den fullständiga API-referensen.</p></figcaption></figure>
:::

***

## Arbetsexempel: anslut Instagram & Messenger för ett underkonto

Att ansluta Instagram & Messenger är ett webbläsarbaserat flöde. Du startar det med API:et, ger den returnerade samtyckes-URL:en till klienten (eller öppnar den åt dem), väntar på att de auktoriserar i sin webbläsare, och väljer sedan vilken sida som ska anslutas — allt medan du riktar in dig på deras underkonto med `sub_account_id`.

### Steg 1 — Starta anslutningen

Anropa anslutningsslutpunkten med klientens `sub_account_id` i body. Inga inloggningsuppgifter skickas här; plattformen returnerar en samtyckes-URL som klienten måste öppna i en webbläsare, plus en engångs-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"
}
```

Skicka klienten till `oauth_url` i en webbläsare för att auktorisera. `state_token` korrelerar detta försök och är en kortlivad hemlighet — logga den inte. Försöket löper ut vid `expires_at`; om det går ut, börja om.

### Steg 2 — Polla tills sidorna laddas

När klienten har godkänt, avläs status-slutpunkten (med samma `sub_account_id`, denna gång som en frågeparameter) tills de anslutningsbara sidorna visas.

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

Fältet `status` rör sig genom `pending` → `token_received` → `pages_loaded` → `connected`. Vänta på `pages_loaded` innan du väljer en sida. Två terminala feltillstånd kan också visas istället för att gå vidare: `failed` och `expired` (klienten nekade samtycke, eller så har tillståndstokenens fönster på cirka 30 minuter löpt ut) — ett `reason`-fält inkluderas när något av dessa inträffar. Sluta polla och starta om från steg 1 om du ser något av dem; vänta inte på `pending` för evigt. Sidåtkomsttoken returneras aldrig.

### Steg 3 — Välj sidan som ska anslutas

Välj ett av sid-ID:na från steg 2 och välj det. Att välja en sida ansluter både Instagram och Messenger för den sidan. Inkludera `sub_account_id` i brödtexten 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 allt — Instagram och Messenger är nu anslutna till klientens underkonto. Du har endast angett `page_id`; den underliggande autentiseringsuppgiften löses på servern och skickas aldrig genom din integration.

***

## Arbetsexempel: köp ett nummer för ett underkonto

Att köpa ett nummer fungerar på samma sätt: sök med `sub_account_id` i frågan och köp sedan med det i brödtexten. Krediter dras från **underkontots** saldo och numret tillhandahålls på underkontot.

**Sök (cURL):**

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

**Köp (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öp (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
}
```

Numret tillhandahålls i tillståndet `PURCHASED` och registreringen av WhatsApp-avsändare fortsätter i bakgrunden. Polla `GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456` tills statusen når `ONLINE` innan du skickar.

***

## Exempel: distribuera en mallagent till varje ny kund

Det vanliga byråmönstret är att behålla en huvudagent på ditt byråkonto, inställd på det sätt du vill att varje kund ska börja, och stämpla en kopia av den till varje nytt underkonto vid provisioneringstillfället. Det är tre anrop, och ingenting behöver upprepas efteråt: kopian behåller sina inställningar tills du ändrar dem.

### Steg 1 — Kopiera in agenten

`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 innehåller den nya agentens id vid `data.agent_id`. FAQ, kunskapsdatabas och mediebibliotek följer med; källkontots WhatsApp-mallar, anslutna sociala inlägg och kontakter följer avsiktligt inte med. Fullständig fältlista finns i [AI Agents API](../api/agents.md#copy-an-agent-into-a-sub-account-agencies).

Observera att denna slutpunkt tar `targetUserId` istället för `sub_account_id` — den namnger båda kontona själv. De två anropen nedan använder den vanliga parametern `sub_account_id`.

### Steg 2 — Slå på den

Kopian anländer alltid pausad, så den kan inte skicka meddelanden till någon förrän du säger till. Detta är också rätt tillfälle att låsa den AI-nivå du vill att kunden ska ha; den stannar där, så det finns inget behov av att tillämpa den enligt ett schema.

```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" }'
```

För att förhindra att kunden ändrar nivån efteråt, [lås de tillåtna nivåerna](#set-per-client-ai-pricing-and-policy) på underkontot istället för att skicka värdet igen.

### Steg 3 — Peka klientens kanaler mot den

Kopian anländer inte heller med någon routning, så ingenting når den förrän du gör den till svarare på de kanaler som kunden har anslutit. Ett anrop per 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" }'
```

Härifrån plockas ett första meddelande från en okänd kontakt på den kanalen upp automatiskt av den kopierade agenten. Se [Peka en kanal mot en agent](../api/entry-points.md#point-a-channel-at-an-agent) för de andra kanalerna och routning per nummer.

> **Ställ in klientens tidszon när du skapar underkontot.** Skicka `time_zone_id` via `POST /v1/subaccounts`. Kampanjens aktiva timmar utvärderas i underkontots egen tidszon, så en klient som skapas utan en sådan får sitt schema läst mot UTC — vilket tyst ändrar när assistenten tillåts svara.

***

## Hoppa över konfigurationsguiden för en klient du konfigurerar själv

`POST /v1/subaccounts`

Som standard guidas en ny underkontoägare genom den guidade konfigurationsguiden första gången de loggar in. För klienter där du gör jobbet åt dem — där du bygger kampanjen och ansluter kanalerna innan klienten ens loggar in — skicka med `guided_onboarding: false` när du skapar kontot. De hamnar på instrumentpanelen istället, och posten **Konfigurationsguide** döljs i deras sidofält.

```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 }
  }'
```

Utelämna fältet (eller skicka `true`) så beter sig guiden exakt som den alltid har gjort, så befintliga integrationer behöver inte ändras. För att ge en klient guiden tillbaka senare, visa `guided_onboarding`-objektet igen med `PUT /v1/subaccounts/{subAccountUid}/menu-visibility` (nedan) — menyvisning styr om guiden är nåbar, `guided_onboarding` styr endast omdirigeringen vid första inloggningen.

***

## Inaktivera uppgifter, dagliga sammanfattningar eller mediebiblioteket för en klient

`POST /v1/subaccounts`

Dessa tre är aktiverade för varje ny klient om du inte anger annat, och de fungerar annorlunda än alla andra funktioner i den här guiden: de är **opt-out**, inte opt-in. Att utelämna dem från `features` räcker inte i sig, eftersom en äldre integrations `features`-lista helt enkelt aldrig nämnde dem — vi kan inte avgöra om "byrån stängde av detta" eller om "den här listan skrevs innan alternativet existerade".

Så ange det uttryckligen 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
    }
  }'
```

Varje nyckel är valfri; allt du utelämnar förblir aktiverat. Med `tasks: false` slutar AI:n att skapa uppgifter för den klienten och inga "Ny uppgift skapad"-e-postmeddelanden skickas ut; med `daily_summaries: false` genereras eller e-postas aldrig den nattliga sammanfattningen.

`feature_settings` är det enda som stänger av dessa tre vid skapandet. Att utelämna dem från `features` gör ingenting i sig, oavsett hur resten av din lista ser ut — det är avsiktligt, så att en äldre integration inte tyst förlorar alla tre.

För att ändra något av detta i efterhand, skicka hela `features`-listan till `PUT /v1/subaccounts/{subAccountUid}/features` — där aktiverar närvaro i listan en funktion och frånvaro inaktiverar den.

***

## Logga in dina klienter automatiskt i deras underkonto (SSO)

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

Ett anrop med din byrå-API-nyckel returnerar en URL som är redo att öppnas och som loggar in klienten direkt i deras eget underkonto – ingen inloggningsskärm, inget lösenordssteg, ingenting att bygga ovanpå. Öppna den i en ny flik, via en omdirigering eller i en iframe inuti din egen produkt.

| Fält | Krävs | Beskrivning |
|---|---|---|
| `redirect` | Nej | Sidan i appen som du vill att klienten ska hamna på, t.ex. `"/chats"` eller `"/agents"`. Returneras som `deep_link_url` i svaret. |
| `app_base_url` | Nej | Dashboard-värd för länken. Standardvärdet är din white-label-appdomän (eller plattformsdomänen om du inte har någon). Måste vara `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"
}
```

Hur du använder det på bästa sätt:

- **Ett hopp.** Genom att öppna `url` loggas klienten in och hamnar direkt på `redirect`-sidan i instrumentpanelen – ingen inloggningsskärm, ingen mellanliggande sida. `deep_link_url` anger samma destination för integratörer som föredrar att navigera till en ram explicit efter inloggning; när sessionen väl existerar fungerar vilken sökväg som helst i instrumentpanelen i den webbläsarkontexten.
- **Skapa vid behov, öppna omedelbart.** Länken innehåller en inloggningsuppgift och upphör att gälla efter ungefär en timme. Begär den på serversidan i det ögonblick klienten klickar, och lagra eller e-posta den aldrig.
- Inloggningstoken färdas i URL-fragmentet (`#…`), vilket webbläsare aldrig skickar till servrar, och den tas bort från adressfältet så fort den har förbrukats.
- **Endast dina egna underkonton.** Slutpunkten nekar alla konton som din byrå inte äger.
- En utgången länk visar ett tydligt felmeddelande med en sökväg för att försöka igen – skapa en ny.

***

## Dölj navigeringsalternativ på ett underkonto

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

Kontrollerar vilka sidofälts- och inställningsobjekt ett underkonto ser – användbart när du bäddar in instrumentpanelen och bara vill visa de ytor som din produkt inte redan täcker. Allt som inte listas förblir synligt; skicka `null` som hela `menuVisibility`-värdet för att återställa allt till synligt. Att dölja ett objekt döljer menyalternativet – kombinera det med de funktioner du ger underkontot för strikt begränsning.

**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` accepterar dessa 13 nycklar, vilka matchar namnen på objekten i sidofältet: `Dashboard`, `DailySummaries`, `Chats`, `Contacts`, `Deals`, `Tasks`, `Automations`, `Campaigns`, `Appointments`, `Settings`, `Help`, `CreditsCounter` (kreditsaldot som visas i sidofältet) och `guided_onboarding` (konfigurationsguiden). Tre ytterligare nycklar — `AiInsights`, `Sub Accounts` och `Agency Reselling` — accepteras men gör ingenting: de gällde endast den numera avvecklade klassiska instrumentpanelen, så att ställa in dem har ingen effekt på dina underkonton. Saknade nycklar innebär att de är synliga; när du loggar in på underkontot själv visas dolda objekt tillfälligt så att du alltid kan ändra tillbaka inställningarna.

Att dölja en sida från menyn ger aldrig åtkomst till den. `Automations` kräver att funktionen `automations` är beviljad på underkontot — ställ in nyckeln till `true` utan den och sidan kommer fortfarande inte att visas. `Tasks` och `DailySummaries` fungerar tvärtom: de är aktiverade för varje klient om du inte stänger av dem (se [Inaktivera uppgifter, dagliga sammanfattningar eller mediebiblioteket för en klient](#turn-tasks-daily-summaries-or-the-media-library-off-for-a-client)).

***

## Välj vilka kanaltyper en klient kan ansluta

`PUT /v1/subaccounts/{subAccountUid}/features`

Växlarna för **Kanaltyper** som du ser på en abonnemangsnivå är vanliga funktions-ID:n, så du kan ställa in dem per klient via API:et istället för via kontrollpanelen. Detta är en av de slutpunkter som namnger underkontot i sin egen URL, så den kräver inget `sub_account_id`.

| Funktions-ID | Kanal |
|---|---|
| `channel_chat_widget` | Chattwidget för webbplats |
| `channel_whatsapp_api` | WhatsApp Business API |
| `channel_whatsapp_web` | WhatsApp Web (QR-länkat nummer) |
| `channel_instagram` | Instagram |
| `channel_messenger` | Facebook Messenger |
| `channel_telegram` | Telegram |
| `channel_line` | LINE |
| `channel_viber` | Viber |
| `channel_email` | E-postbrevlåda |
| `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 saker att få rätt på:

- **Anropet ersätter hela funktionslistan.** Skicka med varje funktion som klienten ska behålla, inte bara de du ändrar. Samma ID:n fungerar som `features` på `POST /v1/subaccounts` när du skapar kontot.
- **Kanaltyper och kanalantal är separata spärrar, och båda tillämpas.** `channels_1` / `channels_3` / `channels_unlimited` styr *hur många* anslutningar; `channel_*`-ID:n styr *vilka typer*. Exemplet ovan betyder "upp till 3 anslutningar, och endast chattwidget, WhatsApp Web eller Instagram".
- **Att inte skicka några `channel_*`-ID:n alls innebär ingen kanalbegränsning.** Det är det ursprungliga beteendet, vilket är anledningen till att befintliga klienter inte påverkades när detta lanserades. Skicka ett eller flera så visas allt annat som låst på klientens kanalsida med en uppgraderingsnotis istället för en Anslut-knapp. Kanaler som klienten redan har anslutit fortsätter att fungera.

> Att ställa in kanallistan på en **abonnemangsnivå**, så att varje klient som köper den nivån ärver den, görs i kontrollpanelen under inställningarna för din byråplan. Denna slutpunkt ställer in det på ett specifikt underkonto.

***

## Ange en exakt gräns för antal teammedlemmar för en klient

`PUT /v1/subaccounts/{subAccountUid}/limits`

`team_seats_*`-funktionerna erbjuder endast förinställda trappsteg (3 / 5 / 10 / obegränsat). För att ge en klient ett **exakt** antal teamplatser — 2, 7, 15, vad som helst — ställ in `usage_limits.team_seats_limit` istället. Den prioriteras över förinställningarna, och plattformen tillämpar den vid varje inbjudan, direkt tillägg och godkännande av inbjudan: när gränsen är nådd nekas ytterligare inbjudningar på serversidan.

- Ett positivt heltal är det exakta taket.
- `0` innebär att teammedlemmar **inte inkluderas** — klienten kan inte bjuda in någon.
- `-1` innebär obegränsat.
- `null` rensar den anpassade gränsen och återgår till vilken `team_seats_*`-förinställning som än finns i funktionslistan.

Att sänka gränsen tar aldrig bort befintliga teammedlemmar; det hindrar bara att nya läggs till.

```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 även ställa in det vid skapandet: `POST /v1/subaccounts` accepterar `usage_limits.team_seats_limit` med samma semantik. För att läsa det nuvarande värdet, hämta underkontot med `GET /v1/subaccounts?email=...` och titta på `usage_limits.team_seats_limit` (frånvarande/`null` = förinställningarna bestämmer). Samma slutpunkt uppdaterar även `credits`, `monthly_credits`, `roll_over_to_next_month`, `rollover_cap_months`, `rollover_expiry_days` och `byok_monthly_limit_usd` — skicka endast de nycklar du vill ändra.

**Hur detta interagerar med SaaS-planens platsbegränsningar.** Dina SaaS-planer kan ha egna platsantal (anges i planredigeraren — se [Teamplatser i en plan](agency-accounts.md#step-3--set-up-pricing-tiers)), vilka tillämpas automatiskt när en kund prenumererar. En gräns som du anger via denna slutpunkt räknas som en **manuell** tilldelning: att köpa en plan ersätter den med planens egna platsantal (det köpet är ett explicit val av plan), men obevakade månatliga **förnyelser skriver aldrig över en manuell gräns** — så ett engångsundantag som du beviljar en kund kvarstår under deras faktureringscykel. Att rensa den manuella gränsen med `null` återlämnar fältet till planen vid nästa förnyelse.

**Begränsa vad en klient tar med sig mellan förnyelser.** Två ytterligare `usage_limits`-nycklar finns bredvid `roll_over_to_next_month`. Båda accepteras även av `POST /v1/subaccounts` vid skapandet, och `null` rensar båda.

| Nyckel | Vad den gör |
|---|---|
| `rollover_cap_months` | Antal månaders tilldelning som klienten får behålla. Ett tal från 0 till 120, bråktal tillåtna (`0.5` = en halv månad). Vid varje förnyelse trimmas det oanvända saldot till högst detta antal gånger den tilldelning som förnyelsen ger, innan de nya krediterna läggs till; `0` för ingenting vidare. |
| `rollover_expiry_days` | Ett heltal av dagar, 1 till 3650. Krediter som lämnats oanvända så länge tas bort vid den första förnyelsen efter att de når den åldern. Förbrukning dras alltid från de äldsta krediterna först, så en klient som förbrukar sin tilldelning varje månad förlorar aldrig några. |

Om de lämnas oinställda faller båda tillbaka på klientens plan; ett värde som skickas här vinner över planens. Endast återkommande krediter (månadstilldelningen och plankrediter) omfattas av dem: påfyllningar, automatiska påfyllningar och engångstillägg begränsas eller löper aldrig ut. Varje trimning skrivs till klientens kredithistorik som en **Rollover Cap Credit Adjustment** eller en **Expired Credits Credit Adjustment** och räknas aldrig som förbrukning. Motsvarigheterna på plannivå är `rollover_cap_months` och `rollover_expiry_days` på en prisnivå — se [Fälten på en nivå](#the-fields-on-a-tier) och [Begränsa vad som rullas över](sub-accounts.md#capping-what-rolls-over).

***

## Ställ in AI-prissättning och policy per klient

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

Åtta ytterligare per-klient-växlar, vid sidan av `/limits`, `/features` och `/menu-visibility` ovan. Varje tar underkontots uid i URL:en (ingen `sub_account_id` body/query-parameter — målet är redan namngivet i sökvägen) och är begränsad på samma sätt: din agenturnyckel, och underkontot måste tillhöra din agentur.

**Vilka AI-modeller en klient kan använda**

```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 }` låter klienten välja att aktivera (eller inaktivera) Max AI-nivån — vår infrastruktur till plattformens listpris. Att aktivera detta för en BYOK-klient ändrar deras AI-kostnad från "gratis med min egen nyckel" till "debiteras min kreditpool", så det är ett medvetet beslut per klient snarare än en byråomfattande standard.

För att begränsa VILKA nivåer en klients kampanjer och agenter får välja mellan (istället för att bara begränsa Max), använd `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` är en array hämtad från `standard`, `economy`, `max`, `mini` — den ERSÄTTER klientens tillåtelselista. Skicka `null` (eller `[]`) för att rensa begränsningen och låta dem välja vilken nivå som helst. Detta är viktigt eftersom ett underkonto som väljer sin egen AI-nivå spenderar från **din** kreditpool, så det är spaken för att styra vilka modeller en återförsäljarklient kan använda för att öka din faktura.

**Ett väntesvar medan klienten har slut på krediter**

```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 pott) är tomt kan AI:n inte svara och kontakten hör ingenting. Med `enabled: true` får varje kontakt som skriver in under avbrottet `message` en gång (max 500 tecken, skickas som det är i varje kanal), och AI:n svarar på dessa konversationer på riktigt när krediterna är tillbaka. `enabled: false` sparar texten för senare; `enabled: false` utan `message` tar bort inställningen. Samma växel som **Väntesvar när krediter saknas** i underkontots redigeringsmodal — se [Ett väntesvar medan en klient har slut på krediter](sub-accounts.md#a-holding-reply-while-a-client-is-out-of-credits).

**Vad en klient betalar per AI-åtgärd och påslaget för WhatsApp-avgifter**

Två sätt att ställa in din klientvända taxa, från enklaste till mest detaljerade:

```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` är priset i krediter som underkontots EGEN balans förbrukar per Max-modell AI-åtgärd — ditt klientvända påslag utöver vad din pool faktiskt betalar. `null` rensar åsidosättningen tillbaka till plattformens listpris. Taxan måste vara minst vad en Max-åtgärd kostar din egen pool (så att du aldrig kan prissätta en klient under din kostnad) och högst 10 krediter; en förfrågan utanför det fönstret avvisas med det beräknade golvet i felmeddelandet.

För prissättning per åtgärdstyp istället för en fast Max-taxa, använd `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` är en SAMMANSLAGNING med klientens befintliga karta — en nyckel du inte nämner lämnas som den var, och `null` återställer den nyckeln till dess standardvärde. De igenkända nycklarna:

| Nyckel | Priser |
|---|---|
| `AI_MESSAGE` | Ett AI-svar |
| `AI_TOOL_USE` | Ett AI-verktygsanrop |
| `EVALUATION_CALL` | Ett utvärderingssteg för chatt |
| `INTERRUPTION_HANDLING` | Hantering av ett avbrott mitt i ett svar |
| `CONTACT_TAG` | En AI-tilldelad kontakttagg |
| `CHAT_SUMMARY` | En chattsammanfattning |
| `wa_carrier_multiplier` | En påslagsmultiplikator som tillämpas på varje icke-AI WhatsApp-avgift som klienten betalar: månatlig hyra för nummer, leveransavgifter för hanterade filer och vidarefakturering av Meta/Twilio-mallkostnader. |

Priser per åtgärd måste vara ett tal större än 0 och upp till 10; `wa_carrier_multiplier` måste vara minst `1` (ingen rabatt under självkostnadspris) och upp till 10. Om du skickar en okänd nyckel eller ett värde utanför intervallet avvisas HELA förfrågan och varje felaktig nyckel namnges, så att ett skrivfel aldrig i tysthet kan spara ett pris som faktiskt inte tillämpas.

Om du är medlem i [Champions Circle](https://skool.com/dm-champions) skickar `insider-rate` vidare din 20 % rabatt för Max/Lead Finder till en klient istället för att tillämpa den på hela byrån:

```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 }'
```

Att aktivera den kräver att ditt eget byråkonto faktiskt har ett Circle-medlemskap; att inaktivera den kräver aldrig detta, så en medlem vars medlemskap löpt ut kan alltid nedgradera en klient igen.

**Lås delar av 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` är en array hämtad från `instructions`, `goal`, `rules`, `personality`, `conclude_unless` — den ERSÄTTER klientens låsta lista. En låst sektion avvisas på serversidan om själva UNDERKONTOT försöker ändra den (direkt eller via API-nyckel), medan du (via `sub_account_id`) och klientens egen administratörsvy i instrumentpanelen fortfarande kan redigera allt. Skicka `null` (eller `[]`) för att låsa upp allt. Användbart för "done-for-you"-klienter där du äger playbooken och bedöms utifrån resultatet.

**Ställ in en klients aviseringsinställningar å deras vägnar**

```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` ersätter hela klientens uppsättning av aviseringsinställningar (inte en sammanslagning per nyckel — skicka med varje kategori du vill behålla, på samma sätt som underkontots egen inställningssida sparar dem). Varje kategori under `settings` accepterar `enabled` (booleskt värde) och upp till tre `channels` från `email`, `in_app`, `webhook`. Skicka `null` för att återställa till plattformens standardvärden.

Alla sju slutpunkter svarar med `{ "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } }` och loggas i granskningsloggen med värdet före/efter. Vanliga fel: `403` om ditt konto inte är Byrå/Utvecklare eller om underkontot inte är ditt att hantera, `400` om det inte är ett byrå-underkonto eller om ett värde ligger utanför intervallet.

***

## Pausa en klient som har avbrutit sin prenumeration

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

När en klient avbryter sin prenumeration hos dig, pausa deras konto istället för att radera det: allt de skickar stoppas omedelbart — utgående meddelanden, utskick, AI-svar i alla kanaler — och när de loggar in ser de ett **Konto pausat**-lås i helskärm (med ditt valfria meddelande) istället för appen. Ingenting raderas eller kopplas bort: agenter, kampanjer, anslutna kanaler, kontakter och chatthistorik förblir precis som de är, så att avpausa klienten innebär att de fortsätter exakt där de slutade — ingen konfiguration behöver göras om.

| Fält | Obligatoriskt | Beskrivning |
|---|---|---|
| `message` | Nej | Visas för klienten på deras låsskärm. Lämna tomt för standardtext. |
| `reason` | Nej | Byråintern anteckning som lagras med pausen och i granskningsloggen — visas aldrig för 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 kommer tillbaka tar `POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause` (ingen brödtext) bort låset — sändningar och AI-svar återupptas omedelbart.

Bra att veta:

- **Det är samma tillstånd som instrumentpanelens växel för hård blockering** ([Blockera / Pausa ett underkonto](sub-accounts.md#blocking-pausing-a-sub-account)) — en klient som pausats via API:et visas som blockerad i instrumentpanelen och vice versa, och att avpausa rensar en blockering som gjorts från båda hållen. Det aktuella tillståndet kan läsas från fältet `agency_block` på `GET /v1/subaccounts` (`level` av `"none"`, `"soft_blocked"` eller `"hard_blocked"`).
- **Båda anropen är idempotenta.** Att pausa en redan pausad klient uppdaterar bara meddelandet, orsaken och tidsstämpeln; att avpausa en aktiv klient ändrar ingenting.
- **Klienten får inget e-postmeddelande automatiskt** — många byråer använder white-label, så det är upp till dig att informera klienten.
- **Din egen DM Champ-fakturering påverkas inte.** Att pausa en klient påverkar endast din relation med dem.
- **AI-assistenter kan också göra detta**: [MCP-servern](../integrations/connect-ai-clients.md) exponerar dessa slutpunkter som verktygen `pause_subaccount` och `unpause_subaccount`.

***

## Ge eller dra av krediter direkt

`POST /v1/subaccounts/credits`

Lägger till eller tar bort ett exakt belopp av krediter från ett underkontos saldo — API-motsvarigheten till instrumentpanelens manuella kreditjustering. Detta är en engångsändring av saldot, skild från de återkommande `monthly_credits`, `roll_over_to_next_month`, `rollover_cap_months` och `rollover_expiry_days`-inställningarna på [`PUT /v1/subaccounts/{subAccountUid}/limits`](#set-an-exact-team-member-limit-for-a-client).

Detta är den enda slutpunkten på denna sida som identifierar underkontot via **e-post** istället för `sub_account_id`.

| Fält | Krävs | Beskrivning |
|---|---|---|
| `email` | Ja | Underkontots e-postadress, så som den finns under din byrå. |
| `amount` | Ja | Antal krediter (ej noll). Positivt lägger till, negativt drar av. |
| `description` | Nej | Visas vid justeringen i klientens kredithistorik. Standardvärdet är en generisk rad: "Justerat av byrå via API". |

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

Ett negativt `amount` som skulle ta saldot under noll nekas med `400`, vilket informerar dig om det tillgängliga saldot och vad du försökte dra av. Om klienten har sin egen Stripe-fakturering (återförsäljarläge), räknas ett tillagt belopp också som krediter de köpt, så det överlever deras nästa månatliga återställning på samma sätt som en riktig påfyllning skulle göra; på en standardallokerad klient behandlas det som en del av deras återkommande tilldelning istället. Hur som helst är de ett engångstillägg, så ett rollover-tak eller ett utgångsdatum inställt på kontot (eller dess plan) trimmar dem aldrig — endast den återkommande tilldelningen och plankrediterna omfattas av dessa.

***

## Läs ett underkontos konversationer

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

Låter dig bygga en övervaknings- eller supportvy av en klients konversationer utan att logga in på deras konto. Lista först deras kontakter med en förhandsgranskning av det senaste meddelandet, och läs sedan en kontakts fullständiga meddelandehistorik.

**Lista kontakter**

```bash
curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
```

| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
| `pageSize` | Nej | Kontakter per sida. Standard 25, max 50. |
| `lastActivityAt` | Nej | Sidnumreringspekare — skicka föregående sidas `lastActivityAt` för att fortsätta. |
| `searchQuery` | Nej | Filtrera efter kontaktnamn 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 sorteras efter senaste aktivitet först. Fortsätt bläddra med `lastActivityAt` medan `hasMore` är `true`.

**Läs en kontakts meddelanden**

```bash
curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
```

| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
| `pageSize` | Nej | Meddelanden per sida. Standard 30, max 100. |
| `beforeTimestamp` | Nej | Sidnumreringspekare — hämta meddelanden äldre än denna ISO-tidsstämpel. |

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

Meddelanden returneras med det nyaste först; bläddra bakåt i historiken med `beforeTimestamp`.

***

## Läs kreditförbrukning och kampanjhälsa för hela din portfölj

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

Två sammanställningar i instrumentpanelsstil över alla underkonton du hanterar, för att bygga din egen byrårapportering istället för att klicka in i varje klient en i taget.

**Kreditförbrukning**

```bash
curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
```

| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
| `from` / `to` | Ja | ISO-datumintervall. |
| `subAccountId` | Nej | Utelämna för en sammanfattning för hela byrån, en rad per underkonto. Inkludera för att växla till detaljläge: det underkontots sammanfattning plus dess råa, sidnumrerade förbrukningsposter. |
| `limitCount` | Nej | Endast detaljläge. Standard 500, max 2000. |
| `startAfterTimestamp` | Nej | Endast detaljläge — sidnumreringspekare. |

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

Skicka `subAccountId` så innehåller samma svar även `records`: individuella debiteringar med `amount`, `reason`, `campaignName`, `contactName` och `timestamp`. En klient som spenderar via sin egen BYOK-nyckel istället för dina krediter får kostnads-/token-siffror undanhållna (`costsRedacted: true`) — det är telemetri för plattformskostnader, inte något som ska visas för en återförsäljare. |

**Kampanjstatus**

```bash
curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
```

| Frågeparameter | Krävs | Beskrivning |
|---|---|---|
| `pageSize` | Nej | Underkonton per sida. Standard 10, max 50. |
| `lastDocumentId` | Nej | Sidbrytningspekare. |
| `searchQuery` | Nej | Filtrera efter underkontots namn eller e-postadress. |

```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` flaggar underkonton som är värda att titta närmare på — till exempel en pausad kampanj eller en kampanj utan någon kanal dirigerad till sig. Använd detta för att bygga en hälsokontrollpanel för hela din portfölj istället för att öppna varje kund för att upptäcka en avstannad kampanj.

> För tidsserier av meddelanden och kreditaktivitet för varje kund (en serie redo för diagram snarare än en ögonblicksbild), se `GET /analytics/agency-rollup` i guiden för Analytics API.

***

## Leverera ett klientkonto som redan är konfigurerat

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

En [ögonblicksbild](snapshots.md) (snapshot) är en återanvändbar mall: en eller flera AI-agenter plus deras kunskapsbas, verktyg och media, hämtade från ditt eget konto. Två slutpunkter gör att du kan inkludera den i ditt etableringsflöde.

**Automatiskt — varje ny klient får den direkt.** Markera en ögonblicksbild som din standard en gång, så kommer varje konto du skapar därefter att ha den installerad. Detta gäller konton som skapats via `POST /v1/subaccounts`, konton du skapar i instrumentpanelen och konton som skapas automatiskt när en klient betalar via din betalningslänk.

Hitta först ögonblicksbildens id:

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

Ställ sedan in den 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 är hela integrationen. Skicka `{"snapshot_id": null}` för att stänga av den igen. Du kan göra samma sak från instrumentpanelen genom att klicka på stjärnan på sidan **Ögonblicksbilder**.

För att läsa av vad som för närvarande är stjärnmarkerat (t.ex. innan ett etableringsskript bestämmer om ett ska ställas in), returnerar `GET /v1/snapshots/default` `{ "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } }` — `null` när inget är stjärnmarkerat. `GET /v1/snapshots` (används för att hitta id:t ovan) returnerar samma `default_snapshot_id` tillsammans med hela `snapshots`-arrayen, så de flesta integrationer behöver bara det anropet. Fälten för hela ögonblicksbildsobjektet finns i guiden [Snapshots](snapshots.md).

**På begäran — installera i ett enskilt konto.** Användbart för att introducera en befintlig klient, eller för att ge en klient en andra mall vid ett senare tillfälle.

```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" }'
```

Utelämna `sub_account_id` så installeras den i ditt eget byråkonto istället. Liksom `/subaccounts`-slutpunkterna anger dessa målkontot i sökvägen eller brödtexten snarare än via den omgivande `sub_account_id`-parametern.

Bra att veta innan du bygger vidare på det:

- **Installerade agenter startar i pausat läge.** Anslut klientens kanaler först och aktivera sedan agenten. Detta gäller både för den automatiska vägen och vägen på begäran.
- **Etablering misslyckas aldrig på grund av en ögonblicksbild.** Om installationen inte kan slutföras skapas klientkontot ändå och är användbart — det levereras bara tomt och du kan applicera ögonblicksbilden i efterhand.
- **Kanaler, kalendrar och OAuth-anslutningar kopieras aldrig.** Varje konto ansluter sina egna. Verktyg som använder en vanlig API-nyckel fortsätter att fungera omedelbart.
- **Att applicera två gånger skapar en andra kopia.** Ingenting skrivs över.

***

## Bygg själva mallen via API:et

`POST /v1/snapshots` · agenter, anpassade funktioner och media via API:et

Avsnittet ovan distribuerar en ögonblicksbild som någon skapat i instrumentpanelen. Skapardelen är också exponerad, så hela loopen — att sätta ihop huvudkonfigurationen en gång, fånga den och ge den till varje klient — kan köras från kod.

Delarna, i den ordning ett etableringsskript använder dem:

1. **Skapa dina anpassade funktioner.** `POST /v1/custom-functions` skapar en; `GET /v1/custom-functions` listar vad du har, och `GET`, `PUT` och `DELETE` på `/v1/custom-functions/{customFunctionId}` läser, uppdaterar och tar bort en. `POST /v1/custom-functions/test` gör en testkörning av en definition innan du sparar den.
2. **Skapa och forma agenten.** `POST /v1/agents` skapar den, `PUT /v1/agents/{agentId}` uppdaterar den, och `PATCH /v1/agents/{agentId}/active` med `{ "active": false }` håller den pausad medan du arbetar (samma anrop med `true` gör den aktiv). `GET /v1/agents` listar dem.
3. **Ge agenten dess förmågor.** `POST /v1/agents/{agentId}/custom-functions` med `{ "custom_function_id": "..." }` kopplar en funktion till agenten; motsvarande `DELETE /v1/agents/{agentId}/custom-functions/{customFunctionId}` kopplar bort den.
4. **Fyll mediebiblioteket.** `POST /v1/agents/{agentId}/media-library` laddar upp ett objekt (JSON med `base64Data`, `mimeType`, `title`, `description`); `GET` listar agentens objekt, och `PATCH`/`DELETE` på `/{itemId}` uppdaterar eller tar bort ett.
5. **Fånga den som en ögonblicksbild.**

```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
  }'
```

Därifrån är det som i föregående avsnitt: markera den som standard så att varje ny klient föds med den, eller tillämpa den vid behov. Underhåll finns vid sidan av: `PATCH /v1/snapshots/{snapshotId}` med `{ "name": "..." }` döper om en, `DELETE /v1/snapshots/{snapshotId}` tar bort en (och avmarkerar den om den var standard), och `GET /v1/snapshots/apply-targets` listar varje konto du kan installera i.

Slutpunkterna för agenter, anpassade funktioner och media accepterar alla `sub_account_id`, så samma anrop kan också underhålla en agent direkt i en klients konto. Ögonblicksbildsanrop agerar alltid på ditt agentkonto — mallen finns hos dig. Fullständiga scheman för anrop och svar för alla dessa finns i [API-referensen](../api/reference.md).

***

## Hantera dina prisnivåer 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äljer i **SaaS-läge → Prisnivåer** kan läsas och ändras via kod, så din egen administratörspanel eller etableringsskript kan lägga till en plan, justera ett pris eller dela ut en betalningslänk utan att någon behöver öppna kontrollpanelen. Autentisera med din byrå-API-nyckel precis som vid alla andra anrop på den här sidan; dessa slutpunkter är på byrånivå, så de kräver inget `sub_account_id`. Varje skrivåtgärd kör samma validering och samma Stripe-synkronisering av produkt och pris som när du sparar i kontrollpanelen, så en plan som skapas här är identisk med en som du ställt in manuellt.

### Lista dina nivåer

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

Varje nivå returneras med sitt **`tierIndex`** — dess position i din planlista, vilket är hur de andra tre anropen adresserar den — och en **`checkout_url`** som är redo att delas. Det är samma länk som fliken **Betalningar** ger dig, och den pekar redan på den [white label-domän](white-labeling.md) som planen säljs på.

### Lägg till en nivå

Brödtexten består av ett nivåobjekt; det läggs till i slutet av din lista.

```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 innehåller den skapade nivån, inklusive `tierIndex` den hamnade på och dess `checkout_url`.

### Redigera en nivå

Skicka endast de fält du vill ändra; allt annat på planen förblir 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 }'
```

Ett fält som API:et inte känner igen avvisas istället för att ignoreras, och felet namnger fältet — så ett skrivfel kan aldrig i tysthet skriva en inställning som ser aktiv ut men inte gör någonting. Att ändra pris, krediter, valuta eller faktureringsintervall skapar ett nytt pris i din Stripe; kunder som redan prenumererar behåller det de registrerade sig för.

### Ta bort en nivå

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

Samma regel som i kontrollpanelen: en plan som fortfarande har aktiva prenumeranter kan inte tas bort. Begäran nekas och du får veta hur många prenumeranter som finns på den — avsluta eller migrera dem först. En lyckad borttagning svarar med dina återstående nivåer, som redan har numrerats om.

### Fälten på en nivå

| Fält | Vad det är |
|---|---|
| `label` / `description` | Planens namn, och den valfria raden som visas på din betalningssida. |
| `credits` | Krediter klienten får **per månad** på en månads- eller årsplan, och **per faktureringsperiod** på en veckoplan. |
| `price_cents` | Pris per faktureringsintervall, i den minsta valutaenheten (`2900` = $29.00). På en årsplan är detta priset för hela året. |
| `currency` | ISO-kod med gemener — `usd`, `eur`, `gbp` och så vidare. |
| `billing_interval` / `billing_interval_count` | `month` (standard), `year`, eller `week` med ett antal på 1–52 för "varje N:e vecka". |
| `trial_days` | Längd på gratis provperiod, 0 till 90. `0` (eller att utelämna den) betyder ingen provperiod. |
| `trial_credits` | Krediter klienten startar provperioden med. Standard är planens `credits`. |
| `trial_card_required` | `false` låter klienten starta provperioden utan att ange ett kort. Standard är `true`. |
| `trial_hard_expiry` | `true` returnerar oanvända provkrediter till din pott och låser klientens konto när en provperiod slutar utan en uppgradering. Standard är `false` — se [Hård utgång efter provperiod](agency-accounts.md#step-3--set-up-pricing-tiers). |
| `rollover_cap_months` | Antal månaders tilldelning som klienter på denna plan får ta med sig mellan förnyelser — ett tal från 0 till 120, bråktal tillåtna. `0` för ingenting vidare; `null` (standard) betyder inget tak. Se [Begränsa vad som rullas över](sub-accounts.md#capping-what-rolls-over). |
| `rollover_expiry_days` | Dagar efter vilka oanvända krediter tas bort vid nästa förnyelse — ett heltal från 1 till 3650. `null` (standard) betyder att de aldrig löper ut. |
| `features` / `feature_settings` | Vad klienter på denna plan får — samma funktions-ID:n som [Välj vilka kanaltyper en klient kan ansluta](#choose-which-channel-types-a-client-can-connect). |
| `team_seats_limit` | Teamplatser som planen ger: ett exakt antal, `0` för inga, `-1` för obegränsat. |
| `white_label_config` | Vilken av dina [white label-domäner](white-labeling.md#up-to-three-white-labels) planen säljs på. |

Fälten för provperiod betyder bara något för en plan som har en provperiod: spara en nivå med `trial_days: 0` så tas de bort. Planens Stripe-produkt- och pris-ID:n hanteras åt dig och kan inte ställas in manuellt.

Tre saker att få rätt på:

- **Nivåindex är positioner, inte permanenta id:n.** Om du tar bort en plan flyttas varje efterföljande plan ett steg nedåt, så hämta listan på nytt efter varje ändring — och kopiera om de betalningslänkar du har publicerat, precis som du skulle göra efter att ha tagit bort en plan i kontrollpanelen.
- **SaaS-läge måste ställas in först.** Dessa slutpunkter kräver ett byråkonto med white labeling och en sparad Stripe-nyckel; utan detta finns inget Stripe-konto där planens produkt och pris kan finnas.
- **Tjugo planer är maxgränsen**, samma som i kontrollpanelen. Fältet `max_tiers` i listsvaret anger den nuvarande gränsen.

Fullständiga scheman för förfrågningar och svar finns i [API-referensen](../api/reference.md), under **Agency**.

***

## Ange ditt pris per kredit via API:et

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

Priset som klienter betalar för ad-hoc-påfyllningar (**SaaS-läge → Prissättning per kredit**) kan även läsas och ändras via kod. Detta är byggt för fall där priset behöver justeras automatiskt: en byrå som säljer krediter i en valuta men fakturerar i en annan kan låta ett schemalagt jobb revidera priset i takt med att växelkursen ändras, istället för att någon behöver redigera det manuellt varje vecka.

### Läs det aktuella priset

```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` är det lägsta priset som plattformen tillåter i den valutan, så ett jobb kan kontrollera ett nytt pris innan det skickas. Alla tre värden är `null` tills ett pris har angetts.

### Ändra det

```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" }'
```

Skicka endast det du vill ändra. `price_per_credit_cents` är priset i den minsta valutaenheten (`130` = 1,30 R$); `currency` är en ISO-kod med gemener; `note` är en valfri rad på upp till 200 tecken som visas för klienter direkt under priset per kredit på deras faktureringssida — praktiskt för ett referenspris i en annan valuta, till exempel *"0,25 USD per kredit enligt vår referenskurs"*. Skicka `"note": ""` för att ta bort den. Svaret har samma format som läsningen ovan, så ett jobb kan jämföra och hoppa över skrivningen när ingenting har ändrats.

Samma regler gäller som i kontrollpanelen: priset kan inte understiga plattformens miniminivå för den valutan, och kontot måste ha white labeling. Till skillnad från slutpunkterna för prisnivåer krävs ingen Stripe-nyckel för att läsa eller ändra detta värde.

### Ge ett jobb en nyckel som inte kan göra något annat

Att lägga in din fullständiga byrálnyckel i en schemaläggare ger mer åtkomst än vad en prisuppdatering kräver. Skapa istället en **begränsad nyckel** (scoped key) som är begränsad till området **Agency Credit Price**: den nyckeln kan läsa och ändra priset per kredit och ingenting annat — den kan inte komma åt underkonton, planer, krediter eller din Stripe-anslutning.

```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 innehåller den nya nyckeln i `api_key` **en gång** — den visas aldrig igen, så spara den omedelbart. Ställ in `"read_only": true` för en nyckel som bara behöver läsa priset, och lägg till `"expires_at"` (ett ISO-datum) om du vill att den ska sluta fungera automatiskt. Endast kontoinnehavarens nyckel kan skapa begränsade nycklar; lista eller återkalla dem med `GET /v1/api-keys` och `DELETE /v1/api-keys/{id}`.

***

## Låt ett underkonto läsa din prissättning

`GET /v1/subaccounts/agency-pricing`

Varje annan slutpunkt på den här sidan anropas med **din byrálnyckel**, valfritt riktad mot en kund via `sub_account_id`. Den här är motsatsen: den anropas med **underkontots egen API-nyckel**, utan `sub_account_id`, så att en kunds egen påfyllningssida (eller en integration du bygger åt dem) kan visa vad du debiterar dem utan att någonsin se ditt byrå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"
  }
}
```

Detta speglar exakt vad [`GET /v1/agency/pricing-tiers`](#list-your-tiers) och [`GET /v1/agency/credit-price`](#read-the-current-price) returnerar för dig som byrå, minus allt som kunden inte behöver se (Stripe-id:n, `max_tiers`, och så vidare). Det fungerar bara för ett konto som faktiskt är ett underkonto med en kopplad byrå — att anropa det från ditt eget byråkonto returnerar ett behörighetsfel.

***

## Saker att tänka på

- **Använd din byrálnyckel.** Autentisera varje anrop med ditt byråkontos API-nyckel — inte underkontots. Parametern `sub_account_id` är det som styr åtgärden.
- **Krediter dras från underkontot.** Köp och återkommande avgifter belastar det riktade underkontots kreditsaldo, inte ditt.
- **Ett `404` betyder "inte ditt underkonto".** Dubbelkolla id:t och att kontot är ett som du hanterar.
- **Parametern är valfri överallt där den accepteras.** Utelämna den så agerar samma slutpunkt på ditt byråkonto, så att du kan återanvända en integration för båda.

***

## Relaterat

- [API-åtkomst](../integrations/api-access.md) — autentisering, bas-URL, fel, hastighetsbegränsningar.
- [Underkonton](sub-accounts.md) — lista och hantera de konton du kan rikta dig mot.
- [Automatisk påfyllning av underkonto](sub-account-auto-recharge.md) — ge krediter till ett underkonto via webhook + API.
- [Kampanj-API](../api/campaigns.md) — skapa, uppdatera och kopiera kampanjer, inklusive fullständig fältreferens.
- [Kanalanslutnings-API](../api/channels.md) — anslut en kunds kanaler och dirigera dem till en kampanj.
- Analytics API-guide (i API-sektionen) — byråns underkontosammanställning och alla andra rapporteringsslutpunkter.
- [Ögonblicksbilder](snapshots.md) — vad en ögonblicksbild fångar och hur man bygger en i instrumentpanelen.
