DM Champ Docs

API pentru agenții

În calitate de agenție, puteți utiliza același REST API pe care îl folosesc clienții dvs., dar direcționând cererile individuale către unul dintre sub-conturile gestionate, în loc de propriul cont. Acest lucru vă permite să construiți instrumente care să integreze un client cap-la-cap — creându-i campaniile, antrenându-i AI-ul pe o bază de cunoștințe, importându-i contactele, conectându-i canalele de mesagerie și cumpărând numere de telefon — totul fără a vă conecta manual la fiecare sub-cont.

Această pagină acoperă doar comportamentul specific agențiilor: cum să acționați în numele unui sub-cont cu parametrul sub_account_id. Pentru elementele de bază (generarea unei chei, autentificare, URL de bază, formatul erorilor, limite de rată), începeți cu ghidul Acces API. Tot ce este acolo se aplică și aici — vă autentificați cu cheia API a contului dumneavoastră de agenție.

Notă: Această pagină este tehnică. Dacă nu sunteți dezvoltator, partajați-o cu persoana care se ocupă de integrarea dumneavoastră.


Cum funcționează „acționarea în numele” cuiva

În mod implicit, fiecare cerere API acționează asupra contului care deține cheia API — contul dumneavoastră de agenție. Pentru a acționa în schimb asupra unui cont de client gestionat, adăugați parametrul opțional sub_account_id la cerere, setat la id-ul contului acelui client.

  • Omiteți sub_account_id → cererea acționează asupra propriului cont de agenție.
  • Includeți sub_account_id → cererea acționează asupra acelui sub-cont, dar numai după ce platforma confirmă că sub-contul vă aparține cu adevărat.

Vă autentificați întotdeauna cu cheia API a contului dumneavoastră de agenție. Nu aveți nevoie niciodată de cheia proprie a sub-contului și nu gestionați niciodată credențialele sub-contului.

Unde să îl plasați

  • Endpointuri GET / DELETE → transmite-l ca parametru de interogare: ?sub_account_id=THE_SUB_ACCOUNT_ID (alături de apiKey, dacă te autentifici prin interogare).
  • Endpointuri POST / PUT / PATCH → include-l în corpul cererii JSON ca "sub_account_id": "THE_SUB_ACCOUNT_ID".
  • Asistenți AI → nu este nimic de configurat. Serverul MCP poartă aceeași setare pe instrumentele sale de citire, deci o singură conexiune cu cheia ta de agenție poate raporta despre fiecare client: doar menționează clientul în cererea ta („câte contacte are Bella’s Bistro?”). Acțiunile de scriere sunt, de asemenea, disponibile: fiecare endpoint care acceptă sub_account_id este expus ca instrument, astfel încât poți crea, modifica și trimite în numele unui client din aceeași conexiune.

Găsirea id-ului unui sub-cont

sub_account_id este identificatorul unic al contului de client. Puteți obține lista subconturilor dumneavoastră și identificatorii acestora din endpoint-urile API SubAccounts (consultați ghidul Sub-Accounts) sau din pagina Sub Accounts din bara laterală.


Proprietatea este întotdeauna verificată

Atunci când transmiteți un sub_account_id, platforma verifică dacă acel cont este un sub-cont real și dacă aparține agenției dumneavoastră. Doar atunci cererea este procesată.

Dacă id-ul este necunoscut, nu este un sub-cont sau aparține unei alte agenții, cererea eșuează cu un răspuns 404:

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

De ce 404 și nu 403? Un răspuns de tip „interzis” (forbidden) i-ar spune unui străin că ID-ul există, dar nu îi aparține. Returnarea aceluiași 404 pentru „nu există” și „nu este al tău” înseamnă că endpoint-ul nu poate fi utilizat pentru a descoperi ce ID-uri de cont aparțin altor agenții. Tratați un 404 aici ca pe „acesta nu este un sub-cont pe care îl gestionați”.


Unde este acceptat sub_account_id

sub_account_id este acceptat practic pe fiecare endpoint de resursă — orice apel care creează, citește, actualizează sau șterge datele proprii ale unui cont. În practică, puteți configura și rula întreaga setare a unui sub-cont cu cheia dvs. de agenție:

  • Configurare AI — campanii, agenți, întrebări frecvente (FAQ), surse pentru baza de cunoștințe (scanare site și încărcare documente), grupuri pentru baza de cunoștințe, difuzări, funcții personalizate, servere MCP
  • Contacte și CRM — contacte (inclusiv import), liste, etichete, sarcini, tranzacții, programări, evenimente
  • Canale și numere — conectare WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE, căutare / achiziționare / gestionare numere de telefon, șabloane WhatsApp, rutare canale
  • Mesagerie și conținut — trimitere mesaje, sesiuni de chat, exporturi de chat, rezumate zilnice
  • Setări și integrări — webhook-uri, configurare widget de chat, configurare white-label, SMS BYOK și alte setări de cont, analiză

Pentru fiecare dintre acestea, parametrul este opțional — omiteți-l și apelul va acționa asupra propriului cont de agenție, astfel încât o singură integrare servește ambelor scopuri. Creditele și utilizarea provin întotdeauna din contul vizat: taxele pentru campaniile, mesajele, etichetele și numerele unui sub-cont sunt scăzute din soldul sub-contului respectiv.

Unde NU se aplică

Câteva endpoint-uri sunt la nivel de agenție sau se adresează contului propriu și ignoră sub_account_id:

  • Gestionarea sub-conturilor propriu-zise — punctele finale (endpoints) SubAccounts (creare / listare / actualizare a unui sub-cont) și punctul final pentru limita de cheltuieli BYOK denumesc deja sub-contul în propria cale URL. Punctele finale pentru prețuri și politici și punctele finale pentru monitorizarea chat-ului urmează același tipar.
  • Copierea unui Agent între conturiPOST /v1/subaccounts/agents/copy denumește ambele conturi, luând destinația ca targetUserId. Consultați exemplul de lucru de mai jos. (Vechiul POST /v1/subaccounts/campaigns/copy funcționează în același mod, dar este depreciat împreună cu restul API-ului Campaigns.)
  • Ajustarea creditelor și cele două centralizări la nivel de agențiePOST /v1/subaccounts/credits identifică sub-contul prin email în schimb; GET /v1/subaccounts/credit-usage și GET /v1/subaccounts/campaign-status raportează despre fiecare sub-cont simultan, deci nu există un singur cont de vizat.
  • Contul propriei agenții — gestionarea cheilor API, raportarea utilizării agenției, gestionarea echipei și nivelurile de preț acționează întotdeauna asupra contului agenției dumneavoastră.
  • Webhook-uri pentru mesaje primite — punctele finale în care sistemele externe postează în sunt legate de contul ale cărui credențiale le-au configurat, deci nu există nimic de redirecționat.

Lista mereu actualizată, lizibilă automat, cu parametrii acceptați de fiecare endpoint se află în referința API din tabloul de bord (Settings → Integrations → API Key) și în specificația OpenAPI la GET /v1/docs/openapi.yaml. Lansăm frecvent modificări ale API-ului — tratați-le pe acelea ca fiind sursa de adevăr.

Pagina de setări a cheii API cu cheia mascată și controlul de regenerare

Setări → Integrări → Cheie API — cheia agenției dumneavoastră se află aici, alături de linkul către referința completă a API-ului.


Exemplu practic: conectarea Instagram și Messenger pentru un sub-cont

Conectarea Instagram și Messenger este un flux bazat pe browser. Îl inițiați prin API, transmiteți clientului URL-ul de consimțământ returnat (sau îl deschideți pentru el), așteptați ca acesta să autorizeze în browserul său, apoi alegeți ce pagină să conectați — totul în timp ce vizați sub-contul acestuia cu sub_account_id.

Pasul 1 — Inițierea conexiunii

Apelați endpoint-ul de conectare cu sub_account_id al clientului în body. Nu sunt trimise credențiale aici; platforma returnează un URL de consimțământ pe care clientul trebuie să îl deschidă într-un browser, plus un token de corelare de unică folosință.

cURL

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

JavaScript

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

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

Python

import requests

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

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

Răspuns:

{
  "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"
}

Trimiteți clientul la oauth_url într-un browser pentru autorizare. state_token corelează această încercare și este un secret cu durată scurtă de viață — nu îl înregistrați în log-uri. Încercarea expiră la expires_at; dacă expiră, începeți din nou.

Pasul 2 — Interogare (polling) până la încărcarea paginilor

După ce clientul autorizează, interogați endpoint-ul de stare (cu același sub_account_id, de data aceasta ca parametru de interogare) până când apar paginile care pot fi conectate.

cURL

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

JavaScript

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

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

Python

import requests

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

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

Răspuns:

{
  "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
}

Câmpul status trece prin pendingtoken_receivedpages_loadedconnected. Așteptați pages_loaded înainte de a selecta o pagină. Două stări de eroare terminale pot apărea, de asemenea, în loc de progres: failed și expired (clientul a refuzat consimțământul sau fereastra de ~30 de minute a jetonului de stare a expirat) — un câmp reason este inclus atunci când apare oricare dintre acestea. Opriți interogarea și reporniți de la Pasul 1 dacă vedeți una dintre ele; nu așteptați pending la nesfârșit. Jetoanele de acces la pagină nu sunt returnate niciodată.

Pasul 3 — Selectați pagina de conectat

Alegeți unul dintre ID-urile de pagină de la Pasul 2 și selectați-l. Selectarea unei pagini conectează atât Instagram, cât și Messenger pentru acea pagină. Includeți din nou sub_account_id în corp.

cURL

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

JavaScript

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

const data = await res.json();

Python

import requests

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

data = res.json()

Răspuns:

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

Asta este tot — Instagram și Messenger sunt acum conectate la sub-contul clientului. Ați furnizat doar page_id; acreditarea subiacentă este rezolvată pe server și nu trece niciodată prin integrarea dumneavoastră.


Exemplu de lucru: cumpărarea unui număr pentru un sub-cont

Achiziționarea unui număr funcționează în același mod: căutați cu sub_account_id în interogare, apoi achiziționați-l folosindu-l în corp. Creditele sunt deduse din soldul sub-contului, iar numărul este alocat sub-contului.

Căutare (cURL):

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

Achiziție (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();

Achiziție (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()

Răspuns:

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

Numărul este furnizat în starea PURCHASED, iar înregistrarea expeditorului WhatsApp continuă în fundal. Interogați GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456 până când starea ajunge la ONLINE înainte de a trimite.


Exemplu de lucru: livrarea unui Agent șablon către fiecare client nou

Tiparul obișnuit al agenției este să păstreze un Agent principal în contul agenției, configurat exact așa cum doriți să înceapă fiecare client, și să creeze o copie a acestuia în fiecare sub-cont nou în momentul provizionării. Acestea sunt trei apeluri și nu este nevoie de nicio repetiție ulterior: copia își păstrează setările până când le modificați.

Pasul 1 — Copierea Agentului

POST /v1/subaccounts/agents/copy

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

Răspunsul conține ID-ul noului Agent la data.agent_id. Întrebările frecvente (FAQ), baza de cunoștințe și biblioteca media sunt incluse; șabloanele WhatsApp, postările sociale conectate și contactele contului sursă sunt omise în mod deliberat. Lista completă a câmpurilor se află în API-ul AI Agents.

Rețineți că acest punct final utilizează targetUserId în loc de sub_account_id — denumește ambele conturi. Cele două apeluri de mai jos utilizează parametrul normal sub_account_id.

Pasul 2 — Activarea acestuia

Copia ajunge întotdeauna în stare suspendată, deci nu poate trimite mesaje nimănui până când nu decideți altfel. Acesta este, de asemenea, momentul pentru a fixa nivelul AI pe care doriți să îl aibă clientul; acesta rămâne setat, deci nu este nevoie să îl reaplicați conform unui program.

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

Pentru a împiedica clientul să modifice nivelul ulterior, blocați nivelurile permise pe sub-cont în loc să retrimiteți valoarea.

Pasul 3 — Direcționarea canalelor clientului către aceasta

Copia ajunge, de asemenea, fără nicio rutare, deci nimic nu ajunge la ea până când nu o setați ca răspunzător pe canalele pe care clientul le-a conectat. Un apel per canal:

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

De aici, un prim mesaj de la un contact necunoscut pe acel canal este preluat automat de Agentul copiat. Consultați Direcționarea unui canal către un Agent pentru celelalte canale și rutarea per număr.

Setați fusul orar al clientului atunci când creați contul secundar. Transmiteți time_zone_id pe POST /v1/subaccounts. Orele active ale campaniei sunt evaluate în fusul orar propriu al contului secundar, astfel încât un client creat fără unul va avea programul citit în raport cu UTC — ceea ce modifică discret momentele în care asistentului îi este permis să răspundă.


Omiteți expertul de configurare pentru un client pe care îl configurați singur

POST /v1/subaccounts

În mod implicit, prima dată când proprietarul unui nou sub-cont se conectează, acesta este ghidat prin Expertul de configurare. Pentru clienții pentru care faceți totul — unde construiți campania și conectați canalele înainte ca clientul să se conecteze vreodată — transmiteți guided_onboarding: false atunci când creați contul. Aceștia vor ajunge direct pe tabloul de bord, iar intrarea Expert de configurare va fi ascunsă din bara lor laterală.

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

Omiteți câmpul (sau trimiteți true) și expertul se va comporta exact ca întotdeauna, deci integrările existente nu necesită nicio modificare. Pentru a reda expertul unui client mai târziu, afișați din nou elementul guided_onboarding cu PUT /v1/subaccounts/{subAccountUid}/menu-visibility (mai jos) — vizibilitatea meniului controlează dacă expertul poate fi accesat, guided_onboarding controlează doar redirecționarea la prima autentificare.


Dezactivați Sarcinile, Rezumatele zilnice sau Biblioteca media pentru un client

POST /v1/subaccounts

Aceste trei funcții sunt activate pentru fiecare client nou, cu excepția cazului în care specificați altfel, și se comportă diferit față de orice altă funcție din acest ghid: ele sunt de tip opt-out (renunțare), nu opt-in (înscriere). Excluderea lor din features nu este suficientă de la sine, deoarece lista features a unei integrări mai vechi pur și simplu nu le menționa — nu putem face distincția între „agenția a dezactivat acest lucru” și „această listă a fost scrisă înainte ca opțiunea să existe”.

Așadar, specificați acest lucru direct cu feature_settings:

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

Fiecare cheie este opțională; tot ceea ce omiteți rămâne activat. Cu tasks: false, AI-ul nu mai creează sarcini pentru acel client și nu se mai trimit e-mailuri de tip „Sarcină nouă creată”; cu daily_summaries: false, rezumatul nocturn nu mai este generat sau trimis prin e-mail.

feature_settings este singurul lucru care dezactivează aceste trei funcții la creare. Excluderea lor din features nu are niciun efect de la sine, indiferent cum arată restul listei — acest lucru este deliberat, astfel încât o integrare mai veche să nu piardă silențios toate cele trei funcții.

Pentru a modifica oricare dintre acestea ulterior, trimiteți lista completă features către PUT /v1/subaccounts/{subAccountUid}/features — acolo, prezența în listă activează o funcție, iar absența o dezactivează.


Conectați automat clienții în subcontul lor (SSO)

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

Un singur apel cu cheia API a agenției dvs. returnează un URL gata de utilizare care conectează clientul direct în propriul său subcont — fără ecran de autentificare, fără pas de parolă, fără nimic de construit suplimentar. Deschideți-l într-o filă nouă, printr-o redirecționare sau într-un iframe în cadrul propriului produs.

Câmp Obligatoriu Descriere
redirect Nu Pagina din aplicație pe care doriți să ajungă clientul, de exemplu "/chats" sau "/agents". Returnat ca deep_link_url în răspuns.
app_base_url Nu Gazda tabloului de bord pentru link. Implicit este domeniul aplicației dvs. white-label (sau domeniul platformei, dacă nu aveți unul). Trebuie să fie https.

cURL

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

Răspuns

{
  "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"
}

Cum să îl utilizați eficient:

  • O singură etapă. Deschiderea url autentifică clientul și îl direcționează direct către pagina redirect a tabloului de bord — fără ecran de autentificare, fără pagină intermediară. deep_link_url indică aceeași destinație, pentru integratorii care preferă să navigheze explicit într-un cadru după autentificare; odată ce sesiunea există, orice cale a tabloului de bord funcționează în acel context de browser.
  • Generare la cerere, deschidere imediată. Linkul conține o credențială de autentificare și expiră după aproximativ o oră. Solicitați-l pe partea de server în momentul în care clientul dă clic și nu îl stocați și nu îl trimiteți niciodată prin e-mail.
  • Tokenul de autentificare circulă în fragmentul URL (#…), pe care browserele nu îl trimit niciodată către servere, și este eliminat din bara de adrese în momentul în care este consumat.
  • Doar propriile sub-conturi. Endpoint-ul refuză orice cont care nu aparține agenției dumneavoastră.
  • Un link expirat afișează o eroare clară cu o cale de reîncercare — generați unul nou.

Ascundeți elementele de navigare dintr-un subcont

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

Controlează ce elemente din bara laterală și din setări vede un subcont — util atunci când încorporați tabloul de bord și doriți doar suprafețele pe care produsul dvs. nu le acoperă deja. Orice element care nu este listat rămâne vizibil; trimiteți null ca întreaga valoare menuVisibility pentru a reseta totul la vizibil. Ascunderea unui element ascunde intrarea din meniu — asociați acest lucru cu funcționalitățile pe care le acordați subcontului pentru restricționare strictă.

cURL

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

Răspuns

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

side_nav acceptă aceste 13 chei, care corespund numelor elementelor din bara laterală: Dashboard, DailySummaries, Chats, Contacts, Deals, Tasks, Automations, Campaigns, Appointments, Settings, Help, CreditsCounter (soldul de credit afișat în bara laterală) și guided_onboarding (Expertul de configurare). Alte trei chei — AiInsights, Sub Accounts și Agency Reselling — sunt acceptate, dar nu fac nimic: acestea s-au aplicat doar vechiului tablou de bord clasic, retras între timp, așa că setarea lor nu are niciun efect asupra subconturilor tale. Cheile lipsă înseamnă vizibil; atunci când te conectezi singur la subcont, elementele ascunse sunt afișate temporar, astfel încât să poți oricând să revii la setările anterioare.

Ascunderea unei pagini din meniu nu oferă niciodată acces la aceasta. Automations necesită funcția automations acordată sub-contului — setați cheia la true fără aceasta și pagina tot nu va apărea. Tasks și DailySummaries funcționează invers: ele sunt activate pentru fiecare client, cu excepția cazului în care le dezactivați (consultați Dezactivați Sarcinile, Rezumatele zilnice sau Biblioteca media pentru un client).


Alegeți ce tipuri de canale poate conecta un client

PUT /v1/subaccounts/{subAccountUid}/features

Comutatoarele pentru Tipuri de canale pe care le vedeți la un nivel de abonament sunt ID-uri de funcționalitate obișnuite, așa că le puteți seta per client din API în loc de tabloul de bord. Acesta este unul dintre punctele finale care denumește sub-contul în propria sa adresă URL, deci nu necesită sub_account_id.

ID Funcționalitate Canal
channel_chat_widget Widget de chat pentru site-ul web
channel_whatsapp_api API WhatsApp Business
channel_whatsapp_web WhatsApp Web (număr conectat prin QR)
channel_instagram Instagram
channel_messenger Facebook Messenger
channel_telegram Telegram
channel_line LINE
channel_viber Viber
channel_email Căsuță poștală e-mail
channel_sms SMS
channel_imessage iMessage
curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/features" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "features": [
      "channels_3",
      "channel_chat_widget",
      "channel_whatsapp_web",
      "channel_instagram",
      "image_understanding",
      "contact_tagging",
      "incoming_campaigns",
      "webhooks"
    ]
  }'

Trei aspecte de reținut:

  • Apelul înlocuiește întreaga listă de funcționalități. Trimiteți fiecare funcționalitate pe care clientul ar trebui să o păstreze, nu doar pe cele pe care le modificați. Aceleași ID-uri funcționează ca features pe POST /v1/subaccounts atunci când creați contul.
  • Tipurile de canale și numărul de canale sunt restricții separate și ambele se aplică. channels_1 / channels_3 / channels_unlimited controlează câte conexiuni sunt permise; ID-urile channel_* controlează ce tipuri. Exemplul de mai sus înseamnă „până la 3 conexiuni și doar Widget de chat, WhatsApp Web sau Instagram”.
  • Trimiterea a zero ID-uri channel_* înseamnă nicio restricție de canal. Acesta este comportamentul original, motiv pentru care clienții existenți nu au fost afectați când s-a lansat această funcție. Trimiteți unul sau mai multe și tot restul va apărea ca blocat pe pagina de Canale a clientului, cu o notă de actualizare în loc de un buton de Conectare. Canalele pe care clientul le-a conectat deja vor continua să funcționeze.

Setarea listei de canale pe un nivel de abonament, astfel încât fiecare client care achiziționează acel nivel să o moștenească, se face în tabloul de bord, în setările planului de agenție. Acest punct final o setează pentru un anumit sub-cont.


Setați o limită exactă de membri ai echipei pentru un client

PUT /v1/subaccounts/{subAccountUid}/limits

Funcționalitățile team_seats_* oferă doar trepte predefinite (3 / 5 / 10 / nelimitat). Pentru a oferi unui client un număr exact de locuri în echipă — 2, 7, 15, orice număr — setați usage_limits.team_seats_limit în schimb. Aceasta prevalează asupra setărilor predefinite, iar platforma o impune la fiecare invitație, adăugare directă și acceptare a invitației: odată ce limita este atinsă, invitațiile ulterioare sunt refuzate la nivel de server.

  • Un număr întreg pozitiv reprezintă limita exactă.
  • 0 înseamnă că membrii echipei nu sunt incluși — clientul nu poate invita pe nimeni.
  • -1 înseamnă nelimitat.
  • null elimină limita personalizată și revine la oricare setare predefinită team_seats_* se află în lista de funcționalități.

Reducerea limitei nu elimină niciodată membrii existenți ai echipei; doar împiedică adăugarea unora noi.

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

De asemenea, îl poți seta în momentul creării: POST /v1/subaccounts acceptă usage_limits.team_seats_limit cu aceeași semantică. Pentru a citi valoarea curentă, preia sub-contul cu GET /v1/subaccounts?email=... și uită-te la usage_limits.team_seats_limit (absent/null = setările implicite decid). Același endpoint actualizează și credits, monthly_credits, roll_over_to_next_month, rollover_cap_months, rollover_expiry_days și byok_monthly_limit_usd — trimite doar cheile pe care dorești să le modifici.

Cum interacționează acest lucru cu limitele de locuri ale planului SaaS. Planurile tale SaaS pot avea propria alocare de locuri (setată în editorul de plan — vezi Locuri de echipă într-un plan), care este aplicată automat atunci când un client se abonează. O limită pe care o setezi prin acest endpoint contează ca o alocare manuală: achiziționarea unui plan o înlocuiește cu propria alocare de locuri a planului (acea achiziție este o alegere explicită a planului), dar reînnoirile lunare nesupravegheate nu suprascriu niciodată o limită manuală — astfel, o excepție unică pe care o acorzi unui client supraviețuiește ciclului său de facturare. Ștergerea limitei manuale cu null redă controlul câmpului către plan la următoarea reînnoire.

Limitează ceea ce un client păstrează între reînnoiri. Încă două chei usage_limits se află lângă roll_over_to_next_month. Ambele sunt acceptate și de POST /v1/subaccounts în momentul creării, iar null le șterge pe oricare dintre ele.

Cheie Ce face
rollover_cap_months Numărul de luni de alocație pe care clientul le poate păstra. Un număr de la 0 la 120, fracțiile sunt permise (0.5 = o jumătate de lună). La fiecare reînnoire, soldul neutilizat este redus la cel mult acest număr de ori alocația pe care o oferă acea reînnoire, înainte de a fi adăugate noile credite; 0 nu reportează nimic.
rollover_expiry_days Un număr întreg de zile, de la 1 la 3650. Creditele rămase neutilizate atât de mult timp sunt eliminate la prima reînnoire după ce ating acea vechime. Consumul se scade întotdeauna mai întâi din cele mai vechi credite, astfel încât un client care își consumă alocația în fiecare lună nu pierde niciodată nimic.

Dacă sunt lăsate nesetate, ambele revin la planul clientului; o valoare trimisă aici prevalează asupra celei din plan. Doar creditele recurente (alocația lunară și creditele planului) sunt supuse acestora: suplimentările, reîncărcările automate și adăugările unice nu sunt niciodată limitate sau expirate. Fiecare reducere este scrisă în istoricul de credite al clientului ca o Ajustare de Credit pentru Limita de Reportare sau o Ajustare de Credit pentru Credite Expirate și nu contează niciodată ca utilizare. Echivalentele la nivel de plan sunt rollover_cap_months și rollover_expiry_days pe un nivel de preț — vezi Câmpurile de pe un nivel și Limitarea a ceea ce se reportează.


Setează prețurile și politica AI per client

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

Încă opt comutatoare per-client, alături de /limits, /features și /menu-visibility de mai sus. Fiecare preia uid-ul sub-contului în URL (fără sub_account_id parametru de corp/interogare — ținta este deja numită în cale) și este limitat în același mod: cheia agenției tale, iar sub-contul trebuie să aparțină agenției tale.

Ce modele AI poate folosi un client

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 } înscrie clientul în (sau îl exclude din) nivelul Max AI — infrastructura noastră la prețul de listă al platformei. Activarea acestei opțiuni pentru un client BYOK schimbă costul său AI din „gratuit pe propria cheie” în „taxat din fondul meu de credite”, deci este o decizie deliberată per client, mai degrabă decât o setare implicită la nivel de agenție.

Pentru a restricționa CE niveluri pot alege campaniile și agenții unui client (în loc de a limita doar Max), folosește ai-tiers:

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

allowed_ai_tiers este o matrice extrasă din standard, economy, max, mini — aceasta ÎNLOCUIEȘTE lista permisă a clientului. Trimite null (sau []) pentru a șterge restricția și a-i permite să aleagă orice nivel. Acest lucru este important deoarece un sub-cont care își alege propriul nivel AI cheltuiește din fondul tău de credite, deci este pârghia pentru a stabili ce modele poate folosi un client revânzător pe factura ta.

Un răspuns de așteptare în timp ce clientul nu mai are credite

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

Când soldul clientului (sau fondul tău) este gol, AI-ul nu poate răspunde și contactul nu aude nimic. Cu enabled: true, fiecare contact care scrie în timpul indisponibilității primește message o dată (maxim 500 de caractere, trimis ca atare pe fiecare canal), iar AI-ul răspunde la acele conversații în mod real odată ce creditele sunt din nou disponibile. enabled: false păstrează textul salvat pentru mai târziu; enabled: false fără message elimină setarea. Același comutator ca Răspuns de așteptare când nu mai sunt credite în fereastra de editare a sub-contului — vezi Un răspuns de așteptare în timp ce un client nu mai are credite.

Ce plătește un client per acțiune AI și adaosul pentru taxa WhatsApp

Două moduri de a seta tariful pentru clienți, de la cel mai simplu la cel mai granular:

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 este prețul în credite pe care soldul PROPRIU al sub-contului îl consumă per acțiune AI de model Max — adaosul tău pentru client peste ceea ce plătește efectiv fondul tău. null șterge suprascrierea revenind la prețul de listă al platformei. Tariful trebuie să fie cel puțin cât costă o acțiune Max pentru propriul tău fond (astfel încât să nu poți taxa niciodată un client sub costul tău) și nu mai mult de 10 credite; o cerere în afara acestui interval este respinsă cu pragul calculat în mesajul de eroare.

Pentru prețuri per tip de acțiune în loc de o rată fixă Max, folosește action-pricing:

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

actionPricing este o ÎMBINARE cu harta existentă a clientului — o cheie pe care nu o menționezi este lăsată așa cum a fost, iar null resetează acea cheie la valoarea implicită. Cheile recunoscute:

Cheie Prețuri
AI_MESSAGE Un răspuns AI
AI_TOOL_USE Un apel de instrument AI
EVALUATION_CALL O trecere de evaluare a chat-ului
INTERRUPTION_HANDLING Gestionarea unei întreruperi în timpul răspunsului
CONTACT_TAG O etichetă de contact atribuită de AI
CHAT_SUMMARY Un rezumat al chat-ului
wa_carrier_multiplier Un multiplicator de adaos aplicat fiecărei taxe WhatsApp non-AI pe care o plătește clientul: chirie lunară pentru număr, taxe de livrare pe bandă gestionată și costuri de transmitere a șabloanelor Meta/Twilio.

Ratele per acțiune trebuie să fie un număr mai mare de 0 și până la 10; wa_carrier_multiplier trebuie să fie cel puțin 1 (fără reducere sub prețul de cost) și până la 10. Trimiterea unei chei nerecunoscute sau a unei valori în afara intervalului respinge ÎNTREAGA cerere și numește fiecare cheie problematică, astfel încât o greșeală de scriere nu poate salva niciodată în mod silențios un preț care nu este de fapt aplicat.

Dacă ești membru Champions Circle, insider-rate transmite rata ta de reducere de 20% pentru Max/Lead Finder către un singur client, în loc să o aplice la nivelul întregii agenții:

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

Activarea acesteia necesită ca propriul tău cont de agenție să dețină efectiv un abonament Circle; dezactivarea nu necesită niciodată acest lucru, astfel încât un membru al cărui abonament a expirat poate oricând să revină la setările anterioare pentru un client.

Blochează secțiuni din manualul de utilizare (playbook) al unui client

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 este o matrice extrasă din instructions, goal, rules, personality, conclude_unless — aceasta ÎNLOCUIEȘTE lista blocată a clientului. O secțiune blocată este respinsă la nivel de server dacă SUB-CONTUL încearcă să o modifice (direct sau prin cheia API), în timp ce tu (prin sub_account_id) și vizualizarea de administrator a tabloului de bord al clientului puteți edita în continuare orice. Trimite null (sau []) pentru a debloca totul. Util pentru clienții pentru care prestezi servicii complete, unde tu deții manualul de utilizare și ești evaluat în funcție de rezultat.

Setează preferințele de notificare ale unui client în numele acestuia

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 înlocuiește întregul set de preferințe de notificare al clientului (nu este o îmbinare per cheie — trimite fiecare categorie pe care dorești să o păstrezi, respectând modul în care pagina de Setări a sub-contului salvează datele). Fiecare categorie din settings acceptă enabled (boolean) și până la trei channels din email, in_app, webhook. Trimite null pentru a reseta la valorile implicite ale platformei.

Toate cele șapte endpoint-uri răspund { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } } și sunt înregistrate în jurnalul de audit cu valoarea înainte/după. Erori comune: 403 dacă contul tău nu este de tip Agenție/Dev sau sub-contul nu este gestionat de tine, 400 dacă nu este un sub-cont de agenție sau o valoare este în afara intervalului.


Întrerupeți un client care și-a suspendat abonamentul

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

Atunci când un client își suspendă abonamentul la serviciile dumneavoastră, întrerupeți contul acestuia în loc să îl ștergeți: tot ceea ce trimite se oprește imediat — mesajele de ieșire, difuzările, răspunsurile AI pe toate canalele — iar când se conectează, aceștia vor vedea un ecran complet de blocare Cont întrerupt (cu mesajul dumneavoastră opțional) în locul aplicației. Nimic nu este șters sau deconectat: agenții, campaniile, canalele conectate, contactele și istoricul chat-ului rămân exact așa cum sunt, deci reluarea activității readuce clientul exact în punctul în care a rămas — fără a fi nevoie de o reconfigurare.

Câmp Obligatoriu Descriere
message Nu Afișat clientului pe ecranul de blocare. Lăsați necompletat pentru textul implicit.
reason Nu Notă internă a agenției stocată odată cu întreruperea și în jurnalul de audit — nu este afișată niciodată clientului.

cURL

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

Răspuns

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

Când clientul revine, POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (fără corp) elimină blocarea — trimiterea mesajelor și răspunsurile AI se reiau imediat.

Bine de știut:

  • Este aceeași stare ca și comutatorul de blocare totală din tabloul de bord (Blocarea / Întreruperea unui sub-cont) — un client întrerupt prin API apare ca blocat în tabloul de bord și invers, iar reluarea activității elimină o blocare plasată din oricare parte. Starea curentă poate fi citită din câmpul agency_block de pe GET /v1/subaccounts (level din "none", "soft_blocked" sau "hard_blocked").
  • Ambele apeluri sunt idempotente. Întreruperea unui client deja întrerupt doar reîmprospătează mesajul, motivul și marcajul temporal; reluarea activității unui client activ nu schimbă nimic.
  • Clientul nu este notificat automat prin e-mail — multe agenții folosesc white-label, așa că informarea clientului vă revine dumneavoastră.
  • Propria dumneavoastră facturare DM Champ rămâne neatinsă. Întreruperea unui client afectează doar relația dumneavoastră cu acesta.
  • Asistenții AI pot face și acest lucru: serverul MCP expune aceste puncte finale ca instrumente pause_subaccount și unpause_subaccount.

Acordă sau deduce credite direct

POST /v1/subaccounts/credits

Adaugă sau elimină o sumă exactă de credite din soldul unui sub-cont — echivalentul API al ajustării manuale de credit din tabloul de bord. Aceasta este o modificare unică a soldului, distinctă de setările recurente monthly_credits, roll_over_to_next_month, rollover_cap_months și rollover_expiry_days de pe PUT /v1/subaccounts/{subAccountUid}/limits.

Acesta este singurul endpoint de pe această pagină care identifică sub-contul prin e-mail în loc de sub_account_id.

Câmp Obligatoriu Descriere
email Da E-mailul sub-contului, așa cum există în cadrul agenției tale.
amount Da Număr diferit de zero de credite. Pozitiv adaugă, negativ deduce.
description Nu Afișat în dreptul ajustării în istoricul creditelor clientului. Implicit este o linie generică “Ajustat de agenție prin API”.

cURL

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

Răspuns

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

Un amount negativ care ar duce soldul sub zero este refuzat cu 400, informându-te despre soldul disponibil și suma pe care ai încercat să o deduci. Dacă clientul este pe propria facturare Stripe (mod revânzător), o sumă adăugată contează și ca credite pe care le-a achiziționat, deci supraviețuiește următoarei resetări lunare la fel cum ar face-o o reîncărcare reală; pe un client alocat standard, este tratată ca parte a alocației sale recurente. Oricum ar fi, sunt o adăugare unică, deci o limită de reportare sau o expirare setată pe cont (sau pe planul său) nu le reduce niciodată — doar alocația recurentă și creditele planului sunt supuse acestora.


Citește conversațiile unui sub-cont

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

Vă permite să creați o vizualizare de monitorizare sau asistență a conversațiilor unui client fără a vă conecta la contul acestuia. Mai întâi, listați contactele acestuia cu o previzualizare a ultimului mesaj, apoi citiți istoricul complet al mesajelor unui contact.

Listare contacte

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
Parametru interogare Obligatoriu Descriere
pageSize Nu Contacte pe pagină. Implicit 25, maximum 50.
lastActivityAt Nu Cursor de paginare — transmiteți lastActivityAt din pagina anterioară pentru a continua.
searchQuery Nu Filtrare după numele contactului sau numărul de telefon.

Răspuns

{
  "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"
  }
}

Contactele sunt ordonate după cea mai recentă activitate. Continuați paginarea cu lastActivityAt cât timp hasMore este true.

Citirea mesajelor unui contact

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
Parametru interogare Obligatoriu Descriere
pageSize Nu Mesaje pe pagină. Implicit 30, maximum 100.
beforeTimestamp Nu Cursor de paginare — preluați mesajele mai vechi decât acest marcaj temporal ISO.

Răspuns

{
  "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"
  }
}

Mesajele sunt returnate începând cu cele mai noi; navigați înapoi prin istoric cu beforeTimestamp.


Citirea utilizării creditelor și a stării campaniilor pentru întregul portofoliu

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

Două rezumate de tip tablou de bord pentru toate subconturile pe care le gestionați, utile pentru a vă crea propriile rapoarte de agenție în loc să accesați fiecare client pe rând.

Utilizarea creditelor

curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
Parametru interogare Obligatoriu Descriere
from / to Da Interval de date ISO.
subAccountId Nu Omiteți pentru un rezumat la nivel de agenție, un rând per subcont. Includeți pentru a comuta în modul detaliat: rezumatul acelui subcont plus înregistrările brute de utilizare paginate.
limitCount Nu Doar pentru modul detaliat. Implicit 500, maximum 2000.
startAfterTimestamp Nu Doar pentru modul detaliat — cursor de paginare.
{
  "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
  }
}

Transmiteți subAccountId și același răspuns va conține și records: taxe individuale cu amount, reason, campaignName, contactName și timestamp. Un client care cheltuiește folosind propria cheie BYOK în loc de creditele dumneavoastră va avea cifrele de cost/token ascunse (costsRedacted: true) — aceasta este telemetrie privind costurile platformei, nu ceva ce trebuie afișat unui revânzător.

Starea campaniei

curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
Parametru de interogare Obligatoriu Descriere
pageSize Nu Sub-conturi pe pagină. Implicit 10, maximum 50.
lastDocumentId Nu Cursor de paginare.
searchQuery Nu Filtrare după numele sau adresa de e-mail a sub-contului.
{
  "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 marchează sub-conturile care merită atenție — o campanie întreruptă sau una fără niciun canal direcționat către ea, de exemplu. Folosiți acest lucru pentru a crea un tablou de bord de verificare a stării pentru întregul portofoliu, în loc să deschideți fiecare client pentru a observa o campanie blocată.

Pentru mesagerie în serie temporală și activitate de credit pentru fiecare client (o serie pregătită pentru grafice, mai degrabă decât un instantaneu la un moment dat), consultați GET /analytics/agency-rollup în ghidul API-ului de Analiză.


Livrați un cont de client care este deja configurat

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

Un snapshot este un șablon reutilizabil: unul sau mai mulți agenți AI plus baza lor de cunoștințe, instrumente și conținut media, capturate din propriul tău cont. Două endpoint-uri îl introduc în fluxul tău de aprovizionare.

Automat — fiecare client nou îl primește implicit. Marchează un snapshot ca implicit o singură dată și fiecare cont pe care îl creezi de atunci înainte va veni cu acesta instalat. Aceasta acoperă conturile create prin POST /v1/subaccounts, conturile pe care le creezi în tabloul de bord și conturile create automat atunci când un client plătește prin linkul tău de checkout.

Mai întâi, găsește ID-ul snapshot-ului:

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

Apoi setează-l ca implicit:

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

Aceasta este întreaga integrare. Trimite {"snapshot_id": null} pentru a-l dezactiva din nou. Poți face același lucru din tabloul de bord făcând clic pe steaua de pe pagina Snapshots.

Pentru a citi ce este marcat în prezent cu stea (de exemplu, înainte ca un script de provizionare să decidă dacă să seteze unul), GET /v1/snapshots/default returnează { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } }null când nimic nu este marcat cu stea. GET /v1/snapshots (folosit pentru a găsi id-ul de mai sus) returnează același default_snapshot_id împreună cu matricea completă snapshots, deci majoritatea integrărilor au nevoie doar de un singur apel. Câmpurile obiectului instantaneu complet se află în ghidul Instantanee.

La cerere — instalare într-un singur cont. Util pentru integrarea unui client existent sau pentru a oferi unui client un al doilea șablon mai târziu.

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

Omite sub_account_id și acesta se va instala în propriul tău cont de agenție. La fel ca endpoint-urile /subaccounts, acestea denumesc contul țintă în cale sau în corp, mai degrabă decât prin parametrul ambiental sub_account_id.

Merită să știi înainte de a construi pe baza acestuia:

  • Agenții instalați pornesc în stare suspendată. Conectează mai întâi canalele clientului, apoi activează agentul. Acest lucru este valabil atât pentru calea automată, cât și pentru cea la cerere.
  • Aprovizionarea nu eșuează niciodată din cauza unui snapshot. Dacă instalarea nu se poate finaliza, contul clientului este totuși creat și utilizabil — acesta ajunge pur și simplu gol și poți aplica snapshot-ul ulterior.
  • Canalele, calendarele și conexiunile OAuth nu sunt niciodată copiate. Fiecare cont își conectează propriile resurse. Instrumentele care utilizează o cheie API simplă continuă să funcționeze imediat.
  • Aplicarea de două ori creează o a doua copie. Nimic nu este suprascris.

Construiește șablonul propriu-zis prin API

POST /v1/snapshots · agenți, funcții personalizate și conținut media prin API

Secțiunea de mai sus distribuie un instantaneu creat de cineva în tabloul de bord. Partea de creare este de asemenea expusă, astfel încât întregul ciclu — asamblarea configurației principale o singură dată, capturarea acesteia, transmiterea către fiecare client — poate fi executat prin cod.

Componentele, în ordinea în care le folosește un script de provizionare:

  1. Creează-ți funcțiile personalizate. POST /v1/custom-functions creează una; GET /v1/custom-functions listează ce ai deja, iar GET, PUT și DELETE pe /v1/custom-functions/{customFunctionId} citesc, actualizează și elimină una. POST /v1/custom-functions/test testează o definiție înainte de a o salva.
  2. Creează și configurează agentul. POST /v1/agents îl creează, PUT /v1/agents/{agentId} îl actualizează, iar PATCH /v1/agents/{agentId}/active cu { "active": false } îl menține în pauză în timp ce lucrezi (același apel cu true îl pune în funcțiune). GET /v1/agents îi listează.
  3. Oferă-i agentului abilitățile sale. POST /v1/agents/{agentId}/custom-functions cu { "custom_function_id": "..." } atașează o funcție agentului; DELETE /v1/agents/{agentId}/custom-functions/{customFunctionId} corespondent o detașează.
  4. Completează biblioteca media. POST /v1/agents/{agentId}/media-library încarcă un element (JSON cu base64Data, mimeType, title, description); GET listează elementele agentului, iar PATCH/DELETE pe /{itemId} actualizează sau elimină unul.
  5. Capturează-l ca instantaneu.
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
  }'

De acolo, se aplică secțiunea anterioară: marchează-l ca implicit, astfel încât fiecare client nou să îl aibă preinstalat, sau aplică-l la cerere. Administrarea se face în paralel: PATCH /v1/snapshots/{snapshotId} cu { "name": "..." } redenumește unul, DELETE /v1/snapshots/{snapshotId} șterge unul (și elimină marcajul dacă era cel implicit), iar GET /v1/snapshots/apply-targets listează fiecare cont în care ai putea face instalarea.

Endpoint-urile pentru agent, funcții personalizate și media acceptă toate sub_account_id, astfel încât aceleași apeluri pot menține un agent direct în contul unui client. Apelurile pentru instantanee acționează întotdeauna asupra contului tău de agenție — șablonul rămâne la tine. Schemele complete de cerere și răspuns pentru toate acestea se află în Referința API.


Gestionați-vă nivelurile de preț prin API

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

Planurile pe care le vindeți în Mod SaaS → Niveluri de preț pot fi citite și modificate din cod, astfel încât propriul panou de administrare sau scriptul de aprovizionare poate adăuga un plan, ajusta un preț sau oferi un link de finalizare a comenzii fără ca cineva să deschidă tabloul de bord. Autentificați-vă cu cheia API a agenției ca la orice alt apel de pe această pagină; aceste puncte finale sunt la nivel de agenție, deci nu necesită sub_account_id. Fiecare scriere rulează aceeași validare și aceeași sincronizare a produselor și prețurilor Stripe ca și salvarea din tabloul de bord, deci un plan creat aici este indistinguibil de unul configurat manual.

Listați-vă nivelurile

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

Răspuns

{
  "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
  }
}

Fiecare nivel revine cu tierIndex-ul său — poziția sa în lista de Planuri, care este modul în care celelalte trei apeluri îl adresează — și un checkout_url gata de partajat, același link pe care vi-l oferă fila Plăți, care indică deja domeniul white label pe care este vândut acel plan.

Adăugați un nivel

Corpul este un obiect de nivel; acesta este adăugat la sfârșitul listei dvs.

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

Răspunsul conține nivelul creat, inclusiv tierIndex-ul pe care a aterizat și checkout_url-ul său.

Editați un nivel

Trimiteți doar câmpurile pe care doriți să le modificați; tot restul planului rămâne așa cum a fost.

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

Un câmp pe care API-ul nu îl recunoaște este refuzat în loc să fie ignorat, iar eroarea îl numește — astfel încât o greșeală de scriere nu poate scrie niciodată în liniște o setare care pare activă, dar nu face nimic. Modificarea prețului, a creditelor, a monedei sau a frecvenței de facturare creează un preț nou în Stripe; clienții care s-au abonat deja rămân la ceea ce au ales inițial.

Ștergeți un nivel

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

Aceeași regulă ca în tabloul de bord: un plan care are încă abonați activi nu poate fi șters. Cererea revine refuzată, spunându-vă câți abonați sunt pe acesta — anulați sau migrați-i mai întâi. O ștergere reușită răspunde cu nivelurile rămase, deja renumerotate.

Câmpurile de pe un nivel

Câmp Ce este
label / description Numele planului și linia opțională afișată pe pagina ta de finalizare a comenzii.
credits Credite pe care clientul le primește pe lună într-un plan lunar sau anual și pe perioadă de facturare într-unul săptămânal.
price_cents Prețul pe interval de facturare, în cea mai mică unitate monetară (2900 = $29.00). Într-un plan anual, acesta este prețul pentru întregul an.
currency Cod ISO cu litere mici — usd, eur, gbp și așa mai departe.
billing_interval / billing_interval_count month (implicit), year, sau week cu un număr de 1–52 pentru “la fiecare N săptămâni”.
trial_days Durata perioadei de probă gratuită, de la 0 la 90. 0 (sau omiterea acesteia) înseamnă fără perioadă de probă.
trial_credits Credite cu care clientul începe perioada de probă. Implicit este credits al planului.
trial_card_required false permite clientului să înceapă perioada de probă fără a introduce un card. Implicit este true.
trial_hard_expiry true returnează creditele neutilizate din perioada de probă în fondul tău și blochează contul clientului când o perioadă de probă se termină fără un upgrade. Implicit este false — vezi Expirare strictă după perioada de probă.
rollover_cap_months Luni de alocație pe care clienții din acest plan le pot păstra între reînnoiri — un număr de la 0 la 120, fracțiile sunt permise. 0 nu reportează nimic; null (implicit) înseamnă fără limită. Vezi Limitarea a ceea ce se reportează.
rollover_expiry_days Zile după care creditele neutilizate sunt eliminate la următoarea reînnoire — un număr întreg de la 1 la 3650. null (implicit) înseamnă că nu expiră niciodată.
features / feature_settings Ce primesc clienții din acest plan — aceleași ID-uri de funcționalități ca la Alege ce tipuri de canale poate conecta un client.
team_seats_limit Locuri în echipă pe care planul le oferă: un număr exact, 0 pentru niciunul, -1 pentru nelimitat.
white_label_config Pe care dintre domeniile tale white label este vândut planul.

Câmpurile pentru perioada de probă au sens doar pentru un plan care are o perioadă de probă: salvează un nivel cu trial_days: 0 și acestea vor fi eliminate. ID-urile de produs și preț Stripe ale planului sunt gestionate pentru tine și nu pot fi setate manual.

Trei aspecte de reținut:

  • Indicii de nivel sunt poziții, nu ID-uri permanente. Ștergerea unui plan mută fiecare plan ulterior cu o poziție mai jos, așa că reîncărcați lista după orice modificare — și copiați din nou linkurile de checkout pe care le-ați publicat, exact așa cum ați face după ștergerea unui plan din tabloul de bord.
  • Modul SaaS trebuie configurat mai întâi. Aceste endpoint-uri necesită un cont de agenție cu white labeling și o cheie Stripe deja salvată; fără acestea, nu există niciun cont Stripe pe care să poată fi găzduite produsul și prețul planului.
  • Douăzeci de planuri este limita maximă, la fel ca în tabloul de bord. Câmpul max_tiers din răspunsul listei vă indică limita curentă.

Schemele complete de cerere și răspuns se află în Referința API, sub secțiunea Agenție.


Setează prețul per credit prin API

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

Prețul pe care clienții îl plătesc pentru reîncărcări ad-hoc (Mod SaaS → Preț per credit) poate fi citit și modificat și din cod. Această funcționalitate este creată pentru situațiile în care prețul trebuie să se ajusteze automat: o agenție care vinde credite într-o monedă, dar facturează în alta, poate lăsa un job programat să revizuiască prețul pe măsură ce cursul valutar se modifică, în loc ca cineva să îl editeze manual în fiecare săptămână.

Citește prețul curent

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

Răspuns

{
  "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 este cel mai mic preț permis de platformă în acea monedă, astfel încât un job poate verifica un preț nou înainte de a-l trimite. Toate cele trei valori sunt null până când un preț a fost setat.

Modifică-l

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

Trimite doar ceea ce dorești să modifici. price_per_credit_cents este prețul în cea mai mică unitate monetară (130 = 1,30 R$); currency este un cod ISO cu litere mici; note este un rând opțional de până la 200 de caractere afișat clienților direct sub prețul per credit pe pagina lor de Facturare — util pentru un preț de referință în altă monedă, cum ar fi “0,25 USD per credit la cursul nostru de referință”. Trimite "note": "" pentru a-l elimina. Răspunsul are aceeași formă ca cel de citire de mai sus, astfel încât un job poate compara și omite scrierea atunci când nimic nu s-a schimbat.

Se aplică aceleași reguli ca în tabloul de bord: prețul nu poate scădea sub minimul platformei pentru acea monedă, iar contul trebuie să aibă activată funcția de white labeling. Spre deosebire de endpoint-urile pentru nivelurile de preț, nu este necesară nicio cheie Stripe pentru a citi sau modifica această valoare.

Oferă unui job o cheie care nu poate face nimic altceva

Introducerea cheii complete a agenției într-un programator oferă mai multe drepturi de acces decât sunt necesare pentru o actualizare de preț. În schimb, generează o cheie cu domeniu limitat (scoped key) restricționată la zona Preț Credit Agenție: acea cheie poate citi și modifica prețul per credit și nimic altceva — nu poate accesa sub-conturi, planuri, credite sau conexiunea ta Stripe.

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

Răspunsul conține noua cheie în api_key o singură dată — nu va mai fi afișată niciodată, așa că salveaz-o imediat. Setează "read_only": true pentru o cheie care trebuie doar să citească prețul și adaugă "expires_at" (o dată ISO) dacă dorești ca aceasta să înceteze să mai funcționeze automat. Doar cheia proprietarului contului poate crea chei cu domeniu limitat; listează-le sau revocă-le folosind GET /v1/api-keys și DELETE /v1/api-keys/{id}.


Permiteți unui sub-cont să vă citească prețurile

GET /v1/subaccounts/agency-pricing

Fiecare alt endpoint de pe această pagină este apelat cu cheia de agenție, vizând opțional un client prin sub_account_id. Acesta este opusul: este apelat cu propria cheie API a sub-contului, fără sub_account_id, astfel încât pagina proprie de reîncărcare a unui client (sau o integrare pe care o construiți pentru el) să poată afișa ceea ce îi taxați fără a vedea vreodată contul de agenție.

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

Răspuns

{
  "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"
  }
}

Acesta oglindește exact ceea ce returnează GET /v1/agency/pricing-tiers și GET /v1/agency/credit-price pentru dumneavoastră ca agenție, minus orice nu trebuie să vadă clientul (id-uri Stripe, max_tiers și așa mai departe). Funcționează doar pentru un cont care este efectiv un sub-cont cu o agenție conectată — apelarea acestuia din propriul cont de agenție returnează o eroare de permisiune.


Aspecte de reținut

  • Folosiți cheia de agenție. Autentificați fiecare apel cu cheia API a contului de agenție — nu a sub-contului. Parametrul sub_account_id este cel care redirecționează acțiunea.
  • Creditele provin din sub-cont. Achizițiile și taxele recurente sunt deduse din soldul de credit al sub-contului vizat, nu din al dumneavoastră.
  • O eroare 404 înseamnă „nu este sub-contul dumneavoastră”. Verificați din nou ID-ul și asigurați-vă că este un cont pe care îl gestionați.
  • Parametrul este opțional peste tot unde este acceptat. Omiteți-l și același endpoint va acționa asupra contului de agenție, astfel încât să puteți reutiliza o singură integrare pentru ambele.

Legate

  • Acces API — autentificare, URL de bază, erori, limite de rată.
  • Sub-conturi — listați și gestionați conturile pe care le puteți viza.
  • Reîncărcare automată sub-cont — acordați credite unui sub-cont prin webhook + API.
  • API Campanii — creați, actualizați și copiați campanii, inclusiv referința completă a câmpurilor.
  • API Conexiune Canal — conectați canalele unui client și direcționați-le către o campanie.
  • Ghid API Analiză (în secțiunea API) — centralizarea sub-conturilor agenției și orice alt endpoint de raportare.
  • Instantanee — ce captează un instantaneu și cum să construiți unul în tabloul de bord.