DM Champ Docs

API para Agências

Como agência, você pode usar a mesma API REST que seus clientes usam, mas direcionar solicitações individuais para uma de suas subcontas gerenciadas em vez de sua própria conta. Isso permite que você crie ferramentas que integram um cliente de ponta a ponta — criando suas campanhas, treinando sua IA em uma base de conhecimento, importando seus contatos, conectando seus canais de mensagens e comprando números de telefone — tudo sem precisar fazer login em cada subconta manualmente.

Esta página cobre apenas o comportamento específico de agências: como agir em nome de uma subconta com o parâmetro sub_account_id. Para o básico (geração de chave, autenticação, URL base, formato de erro, limites de taxa), comece pelo guia de Acesso à API. Tudo o que está lá também se aplica aqui — você se autentica com a chave de API da sua conta de agência.

Nota: Esta página é técnica. Se você não for um desenvolvedor, compartilhe-a com a pessoa responsável pela criação da sua integração.


Como funciona o “agir em nome de”

Por padrão, toda solicitação de API atua na conta que possui a chave de API — sua conta de agência. Para atuar em uma conta de cliente gerenciada, adicione o parâmetro opcional sub_account_id à solicitação, definido como o ID da conta desse cliente.

  • Omitir sub_account_id → a solicitação atua em sua própria conta de agência.
  • Incluir sub_account_id → a solicitação atua nessa subconta, mas apenas após a plataforma confirmar que a subconta é realmente sua.

Você sempre se autentica com a chave de API da sua conta de agência. Você nunca precisa da chave da própria subconta e nunca manipula as credenciais da subconta.

Onde inserir

  • Endpoints GET / DELETE → passe-o como um parâmetro de consulta: ?sub_account_id=THE_SUB_ACCOUNT_ID (junto com seu apiKey, se você se autenticar por consulta).
  • Endpoints POST / PUT / PATCH → inclua-o no corpo da requisição JSON como "sub_account_id": "THE_SUB_ACCOUNT_ID".
  • Assistentes de IA → nada a configurar. O servidor MCP carrega a mesma configuração em suas ferramentas de leitura, portanto, uma conexão com sua chave de agência pode gerar relatórios sobre cada cliente: basta nomear o cliente em sua solicitação (“quantos contatos o Bella’s Bistro tem?”). Ações de escrita também estão disponíveis: cada endpoint que aceita sub_account_id é exposto como uma ferramenta, para que você possa criar, alterar e enviar em nome de um cliente a partir da mesma conexão.

Encontrando o ID de uma subconta

O sub_account_id é o identificador único da conta do cliente. Você pode obter a lista de suas subcontas e seus respectivos IDs nos endpoints da API de SubAccounts (veja o guia de Sub-Accounts) ou na página de Sub Accounts na barra lateral.


A propriedade é sempre verificada

Quando você passa um sub_account_id, a plataforma verifica se a conta é uma subconta real e se ela pertence à sua agência. Somente então a solicitação é processada.

Se o ID for desconhecido, não for uma subconta ou pertencer a uma agência diferente, a solicitação falhará com uma resposta 404:

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

Por que 404 e não 403? Uma resposta “proibido” (forbidden) diria a um estranho que o id existe, mas não pertence a ele. Retornar o mesmo 404 para “não existe” e “não é seu” significa que o endpoint não pode ser usado para descobrir quais ids de conta pertencem a outras agências. Trate um 404 aqui como “esta não é uma subconta que você gerencia.”


Onde sub_account_id é suportado

sub_account_id é aceito em praticamente todos os endpoints de recurso — qualquer chamada que crie, leia, atualize ou exclua dados da própria conta. Na prática, você pode provisionar e executar toda a configuração de uma subconta com sua chave de agência:

  • Configuração de IA — campanhas, agentes, perguntas frequentes, fontes de base de conhecimento (rastreamento de site e upload de documentos), grupos de base de conhecimento, transmissões, funções personalizadas, servidores MCP
  • Contatos e CRM — contatos (incluindo importação), listas, tags, tarefas, negócios, agendamentos, eventos
  • Canais e números — conectar WhatsApp / WhatsApp Web / Telegram / Instagram & Messenger / LINE, pesquisar / comprar / gerenciar números de telefone, modelos de WhatsApp, roteamento de canal
  • Mensagens e conteúdo — enviar mensagens, sessões de chat, exportações de chat, resumos diários
  • Configurações e integrações — webhooks, configuração de widget de chat, configuração de white-label, SMS BYOK e outras configurações de conta, análises

Em todos eles, o parâmetro é opcional — deixe-o de fora e a chamada atuará em sua própria conta de agência, para que uma única integração sirva para ambos. Créditos e uso sempre vêm da conta que você direciona: cobranças por campanhas, mensagens, tags e números de uma subconta são debitadas do saldo da subconta.

Onde NÃO se aplica

Alguns endpoints são de nível de agência ou auto-endereçados e ignoram sub_account_id:

  • Gerenciamento das próprias subcontas — os endpoints de SubAccounts (criar / listar / atualizar uma subconta) e o endpoint de limite de gastos BYOK já nomeiam a subconta em seu próprio caminho de URL. Os endpoints de precificação e política e os endpoints de monitoramento de chat seguem o mesmo padrão.
  • Cópia de um Agente entre contasPOST /v1/subaccounts/agents/copy nomeia ambas as contas, tomando o destino como targetUserId. Veja o exemplo prático abaixo. (O POST /v1/subaccounts/campaigns/copy mais antigo funciona da mesma forma, mas está obsoleto junto com o restante da API de Campanhas.)
  • Ajuste de créditos e os dois rollups de toda a agênciaPOST /v1/subaccounts/credits identifica a subconta por email; GET /v1/subaccounts/credit-usage e GET /v1/subaccounts/campaign-status geram relatórios de todas as subcontas de uma só vez, portanto, não há uma conta única para direcionar.
  • A conta da sua própria agência — O gerenciamento de chaves de API, relatórios de uso da agência, gerenciamento de equipe e seus níveis de precificação sempre atuam na conta da sua agência.
  • Webhooks de mensagens recebidas — os endpoints para os quais sistemas externos enviam dados estão vinculados à conta cujas credenciais os configuraram, portanto, não há nada para redirecionar.

A lista sempre atualizada e legível por máquina de quais parâmetros cada endpoint aceita encontra-se na referência da API do seu painel (Settings → Integrations → API Key) e na especificação OpenAPI em GET /v1/docs/openapi.yaml. Lançamos alterações na API com frequência — trate essas fontes como a referência definitiva.

Página de configurações da Chave de API com chave mascarada e controle de Regenerar

Configurações → Integrações → Chave de API — a chave da sua agência fica aqui, junto com o link para a referência completa da API.


Exemplo prático: conectar Instagram e Messenger para uma subconta

Conectar Instagram e Messenger é um fluxo baseado em navegador. Você o inicia com a API, entrega a URL de consentimento retornada ao cliente (ou abre para ele), espera que ele autorize no navegador e, em seguida, escolhe qual página conectar — tudo isso direcionando a subconta dele com sub_account_id.

Passo 1 — Iniciar a conexão

Chame o endpoint de conexão com o sub_account_id do cliente no corpo. Nenhuma credencial é enviada aqui; a plataforma retorna uma URL de consentimento que o cliente deve abrir em um navegador, além de um token de correlação de uso único.

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

Resposta:

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

Envie o cliente para oauth_url em um navegador para autorizar. O state_token correlaciona esta tentativa e é um segredo de curta duração — não o registre em logs. A tentativa expira em expires_at; se expirar, comece novamente.

Passo 2 — Fazer polling até que as páginas carreguem

Após a autorização do cliente, faça a sondagem (polling) do endpoint de status (com o mesmo sub_account_id, desta vez como um parâmetro de consulta) até que as páginas conectáveis apareçam.

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

Resposta:

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

O campo status passa por pendingtoken_receivedpages_loadedconnected. Aguarde por pages_loaded antes de selecionar uma página. Dois estados de erro terminal também podem aparecer em vez de progredir: failed e expired (o cliente recusou o consentimento ou o período de ~30 minutos do token de estado expirou) — um campo reason é incluído quando qualquer um deles ocorre. Pare a sondagem e reinicie na Etapa 1 se vir um deles; não espere por pending para sempre. Tokens de acesso à página nunca são retornados.

Passo 3 — Selecione a página para conectar

Escolha um dos IDs de página do Passo 2 e selecione-o. Selecionar uma página conecta tanto o Instagram quanto o Messenger para essa página. Inclua sub_account_id no corpo novamente.

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()

Resposta:

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

É isso — o Instagram e o Messenger agora estão conectados na subconta do cliente. Você forneceu apenas o page_id; a credencial subjacente é resolvida no servidor e nunca passa pela sua integração.


Exemplo prático: comprar um número para uma subconta

A compra de um número funciona da mesma forma: pesquise com sub_account_id na consulta e, em seguida, compre com ele no corpo da requisição. Os créditos são deduzidos do saldo da subconta, e o número é provisionado na subconta.

Pesquisa (cURL):

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

Compra (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();

Compra (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()

Resposta:

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

O número é provisionado no estado PURCHASED e o registro do remetente do WhatsApp continua em segundo plano. Faça a sondagem de GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456 até que o status atinja ONLINE antes de enviar.


Exemplo prático: enviar um Agente modelo para cada novo cliente

O padrão usual de agência é manter um Agente mestre na sua conta de agência, configurado da maneira que você deseja que cada cliente comece, e criar uma cópia dele em cada nova subconta no momento do provisionamento. São três chamadas e nada precisa ser repetido depois: a cópia mantém suas configurações até que você as altere.

Passo 1 — Copiar o 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
  }'

A resposta contém o ID do novo Agente em data.agent_id. As FAQs, a base de conhecimento e a biblioteca de mídia são incluídas; os modelos de WhatsApp, postagens sociais conectadas e contatos da conta de origem, deliberadamente, não são. Lista completa de campos na API de Agentes de IA.

Observe que este endpoint utiliza targetUserId em vez de sub_account_id — ele nomeia ambas as contas. As duas chamadas abaixo usam o parâmetro sub_account_id normal.

Passo 2 — Ativá-lo

A cópia sempre chega pausada, portanto, não pode enviar mensagens a ninguém até que você autorize. Este também é o momento de definir o nível de IA em que você deseja que o cliente esteja; ele permanece lá, então não há necessidade de reaplicá-lo em uma programação.

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

Para impedir que o cliente altere o nível posteriormente, bloqueie os níveis permitidos na subconta em vez de reenviar o valor.

Passo 3 — Direcionar os canais do cliente para ela

A cópia também chega sem roteamento, portanto, nada chega até ela até que você a torne a responsável pelas respostas nos canais que o cliente conectou. Uma chamada por 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" }'

A partir daqui, uma primeira mensagem de um contato desconhecido nesse canal é captada pelo Agente copiado automaticamente. Veja Apontar um canal para um Agente para os outros canais e roteamento por número.

Defina o fuso horário do cliente ao criar a subconta. Passe time_zone_id em POST /v1/subaccounts. As horas ativas da campanha são avaliadas no próprio fuso horário da subconta, portanto, um cliente criado sem um terá seu agendamento lido em relação ao UTC — o que altera silenciosamente quando o assistente tem permissão para responder.


Pule o assistente de configuração para um cliente que você mesmo configura

POST /v1/subaccounts

Por padrão, na primeira vez que o proprietário de uma nova subconta faz login, ele é guiado pelo Assistente de Configuração. Para clientes com serviço completo — onde você cria a campanha e conecta os canais antes mesmo de o cliente fazer login — passe guided_onboarding: false ao criar a conta. Eles serão direcionados para o painel de controle, e a entrada Assistente de Configuração ficará oculta na barra lateral deles.

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

Omita o campo (ou envie true) e o assistente se comportará exatamente como sempre se comportou, portanto, as integrações existentes não precisam de alterações. Para devolver o assistente a um cliente mais tarde, exiba novamente o item guided_onboarding com PUT /v1/subaccounts/{subAccountUid}/menu-visibility (abaixo) — a visibilidade do menu controla se o assistente pode ser acessado, guided_onboarding controla apenas o redirecionamento do primeiro login.


Desative Tarefas, Resumos Diários ou a Biblioteca de Mídia para um cliente

POST /v1/subaccounts

Esses três recursos estão ativados para cada novo cliente, a menos que você especifique o contrário, e eles se comportam de maneira diferente de todos os outros recursos neste guia: eles são de opt-out (desativação opcional), não de opt-in. Deixá-los de fora da features não é suficiente por si só, porque a lista features de uma integração mais antiga simplesmente nunca os mencionou — não conseguimos distinguir entre “a agência desativou isso” e “esta lista foi escrita antes de a opção existir”.

Portanto, declare isso explicitamente com 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
    }
  }'

Cada chave é opcional; tudo o que você omitir permanecerá ativado. Com tasks: false, a IA para de criar tarefas para aquele cliente e nenhum e-mail de “Nova Tarefa Criada” é enviado; com daily_summaries: false, o resumo noturno nunca é gerado ou enviado por e-mail.

feature_settings é a única coisa que desativa esses três recursos no momento da criação. Deixá-los de fora da features não faz nada por si só, não importa como o restante da sua lista esteja — isso é intencional, para que uma integração mais antiga não perca silenciosamente todos os três.

Para alterar qualquer um desses itens posteriormente, envie a lista features completa para PUT /v1/subaccounts/{subAccountUid}/features — lá, a presença na lista ativa um recurso e a ausência o desativa.


Faça login automático de seus clientes em suas subcontas (SSO)

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

Uma única chamada com a chave de API da sua agência retorna uma URL pronta para abrir que conecta o cliente diretamente à sua própria subconta — sem tela de login, sem etapa de senha, nada para construir por cima. Abra em uma nova aba, em um redirecionamento ou em um iframe dentro do seu próprio produto.

Campo Obrigatório Descrição
redirect Não Página no aplicativo em que você deseja que o cliente termine, por exemplo, "/chats" ou "/agents". Retornado como deep_link_url na resposta.
app_base_url Não Host do painel para o link. O padrão é o seu domínio de white-label (ou o domínio da plataforma, caso não tenha um). Deve ser 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" }'

Resposta

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

Como usar bem:

  • Um salto. Abrir o url autentica o cliente e o leva diretamente para a página redirect do painel — sem tela de login, sem página intermediária. O deep_link_url nomeia o mesmo destino, para integradores que preferem navegar por um frame explicitamente após o login; uma vez que a sessão exista, qualquer caminho do painel funciona nesse contexto de navegador.
  • Crie sob demanda, abra imediatamente. O link contém uma credencial de login e expira após cerca de uma hora. Solicite-o no lado do servidor no momento em que o cliente clicar, e nunca o armazene ou envie por e-mail.
  • O token de login viaja no fragmento da URL (#…), que os navegadores nunca enviam para servidores, e é removido da barra de endereços no momento em que é consumido.
  • Apenas suas próprias subcontas. O endpoint recusa qualquer conta que sua agência não possua.
  • Um link expirado mostra um erro claro com um caminho para tentar novamente — crie um novo.

Ocultar itens de navegação em uma subconta

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

Controla quais itens da barra lateral e de configurações uma subconta vê — útil quando você incorpora o painel e deseja apenas as superfícies que seu produto ainda não cobre. Tudo o que não estiver listado permanece visível; envie null como o valor total de menuVisibility para redefinir tudo como visível. Ocultar um item oculta a entrada do menu — combine isso com os recursos que você concede à subconta para um controle rígido.

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

Resposta

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

side_nav aceita estas 13 chaves, que correspondem aos nomes dos itens da barra lateral: Dashboard, DailySummaries, Chats, Contacts, Deals, Tasks, Automations, Campaigns, Appointments, Settings, Help, CreditsCounter (o saldo de crédito exibido na barra lateral) e guided_onboarding (o Assistente de Configuração). Três chaves adicionais — AiInsights, Sub Accounts e Agency Reselling — são aceitas, mas não fazem nada: elas só se aplicavam ao painel clássico desativado, portanto, defini-las não tem efeito em suas subcontas. Chaves ausentes significam visível; quando você mesmo faz login na subconta, os itens ocultos são exibidos temporariamente para que você possa sempre reverter as alterações.

Ocultar uma página do menu nunca concede acesso a ela. Automations precisa que o recurso automations seja concedido na subconta — defina a chave como true sem ele e a página ainda não aparecerá. Tasks e DailySummaries funcionam de forma inversa: eles estão ativados para cada cliente, a menos que você os desative (veja Desative Tarefas, Resumos Diários ou a Biblioteca de Mídia para um cliente).


Escolha quais tipos de canal um cliente pode conectar

PUT /v1/subaccounts/{subAccountUid}/features

As chaves de Tipos de Canal que você vê em um nível de plano são IDs de recursos comuns, portanto, você pode defini-las por cliente a partir da API em vez do painel. Este é um dos endpoints que nomeia a subconta em sua própria URL, por isso não requer sub_account_id.

ID do Recurso Canal
channel_chat_widget Widget de Chat do Site
channel_whatsapp_api API do WhatsApp Business
channel_whatsapp_web WhatsApp Web (número vinculado por QR)
channel_instagram Instagram
channel_messenger Facebook Messenger
channel_telegram Telegram
channel_line LINE
channel_viber Viber
channel_email Caixa de entrada de 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"
    ]
  }'

Três coisas para acertar:

  • A chamada substitui toda a lista de recursos. Envie todos os recursos que o cliente deve manter, não apenas aqueles que você está alterando. Os mesmos IDs funcionam como features em POST /v1/subaccounts quando você cria a conta.
  • Tipos de canal e contagem de canais são restrições separadas, e ambas se aplicam. channels_1 / channels_3 / channels_unlimited controlam quantas conexões; os IDs channel_* controlam quais tipos. O exemplo acima significa “até 3 conexões, e apenas Widget de Chat, WhatsApp Web ou Instagram”.
  • Não enviar nenhum ID de channel_* significa nenhuma restrição de canal. Esse é o comportamento original, e é por isso que os clientes existentes não foram afetados quando isso foi lançado. Envie um ou mais e todo o resto aparecerá como bloqueado na página de Canais do cliente com uma nota de upgrade em vez de um botão Conectar. Canais que o cliente já conectou continuam funcionando.

Definir a lista de canais em um nível de plano, para que cada cliente que compra esse nível a herde, é feito no painel, nas configurações do seu plano de agência. Este endpoint a define em uma subconta específica.


Defina um limite exato de membros da equipe para um cliente

PUT /v1/subaccounts/{subAccountUid}/limits

Os recursos do team_seats_* oferecem apenas níveis predefinidos (3 / 5 / 10 / ilimitado). Para dar a um cliente um número exato de assentos na equipe — 2, 7, 15, qualquer um — defina usage_limits.team_seats_limit em vez disso. Ele prevalece sobre as predefinições, e a plataforma o aplica em cada convite, adição direta e aceitação de convite: assim que o limite é atingido, convites adicionais são recusados pelo servidor.

  • Um número inteiro positivo é o limite exato.
  • 0 significa que os membros da equipe não estão incluídos — o cliente não pode convidar ninguém.
  • -1 significa ilimitado.
  • null limpa o limite personalizado e retorna para qualquer predefinição do team_seats_* que esteja na lista de recursos.

Reduzir o limite nunca remove membros existentes da equipe; apenas impede que novos sejam adicionados.

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

Você também pode defini-lo no momento da criação: POST /v1/subaccounts aceita usage_limits.team_seats_limit com a mesma semântica. Para ler o valor atual, busque a subconta com GET /v1/subaccounts?email=... e verifique usage_limits.team_seats_limit (ausente/null = os padrões decidem). O mesmo endpoint também atualiza credits, monthly_credits, roll_over_to_next_month, rollover_cap_months, rollover_expiry_days e byok_monthly_limit_usd — envie apenas as chaves que deseja alterar.

Como isso interage com os limites de assentos do plano SaaS. Seus planos SaaS podem ter sua própria franquia de assentos (definida no editor de planos — veja Assentos de equipe em um plano), que é aplicada automaticamente quando um cliente assina. Um limite que você define por meio deste endpoint conta como uma concessão manual: comprar um plano substitui esse limite pela franquia de assentos do próprio plano (essa compra é uma escolha explícita de plano), mas renovações mensais automáticas nunca sobrescrevem um limite manual — portanto, uma exceção única que você concede a um cliente persiste durante seu ciclo de faturamento. Limpar o limite manual com null devolve o controle do campo ao plano na próxima renovação.

Limite o que um cliente carrega entre renovações. Duas chaves usage_limits adicionais ficam ao lado de roll_over_to_next_month. Ambas também são aceitas por POST /v1/subaccounts no momento da criação, e null limpa qualquer uma delas.

Chave O que faz
rollover_cap_months Meses de franquia que o cliente pode manter. Um número de 0 a 120, frações permitidas (0.5 = meio mês). A cada renovação, o saldo não utilizado é reduzido para, no máximo, esse número de vezes a franquia concedida na renovação, antes que os novos créditos sejam adicionados; 0 não transporta nada.
rollover_expiry_days Um número inteiro de dias, de 1 a 3650. Créditos deixados sem uso por tanto tempo são descartados na primeira renovação após atingirem essa idade. O consumo sempre abate os créditos mais antigos primeiro, portanto, um cliente que gasta sua franquia a cada mês nunca perde nada.

Se não forem definidos, ambos recorrem ao plano do cliente; um valor enviado aqui prevalece sobre o do plano. Apenas créditos recorrentes (a franquia mensal e os créditos do plano) estão sujeitos a eles: recargas, recargas automáticas e adições únicas nunca são limitadas ou expiradas. Cada redução é registrada no histórico de créditos do cliente como um Ajuste de Crédito de Limite de Rolagem ou um Ajuste de Crédito de Créditos Expirados e nunca conta como uso. Os equivalentes no nível do plano são rollover_cap_months e rollover_expiry_days em um nível de preço — veja Os campos em um nível e Limitando o que é transferido.


Definir precificação e política de IA por cliente

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

Oito chaves adicionais por cliente, juntamente com /limits, /features e /menu-visibility acima. Cada uma utiliza o uid da subconta na URL (sem parâmetro de corpo/query sub_account_id — o destino já está nomeado no caminho) e tem o mesmo escopo: sua chave de agência, e a subconta deve pertencer à sua agência.

Quais modelos de IA um cliente pode usar

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 } inclui o cliente no (ou o exclui do) nível Max AI — nossa infraestrutura pelo preço de lista da plataforma. Ativar isso para um cliente BYOK altera o custo de IA dele de “gratuito na minha própria chave” para “cobrado contra meu pool de créditos”, portanto, é uma decisão deliberada por cliente em vez de um padrão para toda a agência.

Para restringir QUAIS níveis as campanhas e Agentes de um cliente podem escolher (em vez de apenas limitar o Max), use 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 é uma matriz extraída de standard, economy, max, mini — ela SUBSTITUI a lista de permissões do cliente. Envie null (ou []) para limpar a restrição e permitir que eles escolham qualquer nível. Isso é importante porque uma subconta que escolhe seu próprio nível de IA gasta do seu pool de créditos, então é a alavanca para definir quais modelos um cliente revendedor pode usar para aumentar sua fatura.

Uma resposta de espera enquanto o cliente está sem créditos

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 o saldo do cliente (ou seu pool) está vazio, a IA não pode responder e o contato não ouve nada. Com enabled: true, cada contato que escreve durante a interrupção recebe message uma vez (máx. 500 caracteres, enviado como está em todos os canais), e a IA responde a essas conversas de verdade assim que os créditos retornarem. enabled: false mantém o texto salvo para mais tarde; enabled: false sem message remove a configuração. O mesmo interruptor que Resposta de espera quando sem créditos no modal de Edição da subconta — veja Uma resposta de espera enquanto um cliente está sem créditos.

Quanto um cliente paga por ação de IA e a margem de lucro da taxa do WhatsApp

Duas maneiras de definir sua taxa voltada para o cliente, da mais simples à mais granular:

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/max-rate" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "rate": 0.35 }'

rate é o preço em créditos que o saldo PRÓPRIO da subconta queima por ação de IA do modelo Max — sua margem de lucro voltada para o cliente sobre o que seu pool realmente paga. null limpa a substituição de volta para o preço de lista da plataforma. A taxa deve ser pelo menos o que uma ação Max custa ao seu próprio pool (para que você nunca possa precificar um cliente abaixo do seu custo) e não mais que 10 créditos; uma solicitação fora desse intervalo é rejeitada com o piso calculado na mensagem de erro.

Para precificação por tipo de ação em vez de uma taxa Max fixa, use 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 é uma MESCLAGEM no mapa existente do cliente — uma chave que você não menciona é deixada como estava, e null redefine essa chave de volta ao seu padrão. As chaves reconhecidas:

Chave Preços
AI_MESSAGE Uma resposta de IA
AI_TOOL_USE Uma chamada de ferramenta de IA
EVALUATION_CALL Uma passagem de avaliação de chat
INTERRUPTION_HANDLING Lidar com uma interrupção no meio da resposta
CONTACT_TAG Uma tag de contato atribuída por IA
CHAT_SUMMARY Um resumo de chat
wa_carrier_multiplier Um multiplicador de margem aplicado a cada taxa de WhatsApp não relacionada à IA que o cliente paga: aluguel mensal de número, taxas de entrega em faixa gerenciada e custos de repasse de modelos Meta/Twilio.

As taxas por ação devem ser um número maior que 0 e até 10; wa_carrier_multiplier deve ser de pelo menos 1 (sem desconto abaixo do custo) e até 10. Enviar uma chave não reconhecida, ou um valor fora do intervalo, rejeita a solicitação INTEIRA e nomeia cada chave ofensiva, para que um erro de digitação nunca salve silenciosamente um preço que não é realmente aplicado.

Se você for um membro do Champions Circle, o insider-rate repassa sua taxa de 20% de desconto do Max/Lead Finder para um cliente em vez de aplicá-la a toda a agência:

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

Ativá-lo exige que sua própria conta de agência possua uma assinatura Circle; desativá-lo nunca exige, portanto, um membro com assinatura expirada sempre pode reverter a configuração de um cliente.

Bloquear seções do playbook de um 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 é uma matriz extraída de instructions, goal, rules, personality, conclude_unless — ela SUBSTITUI a lista bloqueada do cliente. Uma seção bloqueada é rejeitada no lado do servidor se a própria SUB-CONTA tentar alterá-la (diretamente ou por chave de API), enquanto você (via sub_account_id) e a visualização de administrador do painel do próprio cliente ainda podem editar qualquer coisa. Envie null (ou []) para desbloquear tudo. Útil para clientes “done-for-you” onde você é o dono do playbook e é avaliado pelo resultado.

Definir as preferências de notificação de um cliente em nome dele

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 substitui todo o conjunto de preferências de notificação do cliente (não é uma mesclagem por chave — envie todas as categorias que deseja manter, correspondendo a como a página de Configurações da própria subconta salva). Cada categoria em settings aceita enabled (booleano) e até três channels de email, in_app, webhook. Envie null para redefinir para os padrões da plataforma.

Todos os sete endpoints respondem { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } } e são registrados em auditoria com o valor antes/depois. Erros comuns: 403 se sua conta não for de Agência/Dev ou a subconta não for sua para gerenciar, 400 se não for uma subconta de agência ou se um valor estiver fora do intervalo.


Pause um cliente que suspendeu a assinatura dele

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

Quando um cliente suspende a assinatura com você, pause a conta dele em vez de excluí-la: tudo o que ele envia para imediatamente — mensagens de saída, transmissões, respostas de IA em todos os canais — e, ao fazer login, ele verá um bloqueio de Conta pausada em tela cheia (com sua mensagem opcional) em vez do aplicativo. Nada é excluído ou desconectado: agentes, campanhas, canais conectados, contatos e histórico de chat permanecem exatamente como estão, portanto, retomar a conta coloca o cliente exatamente de onde ele parou — sem necessidade de refazer a configuração.

Campo Obrigatório Descrição
message Não Exibido para o cliente na tela de bloqueio. Deixe em branco para usar o texto padrão.
reason Não Nota interna da agência armazenada com a pausa e no log de auditoria — nunca exibida para o 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" }'

Resposta

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

Quando o cliente retornar, POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (sem corpo) remove o bloqueio — o envio de mensagens e as respostas de IA são retomados imediatamente.

Vale a pena saber:

  • É o mesmo estado da alternância de Bloqueio rígido no painel (Bloqueando / Pausando uma Subconta) — um cliente pausado via API aparece como bloqueado no painel e vice-versa, e retomar a conta remove um bloqueio feito de qualquer um dos lados. O estado atual pode ser lido no campo agency_block em GET /v1/subaccounts (level de "none", "soft_blocked" ou "hard_blocked").
  • Ambas as chamadas são idempotentes. Pausar um cliente já pausado apenas atualiza a mensagem, o motivo e o carimbo de data/hora; retomar um cliente ativo não altera nada.
  • O cliente não é notificado por e-mail automaticamente — muitas agências usam white-label, portanto, informar o cliente fica a seu critério.
  • Sua própria cobrança do DM Champ permanece inalterada. Pausar um cliente afeta apenas o seu relacionamento com ele.
  • Assistentes de IA também podem fazer isso: o servidor MCP expõe esses endpoints como as ferramentas pause_subaccount e unpause_subaccount.

Conceder ou deduzir créditos diretamente

POST /v1/subaccounts/credits

Adiciona ou remove uma quantidade exata de créditos do saldo de uma subconta — o equivalente via API ao ajuste manual de crédito do painel. Esta é uma alteração de saldo única, distinta das configurações recorrentes monthly_credits, roll_over_to_next_month, rollover_cap_months e rollover_expiry_days em PUT /v1/subaccounts/{subAccountUid}/limits.

Este é o único endpoint nesta página que identifica a subconta por e-mail em vez de sub_account_id.

Campo Obrigatório Descrição
email Sim O e-mail da subconta, conforme existe em sua agência.
amount Sim Número diferente de zero de créditos. Positivo adiciona, negativo deduz.
description Não Exibido junto ao ajuste no histórico de crédito do cliente. O padrão é uma linha genérica “Ajustado pela agência 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" }'

Resposta

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

Um amount negativo que levaria o saldo abaixo de zero é recusado com 400, informando o saldo disponível e o valor que você tentou deduzir. Se o cliente estiver em seu próprio faturamento Stripe (modo de revenda), um valor adicionado também conta como créditos que ele comprou, portanto, sobrevive à sua próxima redefinição mensal da mesma forma que uma recarga real faria; em um cliente alocado padrão, ele é tratado como parte de sua franquia recorrente. De qualquer forma, são uma adição única, portanto, um limite de rolagem ou uma expiração definida na conta (ou em seu plano) nunca os reduz — apenas a franquia recorrente e os créditos do plano estão sujeitos a isso.


Ler as conversas de uma subconta

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

Permite criar uma visualização de monitoramento ou suporte das conversas de um cliente sem precisar fazer login na conta dele. Primeiro, liste os contatos com uma prévia da última mensagem e, em seguida, leia o histórico completo de mensagens de um contato.

Listar contatos

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
Parâmetro de consulta Obrigatório Descrição
pageSize Não Contatos por página. Padrão 25, máximo 50.
lastActivityAt Não Cursor de paginação — passe o lastActivityAt da página anterior para continuar.
searchQuery Não Filtrar por nome ou número de telefone do contato.

Resposta

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

Os contatos são ordenados pela atividade mais recente primeiro. Continue paginando com lastActivityAt enquanto hasMore for true.

Ler mensagens de um contato

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
Parâmetro de consulta Obrigatório Descrição
pageSize Não Mensagens por página. Padrão 30, máximo 100.
beforeTimestamp Não Cursor de paginação — buscar mensagens mais antigas que este timestamp ISO.

Resposta

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

As mensagens são retornadas da mais recente para a mais antiga; navegue pelo histórico retrocedendo as páginas com beforeTimestamp.


Ler o uso de créditos e a integridade das campanhas em toda a sua carteira

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

Dois resumos em estilo de painel sobre todas as subcontas que você gerencia, para criar seus próprios relatórios de agência em vez de clicar em cada cliente individualmente.

Uso de créditos

curl "https://api.dmchamp.com/v1/subaccounts/credit-usage?apiKey=YOUR_AGENCY_API_KEY&from=2026-08-01&to=2026-08-31"
Parâmetro de consulta Obrigatório Descrição
from / to Sim Intervalo de datas ISO.
subAccountId Não Omita para um resumo de toda a agência, uma linha por subconta. Inclua para alternar para o modo de detalhes: o resumo daquela subconta mais seus registros de uso brutos e paginados.
limitCount Não Apenas modo de detalhes. Padrão 500, máximo 2000.
startAfterTimestamp Não Apenas modo de detalhes — cursor de paginação.
{
  "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
  }
}

Passe subAccountId e a mesma resposta também trará records: cobranças individuais com amount, reason, campaignName, contactName e timestamp. Um cliente que gasta usando sua própria chave BYOK, em vez dos seus créditos, terá os valores de custo/token ocultos (costsRedacted: true) — isso é telemetria de custo da plataforma, não algo para exibir a um revendedor.

Status da campanha

curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
Parâmetro de consulta Obrigatório Descrição
pageSize Não Subcontas por página. Padrão 10, máximo 50.
lastDocumentId Não Cursor de paginação.
searchQuery Não Filtrar por nome ou e-mail da subconta.
{
  "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 sinalizam subcontas que merecem atenção — uma campanha pausada, ou uma sem nenhum canal direcionado a ela, por exemplo. Use isso para criar um painel de verificação de integridade em toda a sua carteira, em vez de abrir cada cliente para notar uma campanha parada.

Para mensagens de série temporal e atividade de crédito em todos os clientes (uma série pronta para gráficos, em vez de um instantâneo de um momento específico), consulte GET /analytics/agency-rollup no guia da API de Analytics.


Entregue uma conta de cliente já configurada

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

Um snapshot é um modelo reutilizável: um ou mais agentes de IA, além de sua base de conhecimento, ferramentas e mídia, capturados a partir da sua própria conta. Dois endpoints o colocam no seu fluxo de provisionamento.

Automático — todo novo cliente já nasce com ele. Marque um snapshot como padrão uma vez, e todas as contas que você criar a partir de então chegarão com ele instalado. Isso cobre contas criadas através do POST /v1/subaccounts, contas que você cria no painel e contas criadas automaticamente quando um cliente paga através do seu link de checkout.

Primeiro, encontre o id do snapshot:

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

Em seguida, defina-o como padrão:

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

Essa é toda a integração. Envie {"snapshot_id": null} para desativá-lo novamente. Você pode fazer a mesma coisa pelo painel clicando na estrela na página Snapshots.

Para ler o que está marcado como favorito atualmente (digamos, antes de um script de provisionamento decidir se deve definir um), GET /v1/snapshots/default retorna { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } }null quando nada está marcado. GET /v1/snapshots (usado para encontrar o id acima) retorna o mesmo default_snapshot_id junto com o array snapshots completo, portanto, a maioria das integrações precisa apenas dessa chamada. Os campos do objeto de instantâneo completo estão no guia Snapshots.

Sob demanda — instale em uma conta específica. Útil para integrar um cliente existente ou para fornecer a um cliente um segundo modelo posteriormente.

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

Omita o sub_account_id e ele será instalado na sua própria conta de agência. Assim como os endpoints /subaccounts, estes nomeiam a conta de destino no caminho ou no corpo, em vez de através do parâmetro sub_account_id ambiente.

Vale a pena saber antes de construir sobre isso:

  • Agentes instalados começam pausados. Conecte os canais do cliente primeiro e, em seguida, ative o agente. Isso vale tanto para o caminho automático quanto para o sob demanda.
  • O provisionamento nunca falha por causa de um snapshot. Se a instalação não puder ser concluída, a conta do cliente ainda será criada e poderá ser usada — ela apenas chegará vazia e você poderá aplicar o snapshot posteriormente.
  • Canais, calendários e conexões OAuth nunca são copiados. Cada conta conecta os seus próprios. Ferramentas que usam uma chave de API simples continuam funcionando imediatamente.
  • Aplicar duas vezes cria uma segunda cópia. Nada é sobrescrito.

Crie o próprio modelo via API

POST /v1/snapshots · agentes, funções personalizadas e mídia via API

A seção acima distribui um snapshot criado por alguém no painel. A parte de criação também está exposta, portanto, todo o ciclo — montar a configuração principal uma vez, capturá-la e entregá-la a cada cliente — pode ser executado via código.

As peças, na ordem em que um script de provisionamento as utiliza:

  1. Crie suas funções personalizadas. POST /v1/custom-functions cria uma; GET /v1/custom-functions lista o que você tem, e GET, PUT e DELETE em /v1/custom-functions/{customFunctionId} leem, atualizam e removem uma. POST /v1/custom-functions/test testa uma definição antes de você salvá-la.
  2. Crie e configure o agente. POST /v1/agents o cria, PUT /v1/agents/{agentId} o atualiza, e PATCH /v1/agents/{agentId}/active com { "active": false } o mantém pausado enquanto você trabalha (a mesma chamada com true o coloca em operação). GET /v1/agents os lista.
  3. Dê habilidades ao agente. POST /v1/agents/{agentId}/custom-functions com { "custom_function_id": "..." } anexa uma função ao agente; o DELETE /v1/agents/{agentId}/custom-functions/{customFunctionId} correspondente a remove.
  4. Preencha a biblioteca de mídia. POST /v1/agents/{agentId}/media-library faz o upload de um item (JSON com base64Data, mimeType, title, description); GET lista os itens do agente, e PATCH/DELETE em /{itemId} atualizam ou removem um.
  5. Capture-o como um snapshot.
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
  }'

A partir daí, segue-se a seção anterior: marque-o como padrão para que cada novo cliente já nasça com ele, ou aplique-o sob demanda. A manutenção é feita da mesma forma: PATCH /v1/snapshots/{snapshotId} com { "name": "..." } renomeia um, DELETE /v1/snapshots/{snapshotId} exclui um (e remove a marcação de padrão, caso estivesse marcado), e GET /v1/snapshots/apply-targets lista todas as contas nas quais você pode realizar a instalação.

Os endpoints de agente, função personalizada e mídia aceitam sub_account_id, portanto, as mesmas chamadas também podem manter um agente diretamente dentro da conta de um cliente. As chamadas de snapshot sempre atuam na sua conta de agência — o modelo permanece com você. Os esquemas completos de solicitação e resposta para todos eles estão na Referência da API.


Gerencie seus níveis de preços via API

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

Os planos que você vende em Modo SaaS → Níveis de Preços podem ser lidos e alterados via código, para que seu próprio painel administrativo ou script de provisionamento possa adicionar um plano, ajustar um preço ou fornecer um link de checkout sem que ninguém precise abrir o painel. Autentique-se com sua chave de API de agência como em qualquer outra chamada nesta página; esses endpoints são de nível de agência, portanto, não utilizam sub_account_id. Toda gravação executa a mesma validação e a mesma sincronização de produto e preço do Stripe que o salvamento no painel, portanto, um plano criado aqui é indistinguível de um que você configurou manualmente.

Liste seus níveis

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

Resposta

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

Cada nível retorna com seu tierIndex — sua posição na sua lista de Planos, que é como as outras três chamadas o endereçam — e um checkout_url pronto para compartilhar, o mesmo link que a aba Pagamentos fornece, já apontando para o domínio white label no qual o plano é vendido.

Adicione um nível

O corpo é um objeto de nível; ele é anexado ao final da sua lista.

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

A resposta traz o nível criado, incluindo o tierIndex no qual ele foi inserido e seu checkout_url.

Edite um nível

Envie apenas os campos que deseja alterar; todo o restante do plano permanece como estava.

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

Um campo que a API não reconhece é recusado em vez de ignorado, e o erro o nomeia — assim, um erro de digitação nunca pode gravar silenciosamente uma configuração que parece ativa, mas não faz nada. Alterar o preço, os créditos, a moeda ou a periodicidade de cobrança cria um novo preço no seu Stripe; clientes que já assinaram permanecem no que assinaram.

Exclua um nível

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

A mesma regra do painel: um plano que ainda possui assinantes ativos não pode ser excluído. A solicitação retorna recusada, informando quantos assinantes estão nele — cancele ou migre-os primeiro. Uma exclusão bem-sucedida responde com seus níveis restantes, já renumerados.

Os campos em um nível

Campo O que é
label / description O nome do plano e a linha opcional exibida na sua página de checkout.
credits Créditos que o cliente recebe por mês em um plano mensal ou anual, e por período de faturamento em um semanal.
price_cents Preço por intervalo de faturamento, na menor unidade monetária (2900 = $29.00). Em um plano anual, este é o preço do ano inteiro.
currency Código ISO em minúsculas — usd, eur, gbp e assim por diante.
billing_interval / billing_interval_count month (o padrão), year, ou week com uma contagem de 1–52 para “a cada N semanas”.
trial_days Duração do teste gratuito, de 0 a 90. 0 (ou omiti-lo) significa sem teste.
trial_credits Créditos com os quais o cliente inicia o teste. O padrão é credits do plano.
trial_card_required false permite que o cliente inicie o teste sem inserir um cartão. O padrão é true.
trial_hard_expiry true devolve créditos de teste não utilizados ao seu pool e bloqueia a conta do cliente quando um teste termina sem um upgrade. O padrão é false — veja Expiração rígida após o teste.
rollover_cap_months Meses de franquia que clientes neste plano podem transportar entre renovações — um número de 0 a 120, frações permitidas. 0 não transporta nada; null (o padrão) significa sem limite. Veja Limitando o que é transferido.
rollover_expiry_days Dias após os quais créditos não utilizados são descartados na próxima renovação — um número inteiro de 1 a 3650. null (o padrão) significa que eles nunca expiram.
features / feature_settings O que os clientes neste plano recebem — os mesmos IDs de recurso que Escolha quais tipos de canal um cliente pode conectar.
team_seats_limit Assentos de equipe que o plano concede: um número exato, 0 para nenhum, -1 para ilimitado.
white_label_config Em qual de seus domínios white label o plano é vendido.

Os campos de teste só fazem sentido em um plano que possui um teste: salve um nível com trial_days: 0 e eles serão descartados. Os IDs de produto e preço do Stripe do plano são gerenciados para você e não podem ser definidos manualmente.

Três coisas para acertar:

  • Os índices de nível são posições, não IDs permanentes. Excluir um plano desloca todos os planos subsequentes para baixo, portanto, busque a lista novamente após qualquer alteração — e copie novamente os links de checkout que você publicou, exatamente como faria após excluir um plano no painel.
  • O Modo SaaS deve ser configurado primeiro. Esses endpoints precisam de uma conta de agência com white labeling e uma chave Stripe já salva; sem isso, não há conta Stripe para o produto e preço do plano residirem.
  • Vinte planos é o limite, o mesmo que no painel. O campo max_tiers na resposta da lista informa o limite atual.

Os esquemas completos de solicitação e resposta estão na Referência da API, em Agência.


Defina seu preço por crédito via API

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

O preço que os clientes pagam por recargas avulsas (Modo SaaS → Preço por Crédito) também pode ser lido e alterado via código. Isso foi criado para casos em que o preço precisa ser ajustado automaticamente: uma agência que vende créditos em uma moeda, mas cobra em outra, pode permitir que uma tarefa agendada revise o preço conforme a taxa de câmbio muda, em vez de alguém editá-lo manualmente toda semana.

Ler o preço atual

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

Resposta

{
  "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 é o preço mais baixo que a plataforma permite nessa moeda, portanto, uma tarefa pode verificar um novo preço antes de enviá-lo. Todos os três valores são null até que um preço tenha sido definido.

Alterá-lo

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

Envie apenas o que deseja alterar. price_per_credit_cents é o preço na menor unidade monetária (130 = R$1,30); currency é um código ISO em letras minúsculas; note é uma linha opcional de até 200 caracteres exibida aos clientes diretamente abaixo do preço por crédito na página de Faturamento — útil para um preço de referência em outra moeda, como “USD 0,25 por crédito à nossa taxa de referência”. Envie "note": "" para removê-la. A resposta tem o mesmo formato da leitura acima, para que uma tarefa possa comparar e pular a gravação quando nada tiver mudado.

As mesmas regras do painel se aplicam: o preço não pode ficar abaixo do mínimo da plataforma para aquela moeda, e a conta precisa de white labeling. Ao contrário dos endpoints de níveis de preço, nenhuma chave do Stripe é necessária para ler ou alterar este valor.

Dê a uma tarefa uma chave que não possa fazer mais nada

Colocar sua chave de agência completa em um agendador concede mais acesso do que uma atualização de preço necessita. Em vez disso, crie uma chave com escopo limitada à área de Preço de Crédito da Agência: essa chave pode ler e alterar o preço por crédito e nada mais — ela não pode acessar subcontas, planos, créditos ou sua conexão com o 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"] } }'

A resposta contém a nova chave em api_key apenas uma vez — ela nunca é exibida novamente, portanto, armazene-a imediatamente. Defina "read_only": true para uma chave que precise apenas ler o preço e adicione "expires_at" (uma data ISO) se desejar que ela pare de funcionar automaticamente. Apenas a chave do proprietário da conta pode criar chaves com escopo; liste ou revogue-as com GET /v1/api-keys e DELETE /v1/api-keys/{id}.


Permita que uma subconta leia seus preços

GET /v1/subaccounts/agency-pricing

Todos os outros endpoints nesta página são chamados com a sua chave de agência, opcionalmente direcionando um cliente via sub_account_id. Este é o oposto: ele é chamado com a própria chave de API da subconta, sem sub_account_id, para que a página de recarga do próprio cliente (ou uma integração que você crie para ele) possa exibir o que você cobra dele sem nunca ver sua conta de agência.

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

Resposta

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

Isso reflete exatamente o que GET /v1/agency/pricing-tiers e GET /v1/agency/credit-price retornam para você como agência, menos qualquer coisa que o cliente não precise ver (ids do Stripe, max_tiers, etc.). Funciona apenas para uma conta que seja, de fato, uma subconta com uma agência vinculada — chamá-lo de sua própria conta de agência retorna um erro de permissão.


Pontos a considerar

  • Use a chave da sua agência. Autentique cada chamada com a chave de API da conta da sua agência — não a da subconta. O parâmetro sub_account_id é o que redireciona a ação.
  • Os créditos vêm da subconta. Compras e cobranças recorrentes são debitadas do saldo de créditos da subconta alvo, não do seu.
  • Um 404 significa “não é sua subconta”. Verifique novamente o id e se a conta é uma que você gerencia.
  • O parâmetro é opcional onde quer que seja aceito. Omita-o e o mesmo endpoint atuará na conta da sua agência, para que você possa reutilizar uma única integração para ambos.

Relacionado

  • Acesso à API — autenticação, URL base, erros, limites de taxa.
  • Subcontas — liste e gerencie as contas que você pode direcionar.
  • Recarga Automática de Subconta — conceda créditos a uma subconta via webhook + API.
  • API de Campanhas — crie, atualize e copie campanhas, incluindo a referência completa de campos.
  • API de Conexão de Canal — conecte os canais de um cliente e direcione-os para uma campanha.
  • Guia da API de Analytics (na seção de API) — o rollup de subcontas da agência e todos os outros endpoints de relatório.
  • Snapshots — o que um snapshot captura e como criar um no painel.