API per le agenzie
Come agenzia, puoi utilizzare la stessa API REST usata dai tuoi clienti, ma indirizzando le singole richieste a uno dei tuoi sotto-account gestiti invece che al tuo account. Questo ti permette di creare strumenti che gestiscono l’onboarding di un cliente dall’inizio alla fine: creando le sue campagne, addestrando la sua IA su una base di conoscenza, importando i suoi contatti, collegando i suoi canali di messaggistica e acquistando numeri di telefono, il tutto senza dover accedere manualmente a ogni sotto-account.
Questa pagina tratta solo il comportamento specifico per le agenzie: come agire per conto di un sub-account con il parametro sub_account_id. Per le nozioni di base (generazione di una chiave, autenticazione, URL di base, formato degli errori, limiti di frequenza), inizia dalla guida Accesso API. Tutto ciò che è riportato lì si applica anche qui: l’autenticazione avviene con la chiave API del tuo account agenzia.
Nota: Questa pagina è tecnica. Se non sei uno sviluppatore, condividila con la persona che sta creando la tua integrazione.
Come funziona l’“agire per conto di”
Per impostazione predefinita, ogni richiesta API agisce sull’account che possiede la chiave API, ovvero il tuo account agenzia. Per agire invece su un account cliente gestito, aggiungi alla richiesta il parametro opzionale sub_account_id, impostandolo sull’id dell’account di quel cliente.
- Ometti
sub_account_id→ la richiesta agisce sul tuo account agenzia. - Includi
sub_account_id→ la richiesta agisce su quel sub-account, ma solo dopo che la piattaforma ha confermato che il sub-account è effettivamente tuo.
Ti autentichi sempre con la chiave API del tuo account agenzia. Non hai mai bisogno della chiave del sub-account e non gestisci mai le credenziali del sub-account.
Dove inserirlo
- Endpoint GET / DELETE → passalo come parametro di query:
?sub_account_id=THE_SUB_ACCOUNT_ID(insieme al tuoapiKey, se ti autentichi tramite query). - Endpoint POST / PUT / PATCH → includilo nel corpo della richiesta JSON come
"sub_account_id": "THE_SUB_ACCOUNT_ID". - Assistenti IA → nulla da configurare. Il server MCP mantiene la stessa impostazione sui suoi strumenti di lettura, quindi una connessione con la tua chiave di agenzia può generare report su ogni cliente: basta nominare il cliente nella tua richiesta (“quanti contatti ha Bella’s Bistro?”). Sono disponibili anche azioni di scrittura: ogni endpoint che accetta
sub_account_idviene esposto come strumento, così puoi creare, modificare e inviare per conto di un cliente dalla stessa connessione.
Trovare l’id di un sub-account
Il sub_account_id è l’id univoco dell’account cliente. Puoi ottenere l’elenco dei tuoi sotto-account e i relativi id dagli endpoint dell’API SubAccounts (consulta la guida Sub-Accounts) o dalla pagina Sub Accounts nella barra laterale.
La proprietà viene sempre verificata
Quando passi un sub_account_id, la piattaforma verifica che l’account sia un sub-account reale e che appartenga alla tua agenzia. Solo allora la richiesta viene elaborata.
Se l’id è sconosciuto, non è un sub-account o appartiene a un’altra agenzia, la richiesta fallisce con una risposta 404:
{
"success": false,
"error_code": 404,
"error": "Sub-account not found."
}
Perché 404 e non 403? Una risposta “forbidden” (vietato) comunicherebbe a un estraneo che l’id esiste ma non gli appartiene. Restituire lo stesso
404per “non esiste” e “non è tuo” significa che l’endpoint non può essere utilizzato per scoprire quali id account appartengono ad altre agenzie. Considera un404qui come “questo non è un sub-account che gestisci.”
Dove è supportato sub_account_id
sub_account_id è accettato praticamente su ogni endpoint di risorsa: qualsiasi chiamata che crea, legge, aggiorna o elimina i dati di un account. In pratica, puoi eseguire il provisioning e gestire l’intera configurazione di un sotto-account con la tua chiave di agenzia:
- Configurazione IA — campagne, agenti, FAQ, fonti della base di conoscenza (scansione sito web e caricamento documenti), gruppi della base di conoscenza, trasmissioni, funzioni personalizzate, server MCP
- Contatti e CRM — contatti (inclusa l’importazione), liste, tag, attività, trattative, appuntamenti, eventi
- Canali e numeri — collega WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE, cerca / acquista / gestisci numeri di telefono, modelli WhatsApp, instradamento canali
- Messaggistica e contenuti — invia messaggi, sessioni di chat, esportazioni chat, riepiloghi giornalieri
- Impostazioni e integrazioni — webhook, configurazione widget chat, configurazione white-label, SMS BYOK e altre impostazioni dell’account, analisi
Per ognuno di questi, il parametro è facoltativo: se lo ometti, la chiamata agirà sul tuo account di agenzia, quindi un’unica integrazione serve entrambi. Crediti e utilizzo provengono sempre dall’account a cui ti rivolgi: gli addebiti per campagne, messaggi, tag e numeri di un sotto-account incidono sul saldo del sotto-account.
Dove NON si applica
Alcuni endpoint sono a livello di agenzia o auto-indirizzati e ignorano sub_account_id:
- Gestione dei sotto-account stessi — gli endpoint SubAccounts (creazione / elenco / aggiornamento di un sotto-account) e l’endpoint per il limite di spesa BYOK indicano già il sotto-account nel proprio percorso URL. Gli endpoint di prezzi e policy e gli endpoint di monitoraggio chat seguono lo stesso schema.
- Copia di un Agente tra account —
POST /v1/subaccounts/agents/copyindica entrambi gli account, prendendo la destinazione cometargetUserId. Vedi l’esempio pratico qui sotto. (Il vecchioPOST /v1/subaccounts/campaigns/copyfunziona allo stesso modo ma è deprecato insieme al resto della Campaigns API.) - Regolazione dei crediti e i due rollup a livello di agenzia —
POST /v1/subaccounts/creditsidentifica il sotto-account tramiteemail;GET /v1/subaccounts/credit-usageeGET /v1/subaccounts/campaign-statusgenerano report su ogni sotto-account contemporaneamente, quindi non c’è un singolo account da gestire. - Il tuo account di agenzia — La gestione delle chiavi API, i report sull’utilizzo dell’agenzia, la gestione del team e i tuoi livelli di prezzo agiscono sempre sul tuo account di agenzia.
- Webhook per messaggi in entrata — gli endpoint in cui i sistemi esterni inviano dati verso l’interno sono legati all’account le cui credenziali li hanno configurati, quindi non c’è nulla da reindirizzare.
L’elenco sempre aggiornato e leggibile dalle macchine dei parametri accettati da ciascun endpoint si trova nel riferimento API della tua dashboard (Settings → Integrations → API Key) e nella specifica OpenAPI all’indirizzo
GET /v1/docs/openapi.yaml. Rilasciamo spesso modifiche alle API: considerale come la fonte di verità.

Impostazioni → Integrazioni → Chiave API — la chiave della tua agenzia si trova qui, insieme al link al riferimento completo dell'API.
Esempio pratico: connettere Instagram e Messenger per un sub-account
La connessione di Instagram e Messenger è un flusso basato su browser. Si avvia tramite API, si fornisce l’URL di consenso restituito al cliente (o lo si apre per lui), si attende che autorizzi nel suo browser, quindi si sceglie quale pagina connettere — il tutto puntando al suo sub-account con sub_account_id.
Passaggio 1 — Avviare la connessione
Chiama l’endpoint di connessione con il sub_account_id del cliente nel body. Qui non vengono inviate credenziali; la piattaforma restituisce un URL di consenso che il cliente deve aprire in un browser, oltre a un token di correlazione monouso.
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
Risposta:
{
"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"
}
Invia il cliente a oauth_url in un browser per autorizzare. Il state_token correla questo tentativo ed è un segreto a breve termine — non registrarlo. Il tentativo scade a expires_at; se scade, ricomincia.
Passaggio 2 — Eseguire il polling fino al caricamento delle pagine
Dopo che il client ha autorizzato, esegui il polling dell’endpoint di stato (con lo stesso sub_account_id, questa volta come parametro di query) finché non appaiono le pagine collegabili.
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"]
Risposta:
{
"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
}
Il campo status passa attraverso pending → token_received → pages_loaded → connected. Attendi pages_loaded prima di selezionare una pagina. Possono apparire anche due stati di errore terminale invece di procedere: failed e expired (il cliente ha rifiutato il consenso o la finestra di circa 30 minuti del token di stato è scaduta) — un campo reason viene incluso quando si verifica uno di questi casi. Interrompi il polling e riavvia dal passaggio 1 se ne vedi uno; non attendere pending all’infinito. I token di accesso alla pagina non vengono mai restituiti.
Passaggio 3 — Seleziona la pagina da collegare
Scegli uno degli ID pagina dal Passaggio 2 e selezionalo. Selezionando una pagina si collegano sia Instagram che Messenger per quella pagina. Includi nuovamente sub_account_id nel corpo.
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()
Risposta:
{
"success": true,
"page_id": "1098765432101234",
"instagram_business_account_id": "17841400000000000"
}
Ecco fatto: Instagram e Messenger sono ora collegati al sub-account del client. Hai fornito solo page_id; la credenziale sottostante viene risolta sul server e non passa mai attraverso la tua integrazione.
Esempio pratico: acquisto di un numero per un sub-account
L’acquisto di un numero funziona allo stesso modo: cerca con sub_account_id nella query, quindi acquista inserendolo nel corpo. I crediti vengono detratti dal saldo del sub-account e il numero viene fornito sul sub-account.
Ricerca (cURL):
curl "https://api.dmchamp.com/v1/phone-numbers/available?apiKey=YOUR_API_KEY&country_code=US&sub_account_id=abc123def456"
Acquisto (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();
Acquisto (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()
Risposta:
{
"success": true,
"phone_number": "+14155551234",
"channel": "whatsapp",
"whatsapp_status": "PURCHASED",
"outgoing_status": "PURCHASED",
"status": "PURCHASED",
"purchase_credits": 11.5,
"monthly_credits": 11.5
}
Il numero viene fornito nello stato PURCHASED e la registrazione del mittente WhatsApp continua in background. Esegui il polling di GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456 finché lo stato non raggiunge ONLINE prima di inviare.
Esempio pratico: inviare un Agente modello a ogni nuovo cliente
Il modello tipico di un’agenzia consiste nel mantenere un Agente principale sull’account dell’agenzia, configurato come si desidera che ogni cliente inizi, e crearne una copia in ogni nuovo sotto-account al momento del provisioning. Si tratta di tre chiamate e non è necessario ripetere nulla in seguito: la copia mantiene le sue impostazioni finché non le modifichi.
Passaggio 1 — Copiare l’Agente
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
}'
La risposta contiene l’id del nuovo Agente in data.agent_id. Le FAQ, la knowledge base e la libreria multimediale vengono trasferite; i modelli WhatsApp, i post social collegati e i contatti dell’account di origine non vengono trasferiti intenzionalmente. Elenco completo dei campi nell’AI Agents API.
Nota che questo endpoint utilizza targetUserId invece di sub_account_id: indica entrambi gli account. Le due chiamate seguenti utilizzano il normale parametro sub_account_id.
Passaggio 2 — Attivarlo
La copia arriva sempre in pausa, quindi non può inviare messaggi a nessuno finché non lo decidi tu. Questo è anche il momento di fissare il livello AI che vuoi assegnare al cliente; rimarrà impostato, quindi non c’è bisogno di riapplicarlo secondo una pianificazione.
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" }'
Per impedire al cliente di modificare il livello in seguito, blocca i livelli consentiti sul sotto-account invece di inviare nuovamente il valore.
Passaggio 3 — Collegamento dei canali del cliente
La copia arriva anche senza routing, quindi nulla la raggiunge finché non la rendi il risponditore sui canali che il cliente ha collegato. Una chiamata per canale:
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" }'
Da qui, un primo messaggio da un contatto sconosciuto su quel canale viene intercettato automaticamente dall’Agente copiato. Vedi Indirizzare un canale verso un Agente per gli altri canali e il routing per numero.
Imposta il fuso orario del cliente quando crei il sotto-account. Passa
time_zone_idsuPOST /v1/subaccounts. Gli orari di attività della campagna vengono valutati nel fuso orario del sotto-account, quindi un cliente creato senza di esso vedrà la sua pianificazione letta rispetto all’UTC — il che sposta silenziosamente gli orari in cui all’assistente è consentito rispondere.
Ignora la procedura guidata di configurazione per un cliente che configuri personalmente
POST /v1/subaccounts
Per impostazione predefinita, la prima volta che il proprietario di un nuovo sub-account effettua l’accesso, viene guidato attraverso la procedura guidata di configurazione (Setup Wizard). Per i clienti “chiavi in mano” — dove sei tu a creare la campagna e a collegare i canali prima ancora che il cliente acceda — passa guided_onboarding: false al momento della creazione dell’account. Il cliente verrà indirizzato direttamente alla dashboard e la voce Setup Wizard sarà nascosta dalla sua barra laterale.
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 }
}'
Ometti il campo (o invia true) e la procedura guidata si comporterà esattamente come ha sempre fatto, quindi le integrazioni esistenti non necessitano di modifiche. Per restituire la procedura guidata a un cliente in un secondo momento, mostra nuovamente l’elemento guided_onboarding con PUT /v1/subaccounts/{subAccountUid}/menu-visibility (di seguito) — la visibilità del menu controlla se la procedura guidata è raggiungibile, guided_onboarding controlla solo il reindirizzamento al primo accesso.
Disattiva Attività, Riepiloghi giornalieri o Libreria multimediale per un cliente
POST /v1/subaccounts
Queste tre funzioni sono attive per ogni nuovo cliente a meno che non venga specificato diversamente, e si comportano in modo diverso rispetto a qualsiasi altra funzionalità in questa guida: sono opt-out, non opt-in. Escluderle da features non è sufficiente di per sé, perché l’elenco features di un’integrazione precedente semplicemente non le menzionava: non possiamo distinguere tra “l’agenzia ha disattivato questa funzione” e “questo elenco è stato scritto prima che l’opzione esistesse”.
Quindi dichiaralo esplicitamente con 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
}
}'
Ogni chiave è facoltativa; tutto ciò che viene omesso rimane attivo. Con tasks: false l’IA smette di creare attività per quel cliente e non vengono inviate email di “Nuova attività creata”; con daily_summaries: false il riepilogo notturno non viene mai generato né inviato via email.
feature_settings è l’unica cosa che disattiva queste tre funzioni al momento della creazione. Escluderle da features non ha alcun effetto di per sé, indipendentemente da come appare il resto dell’elenco: è una scelta deliberata, affinché un’integrazione precedente non perda silenziosamente tutte e tre le funzioni.
Per modificare tutto ciò in un secondo momento, invia l’elenco features completo a PUT /v1/subaccounts/{subAccountUid}/features: in quel caso, la presenza nell’elenco attiva una funzionalità e l’assenza la disattiva.
Effettua l’auto-login dei tuoi clienti nel loro sotto-account (SSO)
POST /v1/subaccounts/{subAccountUid}/sso-link
Una chiamata con la chiave API della tua agenzia restituisce un URL pronto all’uso che collega il cliente direttamente al proprio sotto-account: nessuna schermata di login, nessun passaggio per la password, nulla da sviluppare. Aprilo in una nuova scheda, tramite un redirect o in un iframe all’interno del tuo prodotto.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
redirect |
No | Pagina in-app su cui vuoi che il client approdi, ad es. "/chats" o "/agents". Restituito come deep_link_url nella risposta. |
app_base_url |
No | Host della dashboard per il link. Il valore predefinito è il dominio della tua app white-label (o il dominio della piattaforma se non ne hai uno). Deve essere 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" }'
Risposta
{
"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"
}
Come utilizzarlo al meglio:
- Un solo passaggio. L’apertura di
urlautentica il cliente e lo indirizza direttamente alla paginaredirectdella dashboard: nessuna schermata di login, nessuna pagina intermedia.deep_link_urlindica la stessa destinazione, per gli integratori che preferiscono navigare esplicitamente in un frame dopo il login; una volta creata la sessione, qualsiasi percorso della dashboard funziona in quel contesto del browser. - Generazione su richiesta, apertura immediata. Il link contiene una credenziale di accesso e scade dopo circa un’ora. Richiedilo lato server nel momento in cui il cliente clicca e non memorizzarlo né inviarlo mai via email.
- Il token di accesso viaggia nel frammento dell’URL (
#…), che i browser non inviano mai ai server, e viene rimosso dalla barra degli indirizzi nel momento in cui viene utilizzato. - Solo i tuoi sotto-account. L’endpoint rifiuta qualsiasi account che non sia di proprietà della tua agenzia.
- Un link scaduto mostra un errore chiaro con un percorso per riprovare: generane uno nuovo.
Nascondi elementi di navigazione su un sotto-account
PUT /v1/subaccounts/{subAccountUid}/menu-visibility
Controlla quali elementi della barra laterale e delle impostazioni vede un sotto-account: utile quando incorpori la dashboard e desideri solo le superfici che il tuo prodotto non copre già. Tutto ciò che non è elencato rimane visibile; invia null come intero valore menuVisibility per ripristinare la visibilità di tutto. Nascondere un elemento nasconde la voce di menu: abbinalo alle funzionalità che concedi al sotto-account per un controllo rigoroso.
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 }
}
}'
Risposta
{
"success": true,
"data": {
"subAccountUid": "SUB_ACCOUNT_UID",
"menuVisibility": {
"side_nav": { "Dashboard": false, "Campaigns": false, "Automations": false },
"settings_nav": { "team": false }
}
}
}
side_nav accetta queste 13 chiavi, che corrispondono ai nomi delle voci della barra laterale: Dashboard, DailySummaries, Chats, Contacts, Deals, Tasks, Automations, Campaigns, Appointments, Settings, Help, CreditsCounter (il saldo del credito mostrato nella barra laterale) e guided_onboarding (la procedura guidata di configurazione). Sono accettate altre tre chiavi — AiInsights, Sub Accounts e Agency Reselling — che però non eseguono alcuna azione: si applicavano solo alla dashboard classica ormai in disuso, pertanto la loro impostazione non ha alcun effetto sui tuoi sotto-account. Le chiavi mancanti indicano che l’elemento è visibile; quando accedi personalmente al sotto-account, gli elementi nascosti vengono mostrati temporaneamente in modo da poter sempre ripristinare le impostazioni.
Nascondere una pagina dal menu non ne garantisce mai l’accesso. Automations richiede che la funzionalità automations sia concessa sul sotto-account: imposta la chiave su true senza di essa e la pagina non apparirà comunque. Tasks e DailySummaries funzionano al contrario: sono attive per ogni cliente a meno che non vengano disattivate (vedi Disattiva Attività, Riepiloghi giornalieri o Libreria multimediale per un cliente).
Scegli quali tipi di canale un client può connettere
PUT /v1/subaccounts/{subAccountUid}/features
Gli interruttori Tipi di canale che vedi su un livello di piano sono normali ID funzionalità, quindi puoi impostarli per client dall’API invece che dalla dashboard. Questo è uno degli endpoint che nomina il sub-account nel proprio URL, quindi non richiede alcun sub_account_id.
| ID funzionalità | Canale |
|---|---|
channel_chat_widget |
Widget chat sito web |
channel_whatsapp_api |
API WhatsApp Business |
channel_whatsapp_web |
WhatsApp Web (numero collegato tramite QR) |
channel_instagram |
|
channel_messenger |
Facebook Messenger |
channel_telegram |
Telegram |
channel_line |
LINE |
channel_viber |
Viber |
channel_email |
Casella di posta elettronica |
channel_sms |
SMS |
channel_imessage |
iMessage |
curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/features" \
-H "X-API-Key: YOUR_AGENCY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"features": [
"channels_3",
"channel_chat_widget",
"channel_whatsapp_web",
"channel_instagram",
"image_understanding",
"contact_tagging",
"incoming_campaigns",
"webhooks"
]
}'
Tre cose da fare correttamente:
- La chiamata sostituisce l’intero elenco delle funzionalità. Invia ogni funzionalità che il client deve mantenere, non solo quelle che stai modificando. Gli stessi ID funzionano come
featuressuPOST /v1/subaccountsquando crei l’account. - I tipi di canale e il numero di canali sono blocchi separati ed entrambi si applicano.
channels_1/channels_3/channels_unlimitedcontrollano quante connessioni; gli IDchannel_*controllano quali tipi. L’esempio sopra significa “fino a 3 connessioni e solo Widget chat, WhatsApp Web o Instagram”. - Non inviare alcun ID
channel_*significa nessuna restrizione sui canali. Questo è il comportamento originale, motivo per cui i client esistenti non sono stati influenzati quando è stata rilasciata questa funzione. Inviandone uno o più, tutto il resto verrà visualizzato come bloccato nella pagina Canali del client con una nota di aggiornamento invece di un pulsante Connetti. I canali che il client ha già connesso continueranno a funzionare.
L’impostazione dell’elenco dei canali su un livello di piano, in modo che ogni client che acquista quel livello lo erediti, viene eseguita nella dashboard nelle impostazioni del tuo piano di agenzia. Questo endpoint lo imposta su uno specifico sub-account.
Imposta un limite esatto di membri del team per un cliente
PUT /v1/subaccounts/{subAccountUid}/limits
Le funzionalità team_seats_* offrono solo livelli predefiniti (3 / 5 / 10 / illimitato). Per assegnare a un cliente un numero esatto di posti nel team — 2, 7, 15, qualsiasi numero — imposta invece usage_limits.team_seats_limit. Questa impostazione prevale sui valori predefiniti e la piattaforma la applica a ogni invito, aggiunta diretta e accettazione di invito: una volta raggiunto il limite, ulteriori inviti vengono rifiutati lato server.
- Un numero intero positivo rappresenta il limite esatto.
0significa che i membri del team non sono inclusi — il cliente non può invitare nessuno.-1significa illimitato.nullcancella il limite personalizzato e ripristina qualsiasi valore predefinitoteam_seats_*presente nell’elenco delle funzionalità.
Ridurre il limite non rimuove mai i membri del team esistenti; impedisce solo l’aggiunta di nuovi membri.
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 }
}'
Puoi impostarlo anche al momento della creazione: POST /v1/subaccounts accetta usage_limits.team_seats_limit con la stessa semantica. Per leggere il valore corrente, recupera il sub-account con GET /v1/subaccounts?email=... e controlla usage_limits.team_seats_limit (assente/null = decidono le impostazioni predefinite). Lo stesso endpoint aggiorna anche credits, monthly_credits, roll_over_to_next_month, rollover_cap_months, rollover_expiry_days e byok_monthly_limit_usd — invia solo le chiavi che desideri modificare.
In che modo questo interagisce con i limiti di posti del piano SaaS. I tuoi piani SaaS possono avere una propria dotazione di posti (impostata nell’editor del piano — vedi Posti del team in un piano), che viene applicata automaticamente quando un cliente si abbona. Un limite impostato tramite questo endpoint viene conteggiato come una concessione manuale: l’acquisto di un piano lo sostituisce con la dotazione di posti del piano stesso (quell’acquisto è una scelta esplicita del piano), ma i rinnovi mensili automatici non sovrascrivono mai un limite manuale; pertanto, un’eccezione una tantum concessa a un cliente rimane valida per tutto il suo ciclo di fatturazione. L’eliminazione del limite manuale con null restituisce il controllo del campo al piano al momento del rinnovo successivo.
Limita ciò che un cliente trasporta tra i rinnovi. Altre due chiavi usage_limits si trovano accanto a roll_over_to_next_month. Entrambe sono accettate anche da POST /v1/subaccounts al momento della creazione, e null le cancella entrambe.
| Chiave | Cosa fa |
|---|---|
rollover_cap_months |
Mesi di credito che il cliente può conservare. Un numero da 0 a 120, sono consentite frazioni (0.5 = mezzo mese). A ogni rinnovo, il saldo inutilizzato viene ridotto al massimo a questo numero di volte il credito concesso dal rinnovo, prima che vengano aggiunti i nuovi crediti; 0 non trasporta nulla. |
rollover_expiry_days |
Un numero intero di giorni, da 1 a 3650. I crediti rimasti inutilizzati per così tanto tempo vengono eliminati al primo rinnovo dopo aver raggiunto tale età. La spesa viene sempre detratta dai crediti più vecchi, quindi un cliente che spende il proprio credito ogni mese non ne perde mai nessuno. |
Se non impostati, entrambi tornano al piano del cliente; un valore inviato qui prevale su quello del piano. Solo i crediti ricorrenti (il credito mensile e i crediti del piano) ne sono soggetti: le ricariche, i rinnovi automatici e le aggiunte una tantum non vengono mai limitati o fatti scadere. Ogni riduzione viene scritta nella cronologia dei crediti del cliente come Rollover Cap Credit Adjustment o Expired Credits Credit Adjustment e non viene mai conteggiata come utilizzo. Gli equivalenti a livello di piano sono rollover_cap_months e rollover_expiry_days su un livello di prezzo — vedi I campi su un livello e Limitare ciò che viene trasportato.
Imposta prezzi e policy IA per cliente
PUT /v1/subaccounts/{subAccountUid}/max-tier · /ai-tiers · /max-rate · /action-pricing · /insider-rate · /locked-bot-fields · /notifications · /zero-credit-reply
Altri otto interruttori per cliente, insieme a /limits, /features e /menu-visibility sopra. Ognuno prende l’uid del sub-account nell’URL (nessun parametro sub_account_id nel corpo/query — l’obiettivo è già nominato nel percorso) ed è limitato allo stesso modo: la tua chiave di agenzia, e il sub-account deve appartenere alla tua agenzia.
Quali modelli IA può utilizzare un cliente
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 } abilita (o disabilita) il cliente al livello Max AI — la nostra infrastruttura al prezzo di listino della piattaforma. Attivare questa opzione per un cliente BYOK cambia il costo della sua IA da “gratuito con la mia chiave” a “addebitato sul mio pool di crediti”, quindi è una decisione deliberata per singolo cliente piuttosto che un’impostazione predefinita per l’intera agenzia.
Per limitare i livelli da cui le campagne e gli Agenti di un cliente possono scegliere (invece di limitare solo Max), usa 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 è un array tratto da standard, economy, max, mini — SOSTITUISCE l’elenco consentito del cliente. Invia null (o []) per cancellare la restrizione e consentire loro di scegliere qualsiasi livello. Questo è importante perché un sub-account che sceglie il proprio livello IA spende dal tuo pool di crediti, quindi è la leva per stabilire quali modelli un cliente rivenditore può utilizzare a tue spese.
Una risposta di attesa mentre il cliente è senza crediti
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." }'
Quando il saldo del cliente (o il tuo pool) è vuoto, l’IA non può rispondere e il contatto non riceve nulla. Con enabled: true, ogni contatto che scrive durante l’interruzione riceve message una volta (massimo 500 caratteri, inviati così come sono su ogni canale), e l’IA risponde a quelle conversazioni concretamente una volta che i crediti sono tornati. enabled: false conserva il testo salvato per dopo; enabled: false senza message rimuove l’impostazione. Stesso interruttore di Risposta di attesa quando si è senza crediti nel modale Modifica del sub-account — vedi Una risposta di attesa mentre un cliente è senza crediti.
Cosa paga un cliente per azione IA e il ricarico sulla tariffa WhatsApp
Due modi per impostare la tua tariffa rivolta al cliente, dal più semplice al più granulare:
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 è il prezzo in crediti che il saldo PROPRIO del sub-account consuma per ogni azione IA del modello Max — il tuo ricarico rivolto al cliente oltre a ciò che il tuo pool paga effettivamente. null ripristina l’override al prezzo di listino della piattaforma. La tariffa deve essere almeno pari al costo di un’azione Max per il tuo pool (così non puoi mai far pagare un cliente meno del tuo costo) e non superiore a 10 crediti; una richiesta al di fuori di tale finestra viene rifiutata con il limite minimo calcolato nel messaggio di errore.
Per prezzi basati sul tipo di azione invece di una tariffa fissa Max, usa 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 è una FUSIONE sulla mappa esistente del cliente — una chiave che non menzioni viene lasciata com’era, e null reimposta quella chiave al suo valore predefinito. Le chiavi riconosciute:
| Chiave | Prezzi |
|---|---|
AI_MESSAGE |
Una risposta IA |
AI_TOOL_USE |
Una chiamata a uno strumento IA |
EVALUATION_CALL |
Un passaggio di valutazione chat |
INTERRUPTION_HANDLING |
Gestione di un’interruzione durante la risposta |
CONTACT_TAG |
Un tag contatto assegnato dall’IA |
CHAT_SUMMARY |
Un riepilogo chat |
wa_carrier_multiplier |
Un moltiplicatore di ricarico applicato a ogni tariffa WhatsApp non IA che il cliente paga: affitto mensile del numero, tariffe di consegna su corsia gestita e costi di transito dei template Meta/Twilio. |
Le tariffe per azione devono essere un numero superiore a 0 e fino a 10; wa_carrier_multiplier deve essere almeno 1 (nessuno sconto al di sotto del costo) e fino a 10. L’invio di una chiave non riconosciuta, o di un valore fuori intervallo, rifiuta l’INTERA richiesta e indica ogni chiave non valida, in modo che un errore di battitura non possa mai salvare silenziosamente un prezzo che non viene effettivamente applicato.
Se sei un membro del Champions Circle, insider-rate trasmette la tua tariffa scontata del 20% per Max/Lead Finder a un solo cliente invece di applicarla a tutta l’agenzia:
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 }'
Attivarlo richiede che il tuo account agenzia detenga effettivamente l’iscrizione al Circle; disattivarlo non lo richiede mai, quindi un membro scaduto può sempre riportare un cliente al livello precedente.
Blocca sezioni del playbook di un cliente
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 è un array tratto da instructions, goal, rules, personality, conclude_unless — SOSTITUISCE l’elenco bloccato del cliente. Una sezione bloccata viene rifiutata lato server se il SUB-ACCOUNT stesso tenta di modificarla (direttamente o tramite chiave API), mentre tu (tramite sub_account_id) e la vista amministratore della dashboard del cliente potete ancora modificare tutto. Invia null (o []) per sbloccare tutto. Utile per i clienti “done-for-you” dove sei tu a possedere il playbook e vieni giudicato in base al risultato.
Imposta le preferenze di notifica di un cliente per suo conto
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 sostituisce l’intero set di preferenze di notifica del cliente (non è un merge per chiave: invia ogni categoria che vuoi mantenere, in modo corrispondente a come la salva la pagina Impostazioni del sub-account). Ogni categoria sotto settings accetta enabled (booleano) e fino a tre channels da email, in_app, webhook. Invia null per ripristinare le impostazioni predefinite della piattaforma.
Tutti e sette gli endpoint rispondono { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } } e vengono registrati nel log di controllo con il valore prima/dopo. Errori comuni: 403 se il tuo account non è Agency/Dev o il sub-account non è di tua gestione, 400 se non è un sub-account di agenzia o un valore è fuori intervallo.
Sospendi un cliente che ha interrotto il proprio abbonamento
POST /v1/subaccounts/{subAccountUid}/pause · POST /v1/subaccounts/{subAccountUid}/unpause
Quando un cliente sospende il proprio abbonamento con te, metti in pausa il suo account invece di eliminarlo: tutto ciò che invia si interrompe immediatamente — messaggi in uscita, broadcast, risposte AI su ogni canale — e quando accede, visualizza un blocco a schermo intero Account sospeso (con il tuo messaggio opzionale) invece dell’app. Nulla viene eliminato o disconnesso: agenti, campagne, canali collegati, contatti e cronologia chat rimangono esattamente come sono, quindi la riattivazione riporta il cliente esattamente dove aveva interrotto — nessuna configurazione da rifare.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
message |
No | Mostrato al cliente sulla schermata di blocco. Lascialo vuoto per il testo predefinito. |
reason |
No | Nota interna all’agenzia archiviata con la sospensione e nel registro di controllo — mai mostrata al cliente. |
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" }'
Risposta
{
"success": true,
"data": {
"subAccountUid": "SUB_ACCOUNT_UID",
"paused": true,
"level": "hard_blocked"
}
}
Quando il cliente ritorna, POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (nessun corpo) rimuove il blocco — l’invio e le risposte AI riprendono immediatamente.
Cose da sapere:
- È lo stesso stato dell’interruttore Blocco totale della dashboard (Blocco / Sospensione di un sub-account) — un cliente messo in pausa tramite API appare come bloccato nella dashboard e viceversa, e la riattivazione rimuove un blocco applicato da entrambi i lati. Lo stato attuale è leggibile dal campo
agency_blocksuGET /v1/subaccounts(leveldi"none","soft_blocked"o"hard_blocked"). - Entrambe le chiamate sono idempotenti. Mettere in pausa un cliente già in pausa aggiorna solo il messaggio, il motivo e il timestamp; riattivare un cliente attivo non cambia nulla.
- Il cliente non riceve email automaticamente — molte agenzie utilizzano il white-label, quindi spetta a te informare il cliente.
- La tua fatturazione DM Champ rimane invariata. Mettere in pausa un cliente influisce solo sul tuo rapporto con lui.
- Anche gli assistenti AI possono farlo: il server MCP espone questi endpoint come strumenti
pause_subaccounteunpause_subaccount.
Assegna o detrai crediti direttamente
POST /v1/subaccounts/credits
Aggiunge o rimuove un importo esatto di crediti dal saldo di un sub-account — l’equivalente API della regolazione manuale dei crediti della dashboard. Si tratta di una variazione del saldo una tantum, distinta dalle impostazioni ricorrenti monthly_credits, roll_over_to_next_month, rollover_cap_months e rollover_expiry_days su PUT /v1/subaccounts/{subAccountUid}/limits.
Questo è l’unico endpoint in questa pagina che identifica il sub-account tramite email anziché sub_account_id.
| Campo | Obbligatorio | Descrizione |
|---|---|---|
email |
Sì | L’email del sub-account, così come esiste sotto la tua agenzia. |
amount |
Sì | Numero di crediti diverso da zero. Positivo aggiunge, negativo detrae. |
description |
No | Mostrato accanto alla rettifica nella cronologia crediti del cliente. Per impostazione predefinita è una riga generica “Rettificato dall’agenzia tramite 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" }'
Risposta
{
"success": true,
"data": {
"email": "client@example.com",
"previous_balance": 1200,
"adjustment": 500,
"new_balance": 1700
}
}
Un amount negativo che porterebbe il saldo sotto lo zero viene rifiutato con 400, indicando il saldo disponibile e quanto hai tentato di detrarre. Se il cliente utilizza la propria fatturazione Stripe (modalità rivenditore), un importo aggiunto conta anche come crediti acquistati, quindi sopravvive al successivo ripristino mensile allo stesso modo di una vera ricarica; su un cliente con allocazione standard, viene trattato come parte del suo credito ricorrente. In entrambi i casi si tratta di un’aggiunta una tantum, quindi un limite di rollover o una scadenza impostata sull’account (o sul suo piano) non li riduce mai — solo il credito ricorrente e i crediti del piano sono soggetti a tali limiti.
Leggi le conversazioni di un sub-account
GET /v1/subaccounts/{subAccountUid}/chats · GET /v1/subaccounts/{subAccountUid}/chats/{contactId}/messages
Ti consente di creare una vista di monitoraggio o di supporto delle conversazioni di un cliente senza accedere al suo account. Per prima cosa elenca i suoi contatti con un’anteprima dell’ultimo messaggio, quindi leggi l’intera cronologia dei messaggi di un contatto.
Elenca contatti
curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
| Parametro di query | Obbligatorio | Descrizione |
|---|---|---|
pageSize |
No | Contatti per pagina. Predefinito 25, massimo 50. |
lastActivityAt |
No | Cursore di paginazione: passa il lastActivityAt della pagina precedente per continuare. |
searchQuery |
No | Filtra per nome del contatto o numero di telefono. |
Risposta
{
"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"
}
}
I contatti sono ordinati in base all’attività più recente. Continua la paginazione con lastActivityAt finché hasMore è true.
Leggi i messaggi di un contatto
curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
| Parametro di query | Obbligatorio | Descrizione |
|---|---|---|
pageSize |
No | Messaggi per pagina. Predefinito 30, massimo 100. |
beforeTimestamp |
No | Cursore di paginazione: recupera i messaggi precedenti a questo timestamp ISO. |
Risposta
{
"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"
}
}
I messaggi vengono restituiti dal più recente al meno recente; scorri la cronologia all’indietro con beforeTimestamp.
Leggi l’utilizzo dei crediti e lo stato delle campagne per tutto il tuo portafoglio
GET /v1/subaccounts/credit-usage · GET /v1/subaccounts/campaign-status
Due riepiloghi in stile dashboard su ogni sotto-account che gestisci, per creare i tuoi report di agenzia invece di fare clic su ogni cliente uno alla volta.
Utilizzo dei crediti
curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
| Parametro di query | Obbligatorio | Descrizione |
|---|---|---|
from / to |
Sì | Intervallo di date ISO. |
subAccountId |
No | Ometti per un riepilogo a livello di agenzia, una riga per sotto-account. Includi per passare alla modalità dettagliata: il riepilogo di quel sotto-account più i suoi record di utilizzo grezzi e impaginati. |
limitCount |
No | Solo modalità dettagliata. Predefinito 500, massimo 2000. |
startAfterTimestamp |
No | Solo modalità dettagliata: cursore di paginazione. |
{
"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
}
}
Passa subAccountId e la stessa risposta conterrà anche records: addebiti individuali con amount, reason, campaignName, contactName e timestamp. Un cliente che spende utilizzando la propria chiave BYOK anziché i tuoi crediti avrà i dati su costi/token oscurati (costsRedacted: true): si tratta di telemetria sui costi della piattaforma, non di informazioni da mostrare a un rivenditore.
Stato della campagna
curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
| Parametro di query | Obbligatorio | Descrizione |
|---|---|---|
pageSize |
No | Sotto-account per pagina. Predefinito 10, massimo 50. |
lastDocumentId |
No | Cursore di paginazione. |
searchQuery |
No | Filtra per nome o email del sotto-account. |
{
"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 segnala i sotto-account che meritano attenzione — ad esempio, una campagna in pausa o una a cui non è stato instradato alcun canale. Utilizzalo per creare una dashboard di controllo dello stato per l’intero portafoglio, invece di aprire ogni cliente per notare una campagna in stallo.
Per la messaggistica basata su serie temporali e l’attività di credito per ogni cliente (una serie pronta per i grafici piuttosto che un’istantanea puntuale), consulta
GET /analytics/agency-rollupnella guida all’API di Analytics.
Distribuisci un account cliente già configurato
PUT /v1/snapshots/default · POST /v1/snapshots/{snapshotId}/apply
Uno snapshot è un modello riutilizzabile: uno o più agenti IA insieme alla loro base di conoscenza, strumenti e media, acquisiti dal tuo account. Due endpoint lo inseriscono nel tuo flusso di provisioning.
Automatico: ogni nuovo cliente lo riceve di default. Imposta uno snapshot come predefinito una volta sola e ogni account creato da quel momento in poi lo avrà già installato. Questo copre gli account creati tramite POST /v1/subaccounts, gli account creati nella dashboard e quelli creati automaticamente quando un cliente paga tramite il tuo link di checkout.
Per prima cosa, trova l’id dello snapshot:
curl "https://api.dmchamp.com/v1/snapshots" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Quindi impostalo come predefinito:
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" }'
L’integrazione finisce qui. Invia {"snapshot_id": null} per disattivarlo di nuovo. Puoi fare la stessa cosa dalla dashboard cliccando sulla stella nella pagina Snapshot.
Per leggere ciò che è attualmente contrassegnato come preferito (ad esempio, prima che uno script di provisioning decida se impostarne uno), GET /v1/snapshots/default restituisce { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } } — null quando nulla è contrassegnato. GET /v1/snapshots (utilizzato per trovare l’id sopra) restituisce lo stesso default_snapshot_id insieme all’array completo snapshots, quindi la maggior parte delle integrazioni necessita solo di questa chiamata. I campi completi dell’oggetto snapshot si trovano nella guida Snapshots.
Su richiesta: installazione in un singolo account. Utile per l’onboarding di un cliente esistente o per fornire a un cliente un secondo modello in un secondo momento.
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" }'
Ometti sub_account_id e verrà installato nel tuo account agenzia. Come per gli endpoint /subaccounts, questi specificano l’account di destinazione nel percorso o nel corpo della richiesta, anziché tramite il parametro sub_account_id ambientale.
Cose da sapere prima di iniziare a sviluppare:
- Gli agenti installati iniziano in pausa. Collega prima i canali del cliente, poi attiva l’agente. Questo vale sia per il percorso automatico che per quello su richiesta.
- Il provisioning non fallisce mai a causa di uno snapshot. Se l’installazione non può essere completata, l’account cliente viene comunque creato e rimane utilizzabile; arriverà semplicemente vuoto e potrai applicare lo snapshot in un secondo momento.
- Canali, calendari e connessioni OAuth non vengono mai copiati. Ogni account collega i propri. Gli strumenti che utilizzano una semplice chiave API continuano a funzionare immediatamente.
- L’applicazione doppia crea una seconda copia. Nulla viene sovrascritto.
Crea il template stesso tramite API
POST /v1/snapshots · agenti, funzioni personalizzate e media tramite API
La sezione precedente distribuisce un’istantanea creata da qualcuno nella dashboard. Anche la parte di creazione è esposta, quindi l’intero ciclo — assemblare la configurazione principale una volta, acquisirla, consegnarla a ogni client — può essere eseguito dal codice.
I componenti, nell’ordine in cui uno script di provisioning li utilizza:
- Crea le tue funzioni personalizzate.
POST /v1/custom-functionsne crea una;GET /v1/custom-functionselenca quelle che hai, eGET,PUTeDELETEsu/v1/custom-functions/{customFunctionId}leggono, aggiornano e rimuovono una funzione.POST /v1/custom-functions/testesegue una simulazione di una definizione prima di salvarla. - Crea e configura l’agente.
POST /v1/agentslo crea,PUT /v1/agents/{agentId}lo aggiorna, ePATCH /v1/agents/{agentId}/activecon{ "active": false }lo mantiene in pausa mentre lavori (la stessa chiamata contruelo rende attivo).GET /v1/agentsli elenca. - Assegna le funzionalità all’agente.
POST /v1/agents/{agentId}/custom-functionscon{ "custom_function_id": "..." }collega una funzione all’agente; il corrispondenteDELETE /v1/agents/{agentId}/custom-functions/{customFunctionId}la scollega. - Riempi la libreria multimediale.
POST /v1/agents/{agentId}/media-librarycarica un elemento (JSON conbase64Data,mimeType,title,description);GETelenca gli elementi dell’agente, ePATCH/DELETEsu/{itemId}ne aggiornano o rimuovono uno. - Acquisiscilo come istantanea.
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
}'
Da lì si passa alla sezione precedente: impostalo come predefinito in modo che ogni nuovo client ne sia dotato fin dall’inizio, oppure applicalo su richiesta. La gestione vive parallelamente: PATCH /v1/snapshots/{snapshotId} con { "name": "..." } ne rinomina uno, DELETE /v1/snapshots/{snapshotId} ne elimina uno (e rimuove l’impostazione di predefinito se lo era), e GET /v1/snapshots/apply-targets elenca ogni account in cui potresti eseguire l’installazione.
Gli endpoint per agenti, funzioni personalizzate e media accettano tutti sub_account_id, quindi le stesse chiamate possono anche gestire un agente direttamente all’interno dell’account di un client. Le chiamate alle istantanee agiscono sempre sul tuo account di agenzia: il template rimane con te. Gli schemi completi di richiesta e risposta per tutti questi elementi si trovano nel Riferimento API.
Gestisci i tuoi livelli di prezzo tramite API
GET /v1/agency/pricing-tiers · POST /v1/agency/pricing-tiers · PATCH /v1/agency/pricing-tiers/{tierIndex} · DELETE /v1/agency/pricing-tiers/{tierIndex}
I piani che vendi in Modalità SaaS → Livelli di prezzo possono essere letti e modificati dal codice, in modo che il tuo pannello di amministrazione o script di provisioning possa aggiungere un piano, modificare un prezzo o fornire un link di checkout senza che nessuno debba aprire la dashboard. Autenticati con la tua chiave API di agenzia come per ogni altra chiamata in questa pagina; questi endpoint sono a livello di agenzia, quindi non richiedono alcun sub_account_id. Ogni scrittura esegue la stessa convalida e la stessa sincronizzazione di prodotti e prezzi di Stripe del salvataggio nella dashboard, quindi un piano creato qui è indistinguibile da uno configurato manualmente.
Elenca i tuoi livelli
curl "https://api.dmchamp.com/v1/agency/pricing-tiers" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Risposta
{
"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
}
}
Ogni livello viene restituito con il suo tierIndex — la sua posizione nell’elenco dei Piani, che è il modo in cui le altre tre chiamate vi fanno riferimento — e un checkout_url pronto per essere condiviso, lo stesso link fornito dalla scheda Pagamenti, che punta già al dominio white label su cui viene venduto quel piano.
Aggiungi un livello
Il corpo è un oggetto di livello; viene aggiunto alla fine del tuo elenco.
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"]
}'
La risposta contiene il livello creato, incluso l’ tierIndex su cui è stato inserito e il suo checkout_url.
Modifica un livello
Invia solo i campi che desideri modificare; tutto il resto del piano rimarrà invariato.
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 campo che l’API non riconosce viene rifiutato anziché ignorato, e l’errore lo indica — così un errore di battitura non può mai scrivere silenziosamente un’impostazione che sembra attiva ma non fa nulla. La modifica del prezzo, dei crediti, della valuta o della cadenza di fatturazione crea un nuovo prezzo nel tuo Stripe; i clienti che si sono già abbonati rimangono su ciò per cui si sono iscritti.
Elimina un livello
curl -X DELETE "https://api.dmchamp.com/v1/agency/pricing-tiers/2" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Stessa regola della dashboard: un piano che ha ancora abbonati attivi non può essere eliminato. La richiesta viene rifiutata, indicandoti quanti abbonati sono presenti su di esso — annullali o migrali prima. Un’eliminazione riuscita risponde con i tuoi livelli rimanenti, già rinumerati.
I campi di un livello
| Campo | Cos’è |
|---|---|
label / description |
Il nome del piano e la riga opzionale mostrata sulla tua pagina di checkout. |
credits |
Crediti che il cliente ottiene al mese su un piano mensile o annuale, e per periodo di fatturazione su uno settimanale. |
price_cents |
Prezzo per intervallo di fatturazione, nella più piccola unità di valuta (2900 = $29.00). Su un piano annuale, questo è il prezzo dell’intero anno. |
currency |
Codice ISO in minuscolo — usd, eur, gbp e così via. |
billing_interval / billing_interval_count |
month (predefinito), year, o week con un conteggio da 1 a 52 per “ogni N settimane”. |
trial_days |
Durata della prova gratuita, da 0 a 90. 0 (o lasciarlo vuoto) significa nessuna prova. |
trial_credits |
Crediti con cui il cliente inizia la prova. Predefinito al credits del piano. |
trial_card_required |
false consente al cliente di iniziare la prova senza inserire una carta. Predefinito a true. |
trial_hard_expiry |
true restituisce i crediti di prova inutilizzati al tuo pool e blocca l’account del cliente quando una prova termina senza un upgrade. Predefinito a false — vedi Scadenza rigida dopo la prova. |
rollover_cap_months |
Mesi di credito che i clienti su questo piano possono trasportare tra i rinnovi — un numero da 0 a 120, sono consentite frazioni. 0 non trasporta nulla; null (predefinito) significa nessun limite. Vedi Limitare ciò che viene trasportato. |
rollover_expiry_days |
Giorni dopo i quali i crediti inutilizzati vengono eliminati al rinnovo successivo — un numero intero da 1 a 3650. null (predefinito) significa che non scadono mai. |
features / feature_settings |
Cosa ottengono i clienti su questo piano — gli stessi ID funzionalità di Scegli quali tipi di canale un cliente può connettere. |
team_seats_limit |
Posti team concessi dal piano: un numero esatto, 0 per nessuno, -1 per illimitati. |
white_label_config |
Su quale dei tuoi domini white label viene venduto il piano. |
I campi della prova hanno significato solo in un piano che prevede una prova: salva un livello con trial_days: 0 e verranno eliminati. Gli ID prodotto e prezzo Stripe del piano sono gestiti per te e non possono essere impostati manualmente.
Tre cose da fare correttamente:
- Gli indici dei livelli sono posizioni, non ID permanenti. L’eliminazione di un piano sposta in avanti ogni piano successivo, quindi recupera nuovamente l’elenco dopo qualsiasi modifica e copia di nuovo i link di checkout che hai pubblicato, esattamente come faresti dopo aver eliminato un piano nella dashboard.
- La modalità SaaS deve essere configurata per prima. Questi endpoint richiedono un account agenzia con white labeling e una chiave Stripe già salvata; senza di essa, non esiste un account Stripe su cui far risiedere il prodotto e il prezzo del piano.
- Il limite è di venti piani, lo stesso della dashboard. Il campo
max_tiersnella risposta dell’elenco ti indica il limite attuale.
Gli schemi completi di richiesta e risposta sono disponibili nel Riferimento API, sotto Agenzia.
Imposta il tuo prezzo per credito tramite API
GET /v1/agency/credit-price · PATCH /v1/agency/credit-price
Il prezzo che i clienti pagano per le ricariche ad-hoc (Modalità SaaS → Prezzo per credito) può essere letto e modificato anche tramite codice. Questa funzione è pensata per i casi in cui il prezzo deve variare autonomamente: un’agenzia che vende crediti in una valuta ma addebita in un’altra può consentire a un processo pianificato di aggiornare il prezzo al variare del tasso di cambio, invece di doverlo modificare manualmente ogni settimana.
Leggi il prezzo attuale
curl "https://api.dmchamp.com/v1/agency/credit-price" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Risposta
{
"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 è il prezzo più basso consentito dalla piattaforma in quella valuta, quindi un processo può verificare un nuovo prezzo prima di inviarlo. Tutti e tre i valori sono null finché non viene impostato un prezzo.
Modificalo
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" }'
Invia solo ciò che desideri modificare. price_per_credit_cents è il prezzo nella valuta più piccola (130 = R$1,30); currency è un codice ISO in minuscolo; note è una riga facoltativa di massimo 200 caratteri mostrata ai clienti direttamente sotto il prezzo per credito nella loro pagina di fatturazione: utile per un prezzo di riferimento in un’altra valuta, come “0,25 USD per credito al nostro tasso di riferimento”. Invia "note": "" per rimuoverlo. La risposta ha la stessa forma della lettura precedente, quindi un processo può confrontare e saltare la scrittura quando non è cambiato nulla.
Si applicano le stesse regole della dashboard: il prezzo non può scendere al di sotto del minimo della piattaforma per quella valuta e l’account deve avere il white labeling. A differenza degli endpoint dei livelli di prezzo, non è richiesta alcuna chiave Stripe per leggere o modificare questo valore.
Assegna a un processo una chiave che non può fare altro
Inserire la chiave completa della tua agenzia in uno scheduler fornisce più accessi di quanto un aggiornamento di prezzo richieda. Crea invece una chiave con ambito limitato (scoped key) circoscritta all’area Prezzo Credito Agenzia: tale chiave può leggere e modificare il prezzo per credito e nient’altro; non può accedere a sotto-account, piani, crediti o alla tua connessione 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"] } }'
La risposta contiene la nuova chiave in api_key una sola volta; non verrà mai più mostrata, quindi salvala immediatamente. Imposta "read_only": true per una chiave che deve solo leggere il prezzo e aggiungi "expires_at" (una data ISO) se vuoi che smetta di funzionare automaticamente. Solo la chiave del proprietario dell’account può creare chiavi con ambito limitato; elencale o revocale con GET /v1/api-keys e DELETE /v1/api-keys/{id}.
Consenti a un sotto-account di leggere i tuoi prezzi
GET /v1/subaccounts/agency-pricing
Ogni altro endpoint in questa pagina viene chiamato con la tua chiave di agenzia, puntando facoltativamente a un cliente tramite sub_account_id. Questo è l’opposto: viene chiamato con la chiave API del sotto-account stesso, senza sub_account_id, in modo che la pagina di ricarica del cliente (o un’integrazione che costruisci per loro) possa visualizzare ciò che addebiti loro senza mai vedere il tuo account di agenzia.
curl "https://api.dmchamp.com/v1/subaccounts/agency-pricing" \
-H "X-API-Key: THE_SUB_ACCOUNTS_OWN_API_KEY"
Risposta
{
"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"
}
}
Questo rispecchia esattamente ciò che GET /v1/agency/pricing-tiers e GET /v1/agency/credit-price restituiscono per te come agenzia, meno tutto ciò che il cliente non ha bisogno di vedere (ID Stripe, max_tiers, ecc.). Funziona solo per un account che è effettivamente un sotto-account con un’agenzia collegata — chiamarlo dal tuo account di agenzia restituisce un errore di autorizzazione.
Cose da tenere a mente
- Usa la tua chiave di agenzia. Autentica ogni chiamata con la chiave API del tuo account di agenzia, non quella del sub-account. Il parametro
sub_account_idè ciò che reindirizza l’azione. - I crediti provengono dal sub-account. Gli acquisti e gli addebiti ricorrenti incidono sul saldo crediti del sub-account di destinazione, non sul tuo.
- Un
404significa “non è il tuo sub-account”. Ricontrolla l’id e assicurati che l’account sia uno di quelli che gestisci. - Il parametro è facoltativo ovunque sia accettato. Omettilo e lo stesso endpoint agirà sul tuo account di agenzia, così potrai riutilizzare un’unica integrazione per entrambi.
Correlati
- Accesso API — autenticazione, URL di base, errori, limiti di frequenza.
- Sotto-account — elenca e gestisci gli account che puoi gestire.
- Ricarica automatica sotto-account — concedi crediti a un sotto-account tramite webhook + API.
- API Campagne — crea, aggiorna e copia campagne, incluso il riferimento completo ai campi.
- API Connessione Canale — connetti i canali di un cliente e instradali verso una campagna.
- Guida all’API di Analytics (nella sezione API) — il riepilogo dei sotto-account dell’agenzia e ogni altro endpoint di reportistica.
- Snapshots — cosa cattura uno snapshot e come costruirne uno nella dashboard.