API pour les agences
En tant qu’agence, vous pouvez utiliser la même API REST que vos clients, mais en dirigeant les requêtes individuelles vers l’un de vos sous-comptes gérés au lieu de votre propre compte. Cela vous permet de créer des outils qui intègrent un client de bout en bout — création de ses campagnes, entraînement de son IA sur une base de connaissances, importation de ses contacts, connexion de ses canaux de messagerie et achat de numéros de téléphone — le tout sans avoir à vous connecter manuellement à chaque sous-compte.
Cette page couvre uniquement le comportement spécifique aux agences : comment agir au nom d’un sous-compte avec le paramètre sub_account_id. Pour les bases (génération de clé, authentification, URL de base, format d’erreur, limites de débit), commencez par le guide Accès API. Tout ce qui y est décrit s’applique également ici : vous vous authentifiez avec la clé API de votre compte d’agence.
Remarque : Cette page est technique. Si vous n’êtes pas développeur, partagez-la avec la personne en charge de votre intégration.
Comment fonctionne l’action « au nom de »
Par défaut, chaque requête API agit sur le compte qui possède la clé API, c’est-à-dire votre compte d’agence. Pour agir sur un compte client géré à la place, ajoutez le paramètre optionnel sub_account_id à la requête, défini sur l’identifiant de compte de ce client.
- Omettre
sub_account_id→ la requête agit sur votre propre compte d’agence. - Inclure
sub_account_id→ la requête agit sur ce sous-compte, mais seulement après que la plateforme a confirmé que le sous-compte vous appartient réellement.
Vous vous authentifiez toujours avec la clé API de votre compte d’agence. Vous n’avez jamais besoin de la clé propre au sous-compte et vous ne gérez jamais les identifiants du sous-compte.
Où l’insérer
- Points de terminaison GET / DELETE → passez-le en tant que paramètre de requête :
?sub_account_id=THE_SUB_ACCOUNT_ID(en plus de votreapiKey, si vous vous authentifiez par requête). - Points de terminaison POST / PUT / PATCH → incluez-le dans le corps de la requête JSON en tant que
"sub_account_id": "THE_SUB_ACCOUNT_ID". - Assistants IA → rien à configurer. Le serveur MCP applique le même paramètre sur ses outils de lecture, donc une seule connexion avec votre clé d’agence peut générer des rapports sur chaque client : il suffit de nommer le client dans votre requête (« combien de contacts Bella’s Bistro possède-t-il ? »). Les actions d’écriture sont également disponibles : chaque point de terminaison qui accepte
sub_account_idest exposé en tant qu’outil, vous pouvez donc créer, modifier et envoyer au nom d’un client à partir de la même connexion.
Trouver l’identifiant d’un sous-compte
Le sub_account_id est l’identifiant unique du compte client. Vous pouvez obtenir la liste de vos sous-comptes et leurs identifiants à partir des points de terminaison de l’API SubAccounts (voir le guide Sous-comptes) ou depuis la page Sous-comptes dans la barre latérale.
La propriété est toujours vérifiée
Lorsque vous passez un sub_account_id, la plateforme vérifie que le compte est un sous-compte réel et qu’il appartient à votre agence. Ce n’est qu’à cette condition que la requête est traitée.
Si l’identifiant est inconnu, n’est pas un sous-compte ou appartient à une autre agence, la requête échoue avec une réponse 404 :
{
"success": false,
"error_code": 404,
"error": "Sub-account not found."
}
Pourquoi 404 et non 403 ? Une réponse « forbidden » indiquerait à un tiers que l’identifiant existe mais ne lui appartient pas. Renvoyer la même
404pour « n’existe pas » et « ne vous appartient pas » signifie que le point de terminaison ne peut pas être utilisé pour découvrir quels identifiants de compte appartiennent à d’autres agences. Considérez une404ici comme « ce n’est pas un sous-compte que vous gérez. »
Où sub_account_id est pris en charge
sub_account_id est accepté sur pratiquement tous les points de terminaison de ressource — tout appel qui crée, lit, met à jour ou supprime les données propres à un compte. En pratique, vous pouvez provisionner et exécuter toute la configuration d’un sous-compte avec votre clé d’agence :
- Configuration de l’IA — campagnes, agents, FAQ, sources de base de connaissances (exploration de site web et téléchargement de documents), groupes de base de connaissances, diffusions, fonctions personnalisées, serveurs MCP
- Contacts et CRM — contacts (y compris l’importation), listes, tags, tâches, opportunités, rendez-vous, événements
- Canaux et numéros — connexion WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE, recherche / achat / gestion de numéros de téléphone, modèles WhatsApp, routage des canaux
- Messagerie et contenu — envoi de messages, sessions de chat, exportations de chat, résumés quotidiens
- Paramètres et intégrations — webhooks, configuration du widget de chat, configuration en marque blanche, SMS BYOK et autres paramètres de compte, analyses
Pour chacun d’entre eux, le paramètre est facultatif — omettez-le et l’appel s’effectuera sur votre compte d’agence, de sorte qu’une seule intégration suffit pour les deux. Les crédits et l’utilisation proviennent toujours du compte ciblé : les frais liés aux campagnes, messages, tags et numéros d’un sous-compte sont débités du solde du sous-compte.
Où cela ne s’applique PAS
Quelques points de terminaison sont au niveau de l’agence ou auto-adressés et ignorent sub_account_id :
- Gestion des sous-comptes eux-mêmes — les points de terminaison SubAccounts (créer / lister / mettre à jour un sous-compte) et le point de terminaison de limite de dépenses BYOK nomment déjà le sous-compte dans leur propre chemin d’URL. Les points de terminaison de tarification et de politique et les points de terminaison de surveillance de chat suivent le même modèle.
- Copie d’un agent entre comptes —
POST /v1/subaccounts/agents/copynomme les deux comptes lui-même, en prenant la destination commetargetUserId. Voir l’exemple concret ci-dessous. (L’ancienPOST /v1/subaccounts/campaigns/copyfonctionne de la même manière mais est obsolète avec le reste de l’API Campaigns.) - Ajustement des crédits et les deux cumuls à l’échelle de l’agence —
POST /v1/subaccounts/creditsidentifie le sous-compte paremailà la place ;GET /v1/subaccounts/credit-usageetGET /v1/subaccounts/campaign-statusgénèrent des rapports sur chaque sous-compte à la fois, il n’y a donc pas de compte unique à cibler. - Le propre compte de votre agence — La gestion des clés API, les rapports d’utilisation de l’agence, la gestion d’équipe et vos niveaux de tarification agissent toujours sur votre compte d’agence.
- Webhooks de messages entrants — les points de terminaison vers lesquels les systèmes externes publient sont liés au compte dont les identifiants les ont configurés, il n’y a donc rien à rediriger.
La liste toujours à jour et lisible par machine des paramètres acceptés par chaque point de terminaison se trouve dans la référence de l’API de votre tableau de bord (Paramètres → Intégrations → Clé API) et dans la spécification OpenAPI à l’adresse
GET /v1/docs/openapi.yaml. Nous publions fréquemment des modifications de l’API ; considérez-les comme la source de vérité.

Paramètres → Intégrations → Clé API — la clé de votre agence se trouve ici, ainsi que le lien vers la référence complète de l'API.
Exemple concret : connecter Instagram et Messenger pour un sous-compte
La connexion à Instagram et Messenger est un flux basé sur le navigateur. Vous le démarrez avec l’API, transmettez l’URL de consentement renvoyée au client (ou ouvrez-la pour lui), attendez qu’il s’autorise dans son navigateur, puis choisissez la page à connecter — tout en ciblant son sous-compte avec sub_account_id.
Étape 1 — Démarrer la connexion
Appelez le point de terminaison de connexion avec le sub_account_id du client dans le corps. Aucune information d’identification n’est envoyée ici ; la plateforme renvoie une URL de consentement que le client doit ouvrir dans un navigateur, ainsi qu’un jeton de corrélation à usage unique.
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éponse :
{
"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"
}
Envoyez le client vers oauth_url dans un navigateur pour autoriser. Le state_token corrèle cette tentative et est un secret à courte durée de vie — ne le consignez pas dans les journaux. La tentative expire à expires_at ; si elle expire, recommencez.
Étape 2 — Interroger jusqu’au chargement des pages
Une fois l’autorisation du client obtenue, interrogez le point de terminaison de statut (avec le même sub_account_id, cette fois en tant que paramètre de requête) jusqu’à ce que les pages connectables apparaissent.
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éponse :
{
"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
}
Le champ status progresse via pending → token_received → pages_loaded → connected. Attendez pages_loaded avant de sélectionner une page. Deux états d’erreur terminaux peuvent également apparaître au lieu de progresser : failed et expired (le client a refusé le consentement, ou la fenêtre d’environ 30 minutes du jeton d’état a expiré) — un champ reason est inclus lorsque l’un ou l’autre se produit. Arrêtez l’interrogation et recommencez à l’étape 1 si vous en voyez un ; n’attendez pas indéfiniment sur pending. Les jetons d’accès aux pages ne sont jamais renvoyés.
Étape 3 — Sélectionner la page à connecter
Choisissez l’un des identifiants de page de l’étape 2 et sélectionnez-le. La sélection d’une page connecte à la fois Instagram et Messenger pour cette page. Incluez à nouveau sub_account_id dans le corps de la requête.
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éponse :
{
"success": true,
"page_id": "1098765432101234",
"instagram_business_account_id": "17841400000000000"
}
C’est tout — Instagram et Messenger sont maintenant connectés sur le sous-compte du client. Vous n’avez fourni que le page_id ; l’identifiant sous-jacent est résolu sur le serveur et ne transite jamais par votre intégration.
Exemple pratique : acheter un numéro pour un sous-compte
L’achat d’un numéro fonctionne de la même manière : effectuez une recherche avec sub_account_id dans la requête, puis achetez-le en l’incluant dans le corps. Les crédits sont déduits du solde du sous-compte, et le numéro est provisionné sur ce sous-compte.
Recherche (cURL) :
curl "https://api.dmchamp.com/v1/phone-numbers/available?apiKey=YOUR_API_KEY&country_code=US&sub_account_id=abc123def456"
Achat (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();
Achat (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éponse :
{
"success": true,
"phone_number": "+14155551234",
"channel": "whatsapp",
"whatsapp_status": "PURCHASED",
"outgoing_status": "PURCHASED",
"status": "PURCHASED",
"purchase_credits": 11.5,
"monthly_credits": 11.5
}
Le numéro est provisionné dans l’état PURCHASED et l’enregistrement de l’expéditeur WhatsApp se poursuit en arrière-plan. Interrogez GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456 jusqu’à ce que le statut atteigne ONLINE avant d’envoyer.
Exemple concret : déployer un agent modèle dans chaque nouveau client
Le modèle d’agence habituel consiste à conserver un agent maître sur votre compte d’agence, configuré comme vous souhaitez que chaque client commence, et à en copier une instance dans chaque nouveau sous-compte au moment du provisionnement. Cela représente trois appels, et rien n’a besoin d’être répété par la suite : la copie conserve ses paramètres jusqu’à ce que vous les modifiiez.
Étape 1 — Copier l’agent
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 réponse contient l’identifiant du nouvel agent dans data.agent_id. La FAQ, la base de connaissances et la médiathèque sont incluses ; les modèles WhatsApp, les publications sociales connectées et les contacts du compte source ne le sont délibérément pas. Liste complète des champs dans l’API AI Agents.
Notez que ce point de terminaison utilise targetUserId plutôt que sub_account_id — il nomme les deux comptes lui-même. Les deux appels ci-dessous utilisent le paramètre sub_account_id habituel.
Étape 2 — L’activer
La copie arrive toujours en pause, elle ne peut donc envoyer de messages à personne tant que vous ne l’avez pas autorisé. C’est également le moment de définir le niveau d’IA que vous souhaitez attribuer au client ; il y reste, il n’est donc pas nécessaire de le réappliquer selon un calendrier.
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" }'
Pour empêcher le client de modifier le niveau par la suite, verrouillez les niveaux autorisés sur le sous-compte au lieu de renvoyer la valeur.
Étape 3 — Diriger les canaux du client vers celle-ci
La copie arrive également sans routage, donc rien ne l’atteint tant que vous ne l’avez pas désigné comme répondant sur les canaux que le client a connectés. Un appel par 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" }'
À partir de là, un premier message provenant d’un contact inconnu sur ce canal est automatiquement pris en charge par l’agent copié. Voir Pointer un canal vers un agent pour les autres canaux et le routage par numéro.
Définissez le fuseau horaire du client lors de la création du sous-compte. Transmettez
time_zone_idsurPOST /v1/subaccounts. Les heures d’activité de la campagne sont évaluées dans le fuseau horaire du sous-compte lui-même, de sorte qu’un client créé sans fuseau horaire voit son planning lu par rapport à l’UTC — ce qui décale silencieusement les moments où l’assistant est autorisé à répondre.
Ignorer l’assistant de configuration pour un client que vous configurez vous-même
POST /v1/subaccounts
Par défaut, la première fois qu’un nouveau propriétaire de sous-compte se connecte, il est guidé par l’assistant de configuration. Pour les clients « clé en main » — où vous créez la campagne et connectez les canaux avant même que le client ne se connecte — transmettez guided_onboarding: false lors de la création du compte. Ils arrivent directement sur le tableau de bord et l’entrée Assistant de configuration est masquée dans leur barre latérale.
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 }
}'
Omettez le champ (ou envoyez true) et l’assistant se comportera exactement comme il l’a toujours fait, de sorte que les intégrations existantes n’ont besoin d’aucune modification. Pour redonner l’assistant à un client plus tard, réaffichez l’élément guided_onboarding avec PUT /v1/subaccounts/{subAccountUid}/menu-visibility (ci-dessous) — la visibilité du menu contrôle si l’assistant est accessible, guided_onboarding contrôle uniquement la redirection lors de la première connexion.
Désactiver les Tâches, les Résumés quotidiens ou la Bibliothèque multimédia pour un client
POST /v1/subaccounts
Ces trois fonctionnalités sont activées pour chaque nouveau client, sauf indication contraire de votre part, et elles se comportent différemment de toutes les autres fonctionnalités de ce guide : elles sont en opt-out (désactivation volontaire) et non en opt-in. Les omettre de features ne suffit pas en soi, car la liste features d’une intégration plus ancienne ne les mentionnait tout simplement pas — nous ne pouvons pas distinguer si « l’agence a désactivé ceci » ou si « cette liste a été rédigée avant que l’option n’existe ».
Indiquez-le donc explicitement avec 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
}
}'
Chaque clé est facultative ; tout ce que vous omettez reste activé. Avec tasks: false, l’IA cesse de créer des tâches pour ce client et aucun e-mail de type « Nouvelle tâche créée » n’est envoyé ; avec daily_summaries: false, le résumé nocturne n’est jamais généré ni envoyé par e-mail.
feature_settings est le seul moyen de désactiver ces trois éléments lors de la création. Les omettre de features ne produit aucun effet en soi, quel que soit le reste de votre liste — c’est intentionnel, afin qu’une intégration plus ancienne ne perde pas silencieusement ces trois fonctionnalités.
Pour modifier l’un de ces paramètres par la suite, envoyez la liste complète features à PUT /v1/subaccounts/{subAccountUid}/features — ici, la présence dans la liste active une fonctionnalité et son absence la désactive.
Connectez automatiquement vos clients à leur sous-compte (SSO)
POST /v1/subaccounts/{subAccountUid}/sso-link
Un seul appel avec votre clé API d’agence renvoie une URL prête à l’emploi qui connecte directement le client à son propre sous-compte — aucun écran de connexion, aucune étape de mot de passe, rien à développer en plus. Ouvrez-la dans un nouvel onglet, via une redirection ou dans une iframe au sein de votre propre produit.
| Champ | Requis | Description |
|---|---|---|
redirect |
Non | Page intégrée à l’application sur laquelle vous souhaitez que le client aboutisse, par ex. "/chats" ou "/agents". Renvoyé sous le nom deep_link_url dans la réponse. |
app_base_url |
Non | Hôte du tableau de bord pour le lien. Utilise par défaut votre domaine d’application en marque blanche (ou le domaine de la plateforme si vous n’en avez pas). Doit être 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éponse
{
"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"
}
Comment bien l’utiliser :
- Un seul saut. L’ouverture de
urlconnecte le client et l’envoie directement sur la pageredirectdu tableau de bord — pas d’écran de connexion, pas de page intermédiaire.deep_link_urldésigne la même destination, pour les intégrateurs qui préfèrent naviguer explicitement dans un cadre après la connexion ; une fois la session établie, n’importe quel chemin du tableau de bord fonctionne dans ce contexte de navigateur. - Création à la demande, ouverture immédiate. Le lien contient un identifiant de connexion et expire après environ une heure. Demandez-le côté serveur au moment où le client clique, et ne le stockez ni ne l’envoyez jamais par e-mail.
- Le jeton de connexion transite dans le fragment d’URL (
#…), que les navigateurs n’envoient jamais aux serveurs, et il est supprimé de la barre d’adresse dès qu’il est consommé. - Uniquement vos propres sous-comptes. Le point de terminaison refuse tout compte qui n’appartient pas à votre agence.
- Un lien expiré affiche une erreur claire avec un chemin de réessai — générez-en un nouveau.
Masquer des éléments de navigation sur un sous-compte
PUT /v1/subaccounts/{subAccountUid}/menu-visibility
Contrôle les éléments de la barre latérale et des paramètres visibles par un sous-compte — utile lorsque vous intégrez le tableau de bord et que vous souhaitez uniquement afficher les surfaces que votre produit ne couvre pas déjà. Tout ce qui n’est pas listé reste visible ; envoyez null comme valeur entière de menuVisibility pour tout réinitialiser en mode visible. Masquer un élément masque l’entrée du menu — associez cela aux fonctionnalités que vous accordez au sous-compte pour un contrôle 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éponse
{
"success": true,
"data": {
"subAccountUid": "SUB_ACCOUNT_UID",
"menuVisibility": {
"side_nav": { "Dashboard": false, "Campaigns": false, "Automations": false },
"settings_nav": { "team": false }
}
}
}
side_nav accepte ces 13 clés, qui correspondent aux noms des éléments de la barre latérale : Dashboard, DailySummaries, Chats, Contacts, Deals, Tasks, Automations, Campaigns, Appointments, Settings, Help, CreditsCounter (le solde de crédit affiché dans la barre latérale) et guided_onboarding (l’assistant de configuration). Trois autres clés — AiInsights, Sub Accounts et Agency Reselling — sont acceptées mais ne font rien : elles ne s’appliquaient qu’à l’ancien tableau de bord classique, leur définition n’a donc aucun effet sur vos sous-comptes. Les clés manquantes signifient visible ; lorsque vous vous connectez vous-même au sous-compte, les éléments masqués sont temporairement affichés afin que vous puissiez toujours revenir en arrière.
Masquer une page du menu n’en accorde jamais l’accès. Automations nécessite que la fonctionnalité automations soit accordée sur le sous-compte — définissez la clé sur true sans cela et la page n’apparaîtra toujours pas. Tasks et DailySummaries fonctionnent à l’inverse : elles sont activées pour chaque client à moins que vous ne les désactiviez (voir Désactiver les Tâches, les Résumés quotidiens ou la Bibliothèque multimédia pour un client).
Choisir les types de canaux auxquels un client peut se connecter
PUT /v1/subaccounts/{subAccountUid}/features
Les commutateurs Types de canaux que vous voyez sur un niveau de plan sont des identifiants de fonctionnalité ordinaires. Vous pouvez donc les définir par client depuis l’API au lieu du tableau de bord. Il s’agit de l’un des points de terminaison qui nomme le sous-compte dans sa propre URL, il ne nécessite donc aucun sub_account_id.
| ID de fonctionnalité | Canal |
|---|---|
channel_chat_widget |
Widget de chat sur site web |
channel_whatsapp_api |
API WhatsApp Business |
channel_whatsapp_web |
WhatsApp Web (numéro lié par QR) |
channel_instagram |
|
channel_messenger |
Facebook Messenger |
channel_telegram |
Telegram |
channel_line |
LINE |
channel_viber |
Viber |
channel_email |
Boîte de réception 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"
]
}'
Trois points à bien comprendre :
- L’appel remplace toute la liste des fonctionnalités. Envoyez toutes les fonctionnalités que le client doit conserver, pas seulement celles que vous modifiez. Les mêmes identifiants fonctionnent comme
featuressurPOST /v1/subaccountslorsque vous créez le compte. - Les types de canaux et le nombre de canaux sont des verrous distincts, et les deux s’appliquent.
channels_1/channels_3/channels_unlimitedcontrôlent combien de connexions sont autorisées ; les identifiantschannel_*contrôlent quels types. L’exemple ci-dessus signifie « jusqu’à 3 connexions, et uniquement le widget de chat, WhatsApp Web ou Instagram ». - Ne pas envoyer d’identifiants
channel_*signifie qu’il n’y a aucune restriction de canal. C’est le comportement d’origine, c’est pourquoi les clients existants n’ont pas été affectés lors du déploiement de cette fonctionnalité. Envoyez-en un ou plusieurs et tout le reste apparaîtra comme verrouillé sur la page Canaux du client avec une note de mise à niveau au lieu d’un bouton Connecter. Les canaux déjà connectés par le client continuent de fonctionner.
La définition de la liste des canaux sur un niveau de plan, afin que chaque client qui achète ce niveau en hérite, s’effectue dans le tableau de bord sous les paramètres de votre plan d’agence. Ce point de terminaison la définit pour un sous-compte spécifique.
Définir une limite exacte de membres d’équipe pour un client
PUT /v1/subaccounts/{subAccountUid}/limits
Les fonctionnalités team_seats_* ne proposent que des paliers prédéfinis (3 / 5 / 10 / illimité). Pour attribuer à un client un nombre exact de sièges d’équipe — 2, 7, 15, ou tout autre nombre — définissez plutôt usage_limits.team_seats_limit. Cette valeur prévaut sur les paliers prédéfinis et la plateforme l’applique à chaque invitation, ajout direct et acceptation d’invitation : une fois la limite atteinte, les invitations supplémentaires sont refusées côté serveur.
- Un entier positif correspond au plafond exact.
0signifie que les membres d’équipe ne sont pas inclus — le client ne peut inviter personne.-1signifie illimité.nullefface la limite personnalisée et revient au palierteam_seats_*défini dans la liste des fonctionnalités.
Réduire la limite ne supprime jamais les membres d’équipe existants ; cela empêche seulement l’ajout de nouveaux membres.
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 }
}'
Vous pouvez également le définir lors de la création : POST /v1/subaccounts accepte usage_limits.team_seats_limit avec la même sémantique. Pour lire la valeur actuelle, récupérez le sous-compte avec GET /v1/subaccounts?email=... et examinez usage_limits.team_seats_limit (absent/null = les préréglages décident). Le même point de terminaison met également à jour credits, monthly_credits, roll_over_to_next_month, rollover_cap_months, rollover_expiry_days et byok_monthly_limit_usd — envoyez uniquement les clés que vous souhaitez modifier.
Comment cela interagit avec les limites de sièges des plans SaaS. Vos plans SaaS peuvent comporter leur propre allocation de sièges (définie dans l’éditeur de plan — voir Sièges d’équipe sur un plan), qui est appliquée automatiquement lorsqu’un client s’abonne. Une limite que vous définissez via ce point de terminaison compte comme une attribution manuelle : l’achat d’un plan la remplace par l’allocation de sièges propre au plan (cet achat étant un choix de plan explicite), mais les renouvellements mensuels automatiques ne remplacent jamais une limite manuelle — ainsi, une exception ponctuelle que vous accordez à un client survit à son cycle de facturation. Supprimer la limite manuelle avec null redonne la main au plan lors de son prochain renouvellement.
Limitez ce qu’un client conserve entre deux renouvellements. Deux clés usage_limits supplémentaires se trouvent à côté de roll_over_to_next_month. Toutes deux sont également acceptées par POST /v1/subaccounts lors de la création, et null efface l’une ou l’autre.
| Clé | Action |
|---|---|
rollover_cap_months |
Nombre de mois d’allocation que le client peut conserver. Un nombre de 0 à 120, fractions autorisées (0.5 = un demi-mois). À chaque renouvellement, le solde inutilisé est réduit au maximum à ce nombre de fois l’allocation accordée par ce renouvellement, avant que les nouveaux crédits ne soient ajoutés ; 0 ne reporte rien. |
rollover_expiry_days |
Un nombre entier de jours, de 1 à 3650. Les crédits inutilisés pendant cette durée sont supprimés lors du premier renouvellement après avoir atteint cet âge. La consommation est toujours déduite des crédits les plus anciens en premier, donc un client qui utilise son allocation chaque mois n’en perd jamais. |
S’ils ne sont pas définis, les deux reviennent au plan du client ; une valeur envoyée ici prévaut sur celle du plan. Seuls les crédits récurrents (l’allocation mensuelle et les crédits du plan) y sont soumis : les recharges, les recharges automatiques et les ajouts ponctuels ne sont jamais plafonnés ni expirés. Chaque réduction est inscrite dans l’historique des crédits du client en tant qu’Ajustement de crédit de plafond de report ou Ajustement de crédit de crédits expirés et ne compte jamais comme une utilisation. Les équivalents au niveau du plan sont rollover_cap_months et rollover_expiry_days sur un niveau de tarification — voir Les champs sur un niveau et Plafonner ce qui est reporté.
Définir la tarification et la politique IA par client
PUT /v1/subaccounts/{subAccountUid}/max-tier · /ai-tiers · /max-rate · /action-pricing · /insider-rate · /locked-bot-fields · /notifications · /zero-credit-reply
Huit commutateurs supplémentaires par client, en plus de /limits, /features et /menu-visibility ci-dessus. Chacun prend l’uid du sous-compte dans l’URL (aucun paramètre de corps/requête sub_account_id — la cible est déjà nommée dans le chemin) et est limité de la même manière : votre clé d’agence, et le sous-compte doit appartenir à votre agence.
Quels modèles d’IA un client peut utiliser
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 } permet au client d’opter pour (ou de sortir de) le niveau Max AI — notre infrastructure au prix catalogue de la plateforme. L’activation de cette option pour un client BYOK fait passer son coût d’IA de « gratuit sur ma propre clé » à « facturé sur mon pool de crédits », il s’agit donc d’une décision délibérée par client plutôt que d’une valeur par défaut à l’échelle de l’agence.
Pour restreindre les niveaux que les campagnes et les agents d’un client peuvent choisir (plutôt que de simplement limiter Max), utilisez 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 est un tableau tiré de standard, economy, max, mini — il REMPLACE la liste d’autorisation du client. Envoyez null (ou []) pour effacer la restriction et leur permettre de choisir n’importe quel niveau. Ceci est important car un sous-compte choisissant son propre niveau d’IA dépense à partir de votre pool de crédits, c’est donc le levier pour déterminer quels modèles un client revendeur peut utiliser pour augmenter votre facture.
Une réponse d’attente lorsque le client n’a plus de crédits
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." }'
Lorsque le solde du client (ou votre réserve) est vide, l’IA ne peut pas répondre et le contact n’entend rien. Avec enabled: true, chaque contact qui écrit pendant la panne reçoit message une fois (max 500 caractères, envoyé tel quel sur chaque canal), et l’IA répond réellement à ces conversations une fois que les crédits sont de retour. enabled: false conserve le texte enregistré pour plus tard ; enabled: false sans message supprime le paramètre. Même commutateur que Réponse d’attente en cas de manque de crédits dans la fenêtre modale de modification du sous-compte — voir Une réponse d’attente lorsqu’un client n’a plus de crédits.
Ce qu’un client paie par action IA, et la majoration des frais WhatsApp
Deux façons de définir votre tarif client, du plus simple au plus granulaire :
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 est le prix en crédits que le solde PROPRE du sous-compte brûle par action IA de modèle Max — votre majoration côté client en plus de ce que votre pool paie réellement. null réinitialise la surcharge au prix catalogue de la plateforme. Le taux doit être au moins égal au coût d’une action Max pour votre propre pool (vous ne pouvez donc jamais facturer un client en dessous de votre coût) et ne pas dépasser 10 crédits ; une requête en dehors de cette fenêtre est rejetée avec le plancher calculé dans le message d’erreur.
Pour une tarification par type d’action au lieu d’un tarif Max forfaitaire, utilisez 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 est une FUSION sur la carte existante du client — une clé que vous ne mentionnez pas est laissée telle quelle, et null réinitialise cette clé à sa valeur par défaut. Les clés reconnues :
| Clé | Prix |
|---|---|
AI_MESSAGE |
Une réponse IA |
AI_TOOL_USE |
Un appel d’outil IA |
EVALUATION_CALL |
Une passe d’évaluation de chat |
INTERRUPTION_HANDLING |
Gestion d’une interruption en milieu de réponse |
CONTACT_TAG |
Une étiquette de contact attribuée par l’IA |
CHAT_SUMMARY |
Un résumé de chat |
wa_carrier_multiplier |
Un multiplicateur de majoration appliqué à chaque frais WhatsApp non-IA que le client paie : location mensuelle de numéro, frais de livraison sur voie gérée et coûts de transfert des modèles Meta/Twilio. |
Les tarifs par action doivent être un nombre supérieur à 0 et allant jusqu’à 10 ; wa_carrier_multiplier doit être d’au moins 1 (pas de remise en dessous du coût) et jusqu’à 10. L’envoi d’une clé non reconnue, ou d’une valeur hors limites, rejette la TOTALITÉ de la requête et nomme chaque clé fautive, afin qu’une faute de frappe ne puisse jamais enregistrer silencieusement un prix qui n’est pas réellement appliqué.
Si vous êtes membre du Champions Circle, insider-rate transmet votre tarif de 20 % de réduction Max/Lead Finder à un seul client au lieu de l’appliquer à l’ensemble de l’agence :
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 }'
L’activation nécessite que votre propre compte d’agence détienne réellement une adhésion au Circle ; la désactivation ne le nécessite jamais, donc un membre dont l’adhésion a expiré peut toujours revenir en arrière pour un client.
Verrouiller des sections du playbook d’un 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 est un tableau tiré de instructions, goal, rules, personality, conclude_unless — il REMPLACE la liste verrouillée du client. Une section verrouillée est rejetée côté serveur si le SOUS-COMPTE lui-même tente de la modifier (directement ou par clé API), tandis que vous (via sub_account_id) et la vue administrateur du tableau de bord du client pouvez toujours tout modifier. Envoyez null (ou []) pour tout déverrouiller. Utile pour les clients « clé en main » où vous possédez le playbook et êtes jugé sur le résultat.
Définir les préférences de notification d’un client en son nom
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 remplace l’ensemble des préférences de notification du client (pas une fusion par clé — envoyez chaque catégorie que vous souhaitez conserver, en correspondant à la façon dont la page Paramètres du sous-compte enregistre les données). Chaque catégorie sous settings accepte enabled (booléen) et jusqu’à trois channels parmi email, in_app, webhook. Envoyez null pour réinitialiser aux valeurs par défaut de la plateforme.
Les sept points de terminaison répondent { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } } et sont consignés dans le journal d’audit avec la valeur avant/après. Erreurs courantes : 403 si votre compte n’est pas de type Agence/Dev ou si le sous-compte n’est pas sous votre gestion, 400 s’il ne s’agit pas d’un sous-compte d’agence ou si une valeur est hors limites.
Suspendre un client ayant interrompu son abonnement
POST /v1/subaccounts/{subAccountUid}/pause · POST /v1/subaccounts/{subAccountUid}/unpause
Lorsqu’un client suspend son abonnement auprès de vous, mettez son compte en pause au lieu de le supprimer : tout ce qu’il envoie s’arrête immédiatement — messages sortants, diffusions, réponses IA sur tous les canaux — et lorsqu’il se connecte, il voit un écran de verrouillage Compte suspendu (avec votre message optionnel) au lieu de l’application. Rien n’est supprimé ou déconnecté : les agents, les campagnes, les canaux connectés, les contacts et l’historique des discussions restent exactement tels quels, de sorte que la réactivation remet le client précisément là où il s’était arrêté — aucune configuration à refaire.
| Champ | Requis | Description |
|---|---|---|
message |
Non | Affiché au client sur son écran de verrouillage. Laissez vide pour utiliser le libellé par défaut. |
reason |
Non | Note interne à l’agence stockée avec la mise en pause et dans le journal d’audit — jamais montrée au client. |
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éponse
{
"success": true,
"data": {
"subAccountUid": "SUB_ACCOUNT_UID",
"paused": true,
"level": "hard_blocked"
}
}
Lorsque le client revient, POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (sans corps) lève le verrouillage — l’envoi et les réponses IA reprennent immédiatement.
Bon à savoir :
- Il s’agit du même état que le bouton de blocage strict du tableau de bord (Bloquer / Mettre en pause un sous-compte) — un client mis en pause via l’API apparaît comme bloqué dans le tableau de bord et vice versa, et la réactivation annule un blocage effectué de l’un ou l’autre côté. L’état actuel est lisible depuis le champ
agency_blocksurGET /v1/subaccounts(levelde"none","soft_blocked"ou"hard_blocked"). - Les deux appels sont idempotents. Mettre en pause un client déjà en pause ne fait que rafraîchir le message, la raison et l’horodatage ; réactiver un client actif ne change rien.
- Le client n’est pas informé automatiquement par e-mail — de nombreuses agences utilisant la marque blanche, c’est à vous de prévenir le client.
- Votre propre facturation DM Champ reste inchangée. Mettre un client en pause n’affecte que votre relation avec lui.
- Les assistants IA peuvent également le faire : le serveur MCP expose ces points de terminaison en tant qu’outils
pause_subaccountetunpause_subaccount.
Accorder ou déduire des crédits directement
POST /v1/subaccounts/credits
Ajoute ou supprime un montant exact de crédits du solde d’un sous-compte — l’équivalent API de l’ajustement manuel des crédits du tableau de bord. Il s’agit d’une modification de solde ponctuelle, distincte des paramètres récurrents monthly_credits, roll_over_to_next_month, rollover_cap_months et rollover_expiry_days sur PUT /v1/subaccounts/{subAccountUid}/limits.
C’est le seul point de terminaison sur cette page qui identifie le sous-compte par e-mail plutôt que par sub_account_id.
| Champ | Requis | Description |
|---|---|---|
email |
Oui | L’e-mail du sous-compte, tel qu’il existe sous votre agence. |
amount |
Oui | Nombre de crédits non nul. Positif pour ajouter, négatif pour déduire. |
description |
Non | Affiché à côté de l’ajustement dans l’historique des crédits du client. Par défaut, une ligne générique « Ajusté par l’agence via 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éponse
{
"success": true,
"data": {
"email": "client@example.com",
"previous_balance": 1200,
"adjustment": 500,
"new_balance": 1700
}
}
Un amount négatif qui ferait passer le solde en dessous de zéro est refusé avec 400, vous indiquant le solde disponible et ce que vous avez tenté de déduire. Si le client utilise sa propre facturation Stripe (mode revendeur), un montant ajouté compte également comme des crédits qu’il a achetés, il survit donc à sa prochaine réinitialisation mensuelle de la même manière qu’une vraie recharge ; sur un client alloué standard, il est traité comme faisant partie de son allocation récurrente à la place. Dans les deux cas, il s’agit d’un ajout ponctuel, donc un plafond de report ou une expiration définie sur le compte (ou son plan) ne les réduit jamais — seuls l’allocation récurrente et les crédits du plan y sont soumis.
Lire les conversations d’un sous-compte
GET /v1/subaccounts/{subAccountUid}/chats · GET /v1/subaccounts/{subAccountUid}/chats/{contactId}/messages
Vous permet de créer une vue de surveillance ou de support des conversations d’un client sans vous connecter à son compte. Listez d’abord ses contacts avec un aperçu du dernier message, puis lisez l’historique complet des messages d’un contact.
Lister les contacts
curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
| Paramètre de requête | Requis | Description |
|---|---|---|
pageSize |
Non | Contacts par page. 25 par défaut, 50 maximum. |
lastActivityAt |
Non | Curseur de pagination — transmettez le lastActivityAt de la page précédente pour continuer. |
searchQuery |
Non | Filtrer par nom de contact ou numéro de téléphone. |
Réponse
{
"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"
}
}
Les contacts sont triés par activité la plus récente en premier. Continuez la pagination avec lastActivityAt tant que hasMore est true.
Lire les messages d’un contact
curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
| Paramètre de requête | Requis | Description |
|---|---|---|
pageSize |
Non | Messages par page. 30 par défaut, 100 maximum. |
beforeTimestamp |
Non | Curseur de pagination — récupérez les messages antérieurs à cet horodatage ISO. |
Réponse
{
"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"
}
}
Les messages sont renvoyés du plus récent au plus ancien ; parcourez l’historique page par page avec beforeTimestamp.
Lire l’utilisation des crédits et l’état des campagnes pour l’ensemble de votre portefeuille
GET /v1/subaccounts/credit-usage · GET /v1/subaccounts/campaign-status
Deux synthèses de type tableau de bord pour tous les sous-comptes que vous gérez, afin de créer vos propres rapports d’agence au lieu de cliquer sur chaque client un par un.
Utilisation des crédits
curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
| Paramètre de requête | Requis | Description |
|---|---|---|
from / to |
Oui | Plage de dates ISO. |
subAccountId |
Non | Omettez pour un résumé à l’échelle de l’agence, une ligne par sous-compte. Incluez pour passer en mode détail : le résumé de ce sous-compte ainsi que ses enregistrements d’utilisation bruts et paginés. |
limitCount |
Non | Mode détail uniquement. 500 par défaut, 2000 maximum. |
startAfterTimestamp |
Non | Mode détail uniquement — curseur de pagination. |
{
"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
}
}
Transmettez subAccountId et la réponse contiendra également records : les frais individuels avec amount, reason, campaignName, contactName et timestamp. Un client utilisant sa propre clé BYOK plutôt que vos crédits verra ses chiffres de coût/jeton masqués (costsRedacted: true) — il s’agit de télémétrie des coûts de la plateforme, et non d’informations à afficher à un revendeur. |
État de la campagne
curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
| Paramètre de requête | Requis | Description |
|---|---|---|
pageSize |
Non | Sous-comptes par page. Par défaut 10, maximum 50. |
lastDocumentId |
Non | Curseur de pagination. |
searchQuery |
Non | Filtrer par nom ou e-mail de sous-compte. |
{
"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 signalent les sous-comptes qui méritent une attention particulière — une campagne en pause, ou une campagne sans canal associé, par exemple. Utilisez ceci pour créer un tableau de bord de contrôle de santé pour l’ensemble du portefeuille plutôt que d’ouvrir chaque client pour remarquer une campagne bloquée.
Pour la messagerie chronologique et l’activité de crédit pour chaque client (une série prête à être mise en graphique plutôt qu’un instantané ponctuel), voir
GET /analytics/agency-rollupdans le guide de l’API Analytics.
Déployez un compte client déjà configuré
PUT /v1/snapshots/default · POST /v1/snapshots/{snapshotId}/apply
Un instantané est un modèle réutilisable : un ou plusieurs agents IA ainsi que leur base de connaissances, leurs outils et leurs médias, capturés depuis votre propre compte. Deux points de terminaison permettent de l’intégrer à votre flux de provisionnement.
Automatique — chaque nouveau client en est doté dès sa création. Marquez un instantané comme étant votre modèle par défaut une seule fois, et chaque compte que vous créerez par la suite sera installé avec celui-ci. Cela couvre les comptes créés via POST /v1/subaccounts, les comptes que vous créez dans le tableau de bord, et les comptes créés automatiquement lorsqu’un client paie via votre lien de paiement.
Tout d’abord, trouvez l’identifiant de l’instantané :
curl "https://api.dmchamp.com/v1/snapshots" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Ensuite, définissez-le comme étant le modèle par défaut :
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" }'
C’est tout pour l’intégration. Envoyez {"snapshot_id": null} pour le désactiver à nouveau. Vous pouvez faire la même chose depuis le tableau de bord en cliquant sur l’étoile sur la page Instantanés.
Pour lire ce qui est actuellement mis en favori (par exemple, avant qu’un script de provisionnement ne décide s’il faut en définir un), GET /v1/snapshots/default renvoie { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } } — null quand rien n’est mis en favori. GET /v1/snapshots (utilisé pour trouver l’id ci-dessus) renvoie le même default_snapshot_id avec le tableau complet snapshots, donc la plupart des intégrations n’ont besoin que de cet appel. Les champs complets de l’objet instantané se trouvent dans le guide Snapshots.
À la demande — installation dans un compte spécifique. Utile pour l’intégration d’un client existant, ou pour fournir un second modèle à un client ultérieurement.
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" }'
Omettez sub_account_id et il s’installera dans votre propre compte d’agence à la place. Comme pour les points de terminaison /subaccounts, ceux-ci nomment le compte cible dans le chemin ou le corps de la requête plutôt que via le paramètre ambiant sub_account_id.
Bon à savoir avant de construire dessus :
- Les agents installés démarrent en pause. Connectez d’abord les canaux du client, puis activez l’agent. Cela est vrai pour le chemin automatique comme pour le chemin à la demande.
- Le provisionnement n’échoue jamais à cause d’un instantané. Si l’installation ne peut pas aboutir, le compte client est tout de même créé et utilisable — il arrive simplement vide et vous pouvez appliquer l’instantané par la suite.
- Les canaux, calendriers et connexions OAuth ne sont jamais copiés. Chaque compte connecte les siens. Les outils utilisant une clé API simple continuent de fonctionner immédiatement.
- Appliquer deux fois crée une seconde copie. Rien n’est écrasé.
Créer le modèle lui-même via l’API
POST /v1/snapshots · agents, fonctions personnalisées et médias via l’API
La section ci-dessus distribue un instantané créé par quelqu’un dans le tableau de bord. La partie création est également exposée, de sorte que la boucle complète — assembler la configuration principale une fois, la capturer, la transmettre à chaque client — peut être exécutée à partir du code.
Les éléments, dans l’ordre où un script de provisionnement les utilise :
- Créez vos fonctions personnalisées.
POST /v1/custom-functionsen crée une ;GET /v1/custom-functionsliste celles que vous avez, etGET,PUTetDELETEsur/v1/custom-functions/{customFunctionId}permettent de lire, mettre à jour et supprimer une fonction.POST /v1/custom-functions/testeffectue un test à blanc d’une définition avant que vous ne l’enregistriez. - Créez et configurez l’agent.
POST /v1/agentsle crée,PUT /v1/agents/{agentId}le met à jour, etPATCH /v1/agents/{agentId}/activeavec{ "active": false }le maintient en pause pendant que vous travaillez (le même appel avectruele met en ligne).GET /v1/agentsles liste. - Donnez ses capacités à l’agent.
POST /v1/agents/{agentId}/custom-functionsavec{ "custom_function_id": "..." }attache une fonction à l’agent ; leDELETE /v1/agents/{agentId}/custom-functions/{customFunctionId}correspondant la détache. - Remplissez la bibliothèque multimédia.
POST /v1/agents/{agentId}/media-librarytéléverse un élément (JSON avecbase64Data,mimeType,title,description) ;GETliste les éléments de l’agent, etPATCH/DELETEsur/{itemId}permettent de mettre à jour ou de supprimer un élément. - Capturez-le en tant qu’instantané.
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
}'
À partir de là, il s’agit de la section précédente : définissez-le comme favori par défaut afin que chaque nouveau client en soit doté dès sa création, ou appliquez-le à la demande. La gestion courante se trouve à côté : PATCH /v1/snapshots/{snapshotId} avec { "name": "..." } en renomme un, DELETE /v1/snapshots/{snapshotId} en supprime un (et retire le statut de favori s’il s’agissait du défaut), et GET /v1/snapshots/apply-targets liste tous les comptes sur lesquels vous pourriez effectuer une installation.
Les points de terminaison pour les agents, les fonctions personnalisées et les médias acceptent tous sub_account_id, de sorte que les mêmes appels peuvent également gérer un agent directement dans le compte d’un client. Les appels d’instantané agissent toujours sur votre compte d’agence — le modèle reste avec vous. Les schémas complets de requête et de réponse pour tous ces éléments se trouvent dans la Référence de l’API.
Gérer vos niveaux de tarification via l’API
GET /v1/agency/pricing-tiers · POST /v1/agency/pricing-tiers · PATCH /v1/agency/pricing-tiers/{tierIndex} · DELETE /v1/agency/pricing-tiers/{tierIndex}
Les plans que vous vendez dans Mode SaaS → Niveaux de tarification peuvent être lus et modifiés par code, afin que votre propre panneau d’administration ou script de provisionnement puisse ajouter un plan, ajuster un prix ou distribuer un lien de paiement sans que personne n’ait à ouvrir le tableau de bord. Authentifiez-vous avec votre clé API d’agence comme pour tout autre appel sur cette page ; ces points de terminaison sont au niveau de l’agence, ils ne prennent donc aucun sub_account_id. Chaque écriture exécute la même validation et la même synchronisation produit-et-prix Stripe que l’enregistrement dans le tableau de bord, de sorte qu’un plan créé ici est indiscernable de celui que vous avez configuré manuellement.
Lister vos niveaux
curl "https://api.dmchamp.com/v1/agency/pricing-tiers" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Réponse
{
"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
}
}
Chaque niveau est renvoyé avec son tierIndex — sa position dans votre liste de Plans, qui est la manière dont les trois autres appels le désignent — et un checkout_url prêt à être partagé, le même lien que l’onglet Paiements vous donne, pointant déjà vers le domaine en marque blanche sur lequel ce plan est vendu.
Ajouter un niveau
Le corps est un objet de niveau ; il est ajouté à la fin de votre liste.
curl -X POST "https://api.dmchamp.com/v1/agency/pricing-tiers" \
-H "X-API-Key: YOUR_AGENCY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Starter",
"credits": 1000,
"price_cents": 2900,
"currency": "usd",
"billing_interval": "month",
"trial_days": 14,
"trial_credits": 250,
"trial_card_required": false,
"trial_hard_expiry": true,
"features": ["channels_3", "channel_whatsapp_web", "webhooks"]
}'
La réponse contient le niveau créé, y compris le tierIndex sur lequel il a atterri et son checkout_url.
Modifier un niveau
Envoyez uniquement les champs que vous souhaitez modifier ; tout le reste du plan est laissé tel quel.
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 champ que l’API ne reconnaît pas est refusé plutôt qu’ignoré, et l’erreur le nomme — ainsi, une faute de frappe ne peut jamais modifier silencieusement un paramètre qui semble actif mais ne fait rien. La modification du prix, des crédits, de la devise ou de la fréquence de facturation crée un nouveau prix dans votre Stripe ; les clients qui ont déjà souscrit restent sur ce pour quoi ils se sont inscrits.
Supprimer un niveau
curl -X DELETE "https://api.dmchamp.com/v1/agency/pricing-tiers/2" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Même règle que pour le tableau de bord : un plan qui a encore des abonnés actifs ne peut pas être supprimé. La demande est refusée, vous indiquant combien d’abonnés y sont inscrits — annulez ou migrez-les d’abord. Une suppression réussie répond avec vos niveaux restants, déjà renumérotés.
Les champs d’un niveau
| Champ | Description |
|---|---|
label / description |
Le nom du plan et la ligne facultative affichée sur votre page de paiement. |
credits |
Crédits que le client obtient par mois sur un plan mensuel ou annuel, et par période de facturation sur un plan hebdomadaire. |
price_cents |
Prix par intervalle de facturation, dans la plus petite unité monétaire (2900 = 29,00 $). Sur un plan annuel, il s’agit du prix de l’année entière. |
currency |
Code ISO en minuscules — usd, eur, gbp, etc. |
billing_interval / billing_interval_count |
month (par défaut), year, ou week avec un nombre de 1 à 52 pour « tous les N semaines ». |
trial_days |
Durée de l’essai gratuit, de 0 à 90. 0 (ou l’omettre) signifie aucun essai. |
trial_credits |
Crédits avec lesquels le client commence l’essai. Par défaut, le credits du plan. |
trial_card_required |
false permet au client de commencer l’essai sans saisir de carte. Par défaut true. |
trial_hard_expiry |
true renvoie les crédits d’essai inutilisés à votre réserve et verrouille le compte du client lorsqu’un essai se termine sans mise à niveau. Par défaut false — voir Expiration stricte après l’essai. |
rollover_cap_months |
Mois d’allocation que les clients de ce plan peuvent conserver entre deux renouvellements — un nombre de 0 à 120, fractions autorisées. 0 ne reporte rien ; null (par défaut) signifie aucun plafond. Voir Plafonner ce qui est reporté. |
rollover_expiry_days |
Jours après lesquels les crédits inutilisés sont supprimés au renouvellement suivant — un nombre entier de 1 à 3650. null (par défaut) signifie qu’ils n’expirent jamais. |
features / feature_settings |
Ce que les clients de ce plan obtiennent — les mêmes identifiants de fonctionnalité que Choisir les types de canaux qu’un client peut connecter. |
team_seats_limit |
Sièges d’équipe accordés par le plan : un nombre exact, 0 pour aucun, -1 pour illimité. |
white_label_config |
Sur lequel de vos domaines en marque blanche le plan est vendu. |
Les champs d’essai n’ont de sens que pour un plan qui inclut un essai : enregistrez un niveau avec trial_days: 0 et ils seront supprimés. Les identifiants de produit et de prix Stripe du plan sont gérés pour vous et ne peuvent pas être définis manuellement.
Trois points à bien comprendre :
- Les index de niveau sont des positions, pas des identifiants permanents. La suppression d’un plan décale tous les plans suivants d’un rang vers le bas. Récupérez donc la liste après toute modification — et copiez à nouveau les liens de paiement que vous avez publiés, exactement comme vous le feriez après avoir supprimé un plan dans le tableau de bord.
- Le mode SaaS doit être configuré en premier. Ces points de terminaison nécessitent un compte d’agence avec marque blanche et une clé Stripe déjà enregistrée ; sans cela, il n’y a pas de compte Stripe sur lequel le produit et le prix du plan peuvent exister.
- Vingt plans est la limite, tout comme dans le tableau de bord. Le champ
max_tiersdans la réponse de la liste vous indique la limite actuelle.
Les schémas complets de requête et de réponse se trouvent dans la Référence de l’API, sous Agence.
Définissez votre prix par crédit via l’API
GET /v1/agency/credit-price · PATCH /v1/agency/credit-price
Le prix que les clients paient pour les recharges ponctuelles (Mode SaaS → Tarification par crédit) peut également être lu et modifié par le code. Cette fonctionnalité est conçue pour les cas où le prix doit évoluer de manière autonome : une agence qui vend des crédits dans une devise mais facture dans une autre peut laisser une tâche planifiée réviser le prix en fonction des variations du taux de change, plutôt que de demander à quelqu’un de le modifier manuellement chaque semaine.
Lire le prix actuel
curl "https://api.dmchamp.com/v1/agency/credit-price" \
-H "X-API-Key: YOUR_AGENCY_API_KEY"
Réponse
{
"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 est le prix le plus bas autorisé par la plateforme dans cette devise, afin qu’une tâche puisse vérifier un nouveau prix avant de l’envoyer. Les trois valeurs sont null tant qu’aucun prix n’a été défini.
Le modifier
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" }'
Envoyez uniquement ce que vous souhaitez modifier. price_per_credit_cents est le prix dans la plus petite unité monétaire (130 = 1,30 R$) ; currency est un code ISO en minuscules ; note est une ligne optionnelle de 200 caractères maximum affichée aux clients directement sous le prix par crédit sur leur page de facturation — pratique pour un prix de référence dans une autre devise, tel que “0,25 USD par crédit à notre taux de référence”. Envoyez "note": "" pour le supprimer. La réponse a la même forme que la lecture ci-dessus, ce qui permet à une tâche de comparer et d’ignorer l’écriture si rien n’a changé.
Les mêmes règles que dans le tableau de bord s’appliquent : le prix ne peut pas être inférieur au minimum de la plateforme pour cette devise, et le compte doit disposer de la marque blanche (white labeling). Contrairement aux points de terminaison des niveaux de tarification, aucune clé Stripe n’est requise pour lire ou modifier cette valeur.
Donnez à une tâche une clé qui ne peut rien faire d’autre
Placer votre clé d’agence complète dans un planificateur donne plus d’accès qu’une mise à jour de prix ne le nécessite. À la place, créez une clé à portée limitée restreinte à la zone Prix du crédit d’agence : cette clé peut lire et modifier le prix par crédit et rien d’autre — elle ne peut pas toucher aux sous-comptes, aux plans, aux crédits ou à votre connexion 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 réponse contient la nouvelle clé dans api_key une seule fois — elle n’est plus jamais affichée, alors enregistrez-la immédiatement. Définissez "read_only": true pour une clé qui a seulement besoin de lire le prix, et ajoutez "expires_at" (une date ISO) si vous souhaitez qu’elle cesse de fonctionner d’elle-même. Seule la clé du propriétaire du compte peut créer des clés à portée limitée ; listez-les ou révoquez-les avec GET /v1/api-keys et DELETE /v1/api-keys/{id}.
Laisser un sous-compte lire votre tarification
GET /v1/subaccounts/agency-pricing
Tous les autres points de terminaison sur cette page sont appelés avec votre clé d’agence, ciblant éventuellement un client via sub_account_id. Celui-ci est l’opposé : il est appelé avec la propre clé API du sous-compte, sans sub_account_id, afin que la propre page de recharge d’un client (ou une intégration que vous construisez pour lui) puisse afficher ce que vous lui facturez sans jamais voir votre compte d’agence.
curl "https://api.dmchamp.com/v1/subaccounts/agency-pricing" \
-H "X-API-Key: THE_SUB_ACCOUNTS_OWN_API_KEY"
Réponse
{
"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"
}
}
Ceci reflète exactement ce que GET /v1/agency/pricing-tiers et GET /v1/agency/credit-price vous renvoient en tant qu’agence, moins tout ce que le client n’a pas besoin de voir (identifiants Stripe, max_tiers, etc.). Cela ne fonctionne que pour un compte qui est réellement un sous-compte avec une agence liée — l’appeler depuis votre propre compte d’agence renvoie une erreur de permission.
Points à garder à l’esprit
- Utilisez votre clé d’agence. Authentifiez chaque appel avec la clé API de votre compte d’agence — et non celle du sous-compte. Le paramètre
sub_account_idest ce qui redirige l’action. - Les crédits proviennent du sous-compte. Les achats et les frais récurrents sont débités du solde de crédit du sous-compte ciblé, et non du vôtre.
- Une erreur
404signifie « ce n’est pas votre sous-compte ». Vérifiez l’identifiant et assurez-vous que le compte est bien l’un de ceux que vous gérez. - Le paramètre est facultatif partout où il est accepté. Omettez-le et le même point de terminaison agira sur votre compte d’agence, vous permettant ainsi de réutiliser une seule intégration pour les deux.
Connexe
- Accès API — authentification, URL de base, erreurs, limites de débit.
- Sous-comptes — lister et gérer les comptes que vous pouvez cibler.
- Recharge automatique de sous-compte — accorder des crédits à un sous-compte via webhook + API.
- API Campagnes — créer, mettre à jour et copier des campagnes, y compris la référence complète des champs.
- API Connexion de canal — connecter les canaux d’un client et les acheminer vers une campagne.
- Guide de l’API Analytics (dans la section API) — le cumul des sous-comptes d’agence et tous les autres points de terminaison de rapport.
- Snapshots — ce qu’un instantané capture et comment en construire un dans le tableau de bord.