DM Champ Docs

API para agencias

Como agencia, puede utilizar la misma API REST que utilizan sus clientes, pero dirigiendo las solicitudes individuales a una de sus subcuentas gestionadas en lugar de a su propia cuenta. Esto le permite crear herramientas que incorporen a un cliente de principio a fin: creando sus campañas, entrenando a su IA en una base de conocimientos, importando sus contactos, conectando sus canales de mensajería y comprando números de teléfono, todo ello sin tener que iniciar sesión manualmente en cada subcuenta.

Esta página cubre únicamente el comportamiento específico de la agencia: cómo actuar en nombre de una subcuenta con el parámetro sub_account_id. Para conocer los aspectos básicos (generación de claves, autenticación, URL base, formato de error, límites de velocidad), comience con la guía de Acceso a la API. Todo lo que se indica allí también se aplica aquí: usted se autentica con la clave de API de su cuenta de agencia.

Nota: Esta página es técnica. Si no es desarrollador, compártala con la persona que está creando su integración.


Cómo funciona “actuar en nombre de”

De forma predeterminada, cada solicitud de API actúa sobre la cuenta propietaria de la clave de API: su cuenta de agencia. Para actuar en nombre de una cuenta de cliente gestionada, añada el parámetro opcional sub_account_id a la solicitud, configurado con el ID de cuenta de dicho cliente.

  • Omitir sub_account_id → la solicitud actúa sobre su propia cuenta de agencia.
  • Incluir sub_account_id → la solicitud actúa sobre esa subcuenta, pero solo después de que la plataforma confirme que la subcuenta es realmente suya.

Usted siempre se autentica con la clave de API de su cuenta de agencia. Nunca necesita la clave propia de la subcuenta y nunca maneja las credenciales de la subcuenta.

Dónde colocarlo

  • Endpoints GET / DELETE → páselo como un parámetro de consulta: ?sub_account_id=THE_SUB_ACCOUNT_ID (junto con su apiKey, si se autentica mediante consulta).
  • Endpoints POST / PUT / PATCH → inclúyalo en el cuerpo de la solicitud JSON como "sub_account_id": "THE_SUB_ACCOUNT_ID".
  • Asistentes de IA → nada que configurar. El servidor MCP lleva la misma configuración en sus herramientas de lectura, por lo que una conexión con su clave de agencia puede informar sobre cada cliente: simplemente nombre al cliente en su solicitud (“¿cuántos contactos tiene Bella’s Bistro?”). Las acciones de escritura también están disponibles: cada endpoint que acepta sub_account_id se expone como una herramienta, por lo que puede crear, cambiar y enviar en nombre de un cliente desde la misma conexión.

Cómo encontrar el ID de una subcuenta

El sub_account_id es el identificador único de la cuenta del cliente. Puede obtener la lista de sus subcuentas y sus identificadores desde los endpoints de la API de SubAccounts (consulte la guía de Sub-Accounts) o desde la página de Sub Accounts en la barra lateral.


La propiedad siempre se verifica

Cuando usted pasa un sub_account_id, la plataforma comprueba que la cuenta sea una subcuenta real y que pertenezca a su agencia. Solo entonces se procesa la solicitud.

Si el ID es desconocido, no es una subcuenta o pertenece a una agencia diferente, la solicitud fallará con una respuesta 404:

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

¿Por qué 404 y no 403? Una respuesta de “prohibido” le diría a un extraño que el id existe pero no le pertenece. Devolver el mismo 404 para “no existe” y “no es tuyo” significa que el endpoint no puede utilizarse para descubrir qué ids de cuenta pertenecen a otras agencias. Trata un 404 aquí como “esta no es una subcuenta que tú administras”.


Dónde se admite sub_account_id

sub_account_id se acepta en prácticamente todos los endpoints de recursos: cualquier llamada que cree, lea, actualice o elimine los datos propios de una cuenta. En la práctica, puede aprovisionar y ejecutar toda la configuración de una subcuenta con su clave de agencia:

  • Configuración de IA — campañas, agentes, preguntas frecuentes, fuentes de la base de conocimientos (rastreo de sitios web y carga de documentos), grupos de bases de conocimientos, difusiones, funciones personalizadas, servidores MCP
  • Contactos y CRM — contactos (incluida la importación), listas, etiquetas, tareas, tratos, citas, eventos
  • Canales y números — conectar WhatsApp / WhatsApp Web / Telegram / Instagram y Messenger / LINE, buscar / comprar / gestionar números de teléfono, plantillas de WhatsApp, enrutamiento de canales
  • Mensajería y contenido — enviar mensajes, sesiones de chat, exportaciones de chat, resúmenes diarios
  • Configuración e integraciones — webhooks, configuración del widget de chat, configuración de marca blanca, SMS BYOK y otros ajustes de cuenta, análisis

En todos ellos, el parámetro es opcional: si lo omite, la llamada actuará sobre su propia cuenta de agencia, por lo que una única integración sirve para ambos casos. Los créditos y el uso siempre provienen de la cuenta a la que se dirige: los cargos por las campañas, mensajes, etiquetas y números de una subcuenta se aplican al saldo de la subcuenta.

Dónde NO se aplica

Algunos endpoints son de nivel de agencia o se dirigen a sí mismos e ignoran sub_account_id:

  • Gestión de las subcuentas en sí — los endpoints de SubAccounts (crear / listar / actualizar una subcuenta) y el endpoint de límite de gasto BYOK ya nombran la subcuenta en su propia ruta URL. Los endpoints de precios y políticas y los endpoints de monitoreo de chat siguen el mismo patrón.
  • Copiar un Agente entre cuentasPOST /v1/subaccounts/agents/copy nombra ambas cuentas, tomando el destino como targetUserId. Consulte el ejemplo práctico a continuación. (El POST /v1/subaccounts/campaigns/copy más antiguo funciona de la misma manera, pero está obsoleto junto con el resto de la API de Campañas.)
  • Ajuste de créditos y los dos resúmenes a nivel de agenciaPOST /v1/subaccounts/credits identifica la subcuenta mediante email en su lugar; GET /v1/subaccounts/credit-usage y GET /v1/subaccounts/campaign-status informan sobre todas las subcuentas a la vez, por lo que no hay una sola cuenta a la cual dirigirse.
  • La propia cuenta de su agencia — La gestión de claves API, los informes de uso de la agencia, la gestión de equipos y sus niveles de precios siempre actúan sobre la cuenta de su agencia.
  • Webhooks de mensajes entrantes — los endpoints en los que los sistemas externos publican hacia están vinculados a la cuenta cuyas credenciales los configuraron, por lo que no hay nada que redirigir.

La lista siempre actualizada y legible por máquina de los parámetros que acepta cada endpoint se encuentra en la referencia de la API de su panel de control (Settings → Integrations → API Key) y en la especificación OpenAPI en GET /v1/docs/openapi.yaml. Realizamos cambios en la API con frecuencia; considérelos como la fuente de información definitiva.

Página de configuración de la clave API con la clave enmascarada y el control de regeneración

Configuración → Integraciones → Clave API — la clave de tu agencia se encuentra aquí, junto con el enlace a la referencia completa de la API.


Ejemplo práctico: conectar Instagram y Messenger para una subcuenta

Conectar Instagram y Messenger es un flujo basado en navegador. Lo inicias con la API, entregas la URL de consentimiento devuelta al cliente (o la abres por él), esperas a que autorice en su navegador y luego eliges qué página conectar, todo ello mientras apuntas a su subcuenta con sub_account_id.

Paso 1 — Iniciar la conexión

Llama al endpoint de conexión con el sub_account_id del cliente en el body. Aquí no se envían credenciales; la plataforma devuelve una URL de consentimiento que el cliente debe abrir en un navegador, además de un token de correlación de un solo uso.

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

Respuesta:

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

Envía al cliente a oauth_url en un navegador para autorizar. El state_token correlaciona este intento y es un secreto de corta duración; no lo registres. El intento caduca en expires_at; si vence, comienza de nuevo.

Paso 2 — Realizar sondeos hasta que las páginas se carguen

Después de que el cliente autorice, consulte el endpoint de estado (con el mismo sub_account_id, esta vez como parámetro de consulta) hasta que aparezcan las páginas conectables.

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

Respuesta:

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

El campo status avanza a través de pendingtoken_receivedpages_loadedconnected. Espere a pages_loaded antes de seleccionar una página. También pueden aparecer dos estados de error terminal en lugar de avanzar: failed y expired (el cliente rechazó el consentimiento o el periodo de ~30 minutos del token de estado ha caducado); se incluye un campo reason cuando ocurre cualquiera de ellos. Deje de realizar sondeos y reinicie en el Paso 1 si ve uno; no espere en pending indefinidamente. Los tokens de acceso a la página nunca se devuelven.

Paso 3 — Seleccionar la página para conectar

Elija uno de los identificadores de página del Paso 2 y selecciónelo. Al seleccionar una página, se conectan tanto Instagram como Messenger para dicha página. Incluya sub_account_id en el cuerpo nuevamente.

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

Respuesta:

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

Eso es todo: Instagram y Messenger ya están conectados en la subcuenta del cliente. Usted solo proporcionó el page_id; la credencial subyacente se resuelve en el servidor y nunca pasa a través de su integración.


Ejemplo práctico: comprar un número para una subcuenta

La compra de un número funciona de la misma manera: busque con sub_account_id en la consulta y luego realice la compra incluyéndolo en el cuerpo. Los créditos se deducen del saldo de la subcuenta y el número se aprovisiona en la subcuenta.

Búsqueda (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()

Respuesta:

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

El número se aprovisiona en el estado PURCHASED y el registro del remitente de WhatsApp continúa en segundo plano. Realice sondeos en GET /v1/phone-numbers/{phoneNumber}/status?sub_account_id=abc123def456 hasta que el estado llegue a ONLINE antes de enviar.


Ejemplo práctico: enviar un Agente de plantilla a cada cliente nuevo

El patrón habitual de las agencias es mantener un Agente maestro en su cuenta de agencia, configurado de la forma en que desea que cada cliente comience, y estampar una copia del mismo en cada subcuenta nueva en el momento del aprovisionamiento. Son tres llamadas y no es necesario repetir nada después: la copia conserva su configuración hasta que usted la cambie.

Paso 1 — Copiar el Agente

POST /v1/subaccounts/agents/copy

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

La respuesta contiene el id del nuevo Agente en data.agent_id. Las preguntas frecuentes, la base de conocimientos y la biblioteca de medios se incluyen; las plantillas de WhatsApp, las publicaciones sociales conectadas y los contactos de la cuenta de origen deliberadamente no se incluyen. Lista completa de campos en la API de Agentes de IA.

Ten en cuenta que este endpoint utiliza targetUserId en lugar de sub_account_id; nombra ambas cuentas por sí mismo. Las dos llamadas siguientes utilizan el parámetro normal sub_account_id.

Paso 2 — Activarlo

La copia siempre llega en pausa, por lo que no puede enviar mensajes a nadie hasta que usted lo indique. Este es también el momento de fijar el nivel de IA en el que desea que esté el cliente; permanece allí, por lo que no es necesario volver a aplicarlo según un cronograma.

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 evitar que el cliente cambie el nivel después, bloquee los niveles permitidos en la subcuenta en lugar de volver a enviar el valor.

Paso 3 — Dirigir los canales del cliente hacia ella

La copia tampoco llega con enrutamiento, por lo que nada llega a ella hasta que usted la convierte en el respondedor en los canales que el cliente ha conectado. Una llamada 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 de aquí, un mensaje inicial de un contacto desconocido en ese canal es captado automáticamente por el Agente copiado. Consulte Apuntar un canal a un Agente para conocer los otros canales y el enrutamiento por número.

Establece la zona horaria del cliente cuando crees la subcuenta. Pasa time_zone_id en POST /v1/subaccounts. Las horas activas de la campaña se evalúan en la propia zona horaria de la subcuenta, por lo que un cliente creado sin una tendrá su programación leída según UTC, lo que cambia silenciosamente cuándo se permite responder al asistente.


Omitir el asistente de configuración para un cliente que usted mismo configura

POST /v1/subaccounts

De forma predeterminada, la primera vez que el propietario de una nueva subcuenta inicia sesión, se le guía a través del Asistente de configuración. Para clientes con servicio completo (done-for-you), donde usted crea la campaña y conecta los canales antes de que el cliente inicie sesión, pase guided_onboarding: false al crear la cuenta. En su lugar, llegarán al panel de control y la entrada Asistente de configuración se ocultará de su barra lateral.

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

Omite el campo (o envía true) y el asistente se comportará exactamente como siempre lo ha hecho, por lo que las integraciones existentes no necesitan cambios. Para devolverle el asistente a un cliente más tarde, vuelve a mostrar el elemento guided_onboarding con PUT /v1/subaccounts/{subAccountUid}/menu-visibility (a continuación): la visibilidad del menú controla si el asistente es accesible, guided_onboarding controla solo la redirección del primer inicio de sesión.


Desactivar Tareas, Resúmenes diarios o la Biblioteca de medios para un cliente

POST /v1/subaccounts

Estas tres funciones están activadas para cada cliente nuevo a menos que indique lo contrario, y se comportan de forma diferente a cualquier otra función de esta guía: son de exclusión voluntaria (opt-out), no de inclusión. Dejarlas fuera de features no es suficiente por sí solo, porque la lista features de una integración antigua simplemente no las mencionaba; no podemos distinguir entre “la agencia desactivó esto” y “esta lista se escribió antes de que existiera la opción”.

Por lo tanto, indíquelo explícitamente con feature_settings:

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

Cada clave es opcional; todo lo que omita permanecerá activado. Con tasks: false, la IA deja de crear tareas para ese cliente y no se envían correos electrónicos de “Nueva tarea creada”; con daily_summaries: false, el resumen nocturno nunca se genera ni se envía por correo electrónico.

feature_settings es lo único que desactiva estas tres funciones en el momento de la creación. Dejarlas fuera de features no hace nada por sí solo, sin importar cómo se vea el resto de su lista; esto es deliberado, para que una integración antigua no pierda las tres funciones de forma silenciosa.

Para cambiar cualquiera de estos ajustes posteriormente, envíe la lista features completa a PUT /v1/subaccounts/{subAccountUid}/features; allí, la presencia en la lista activa una función y su ausencia la desactiva.


Inicie sesión automáticamente a sus clientes en su subcuenta (SSO)

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

Una llamada con la clave API de su agencia devuelve una URL lista para abrir que inicia la sesión del cliente directamente en su propia subcuenta: sin pantalla de inicio de sesión, sin pasos de contraseña, nada que construir adicionalmente. Ábrala en una nueva pestaña, mediante una redirección o en un iframe dentro de su propio producto.

Campo Obligatorio Descripción
redirect No Página dentro de la aplicación en la que desea que termine el cliente, p. ej., "/chats" o "/agents". Se devuelve como deep_link_url en la respuesta.
app_base_url No Host del panel para el enlace. El valor predeterminado es su dominio de aplicación de marca blanca (o el dominio de la plataforma si no tiene ninguno). Debe 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" }'

Respuesta

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

Cómo utilizarlo correctamente:

  • Un solo salto. Abrir url inicia la sesión del cliente y lo lleva directamente a la página redirect del panel de control; sin pantalla de inicio de sesión ni páginas intermedias. deep_link_url designa el mismo destino, para los integradores que prefieren navegar por un marco explícitamente después de iniciar sesión; una vez que existe la sesión, cualquier ruta del panel de control funciona en ese contexto del navegador.
  • Crear bajo demanda, abrir inmediatamente. El enlace contiene una credencial de inicio de sesión y caduca después de aproximadamente una hora. Solicítelo en el lado del servidor en el momento en que el cliente haga clic, y nunca lo almacene ni lo envíe por correo electrónico.
  • El token de inicio de sesión viaja en el fragmento de la URL (#…), que los navegadores nunca envían a los servidores, y se elimina de la barra de direcciones en el momento en que se consume.
  • Solo sus propias subcuentas. El endpoint rechaza cualquier cuenta que su agencia no posea.
  • Un enlace caducado muestra un error claro con una ruta de reintento: cree uno nuevo.

Ocultar elementos de navegación en una subcuenta

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

Controla qué elementos de la barra lateral y de configuración ve una subcuenta; es útil cuando integra el panel de control y solo desea las superficies que su producto aún no cubre. Todo lo que no esté en la lista permanece visible; envíe null como el valor completo de menuVisibility para restablecer todo a visible. Ocultar un elemento oculta la entrada del menú: combínelo con las funciones que otorga a la subcuenta para un control estricto.

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

Respuesta

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

side_nav acepta estas 13 claves, que coinciden con los nombres de los elementos de la barra lateral: Dashboard, DailySummaries, Chats, Contacts, Deals, Tasks, Automations, Campaigns, Appointments, Settings, Help, CreditsCounter (el saldo de crédito que se muestra en la barra lateral) y guided_onboarding (el asistente de configuración). Se aceptan otras tres claves — AiInsights, Sub Accounts y Agency Reselling — pero no realizan ninguna acción: solo se aplicaban al panel de control clásico retirado, por lo que configurarlas no tiene ningún efecto en sus subcuentas. Las claves que faltan significan que están visibles; cuando usted mismo inicia sesión en la subcuenta, los elementos ocultos se muestran temporalmente para que siempre pueda volver a cambiarlos.

Ocultar una página del menú nunca otorga acceso a ella. Automations necesita que la función automations esté concedida en la subcuenta; si establece la clave en true sin ella, la página seguirá sin aparecer. Tasks y DailySummaries funcionan a la inversa: están activadas para todos los clientes a menos que las desactive (consulte Desactivar Tareas, Resúmenes diarios o la Biblioteca de medios para un cliente).


Elija qué tipos de canal puede conectar un cliente

PUT /v1/subaccounts/{subAccountUid}/features

Los interruptores de Tipos de canal que ve en un nivel de plan son ID de funciones comunes, por lo que puede configurarlos por cliente desde la API en lugar del panel de control. Este es uno de los puntos finales que nombra a la subcuenta en su propia URL, por lo que no requiere sub_account_id.

ID de función Canal
channel_chat_widget Widget de chat del sitio web
channel_whatsapp_api API de 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 Buzón de correo electrónico
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"
    ]
  }'

Tres cosas que debe tener en cuenta:

  • La llamada reemplaza toda la lista de funciones. Envíe todas las funciones que el cliente debe conservar, no solo las que está cambiando. Los mismos ID funcionan como features en POST /v1/subaccounts cuando crea la cuenta.
  • Los tipos de canal y el recuento de canales son puertas separadas, y ambas se aplican. channels_1 / channels_3 / channels_unlimited controlan cuántas conexiones; los ID de channel_* controlan qué tipos. El ejemplo anterior significa “hasta 3 conexiones, y solo Widget de chat, WhatsApp Web o Instagram”.
  • No enviar ningún ID de channel_* significa que no hay restricción de canal. Ese es el comportamiento original, razón por la cual los clientes existentes no se vieron afectados cuando se lanzó esto. Envíe uno o más y todo lo demás aparecerá como bloqueado en la página de Canales del cliente con una nota de actualización en lugar de un botón Conectar. Los canales que el cliente ya conectó seguirán funcionando.

La configuración de la lista de canales en un nivel de plan, para que cada cliente que compre ese nivel la herede, se realiza en el panel de control bajo la configuración de su plan de agencia. Este punto final la establece en una subcuenta específica.


Establecer un límite exacto de miembros del equipo para un cliente

PUT /v1/subaccounts/{subAccountUid}/limits

Las funciones de team_seats_* solo ofrecen niveles preestablecidos (3 / 5 / 10 / ilimitado). Para asignar a un cliente un número exacto de puestos de equipo (2, 7, 15, o cualquier otro), configure usage_limits.team_seats_limit en su lugar. Esta opción prevalece sobre los valores preestablecidos y la plataforma la aplica en cada invitación, adición directa y aceptación de invitación: una vez alcanzado el límite, se rechazan las invitaciones adicionales desde el lado del servidor.

  • Un número entero positivo es el límite exacto.
  • 0 significa que los miembros del equipo no están incluidos: el cliente no puede invitar a nadie.
  • -1 significa ilimitado.
  • null borra el límite personalizado y vuelve al valor preestablecido de team_seats_* que esté en la lista de funciones.

Reducir el límite nunca elimina a los miembros del equipo existentes; solo impide que se añadan otros nuevos.

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

También puede establecerlo en el momento de la creación: POST /v1/subaccounts acepta usage_limits.team_seats_limit con la misma semántica. Para leer el valor actual, obtenga la subcuenta con GET /v1/subaccounts?email=... y consulte usage_limits.team_seats_limit (ausente/null = los valores predeterminados deciden). El mismo endpoint también actualiza credits, monthly_credits, roll_over_to_next_month, rollover_cap_months, rollover_expiry_days y byok_monthly_limit_usd: envíe solo las claves que desea cambiar.

Cómo interactúa esto con los límites de asientos de los planes SaaS. Sus planes SaaS pueden tener su propia asignación de asientos (configurada en el editor de planes; consulte Asientos de equipo en un plan), la cual se aplica automáticamente cuando un cliente se suscribe. Un límite que usted establezca a través de este endpoint cuenta como una concesión manual: comprar un plan lo reemplaza con la propia asignación de asientos del plan (esa compra es una elección explícita del plan), pero las renovaciones mensuales automáticas nunca sobrescriben un límite manual; por lo tanto, una excepción única que usted otorgue a un cliente persiste durante su ciclo de facturación. Borrar el límite manual con null devuelve el control del campo al plan en su próxima renovación.

Limite lo que un cliente transfiere entre renovaciones. Dos claves usage_limits adicionales se encuentran junto a roll_over_to_next_month. Ambas también son aceptadas por POST /v1/subaccounts en el momento de la creación, y null borra cualquiera de las dos.

Clave Qué hace
rollover_cap_months Meses de asignación que el cliente puede conservar. Un número del 0 al 120, se permiten fracciones (0.5 = medio mes). En cada renovación, el saldo no utilizado se recorta hasta un máximo de esta cantidad multiplicada por la asignación que otorga esa renovación, antes de que se añadan los nuevos créditos; 0 no transfiere nada.
rollover_expiry_days Un número entero de días, de 1 a 3650. Los créditos que quedan sin usar durante tanto tiempo se eliminan en la primera renovación después de alcanzar esa antigüedad. El gasto siempre se descuenta primero de los créditos más antiguos, por lo que un cliente que gasta su asignación cada mes nunca pierde ninguno.

Si no se establecen, ambos recurren al plan del cliente; un valor enviado aquí prevalece sobre el del plan. Solo los créditos recurrentes (la asignación mensual y los créditos del plan) están sujetos a ellos: las recargas, las recargas automáticas y las adiciones únicas nunca se limitan ni caducan. Cada recorte se registra en el historial de créditos del cliente como un Ajuste de crédito por límite de transferencia o un Ajuste de crédito por créditos caducados y nunca cuenta como uso. Los equivalentes a nivel de plan son rollover_cap_months y rollover_expiry_days en un nivel de precios: consulte Los campos en un nivel y Limitar lo que se transfiere.


Establecer precios y políticas 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

Ocho interruptores más por cliente, junto con /limits, /features y /menu-visibility anteriores. Cada uno toma el uid de la subcuenta en la URL (sin sub_account_id cuerpo/parámetro de consulta: el objetivo ya está nombrado en la ruta) y tiene el mismo alcance: su clave de agencia, y la subcuenta debe pertenecer a su agencia.

Qué modelos de IA puede usar un cliente

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

{ "enabled": boolean } inscribe al cliente en (o lo excluye de) el nivel Max AI: nuestra infraestructura al precio de lista de la plataforma. Activar esto para un cliente BYOK cambia su costo de IA de “gratis con mi propia clave” a “cargado contra mi fondo de crédito”, por lo que es una decisión deliberada por cliente en lugar de un valor predeterminado para toda la agencia.

Para restringir QUÉ niveles pueden elegir las campañas y agentes de un cliente (en lugar de solo limitar 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 es una matriz extraída de standard, economy, max, mini — REEMPLAZA la lista de permitidos del cliente. Envíe null (o []) para borrar la restricción y permitirles elegir cualquier nivel. Esto es importante porque una subcuenta que elige su propio nivel de IA gasta de su fondo de crédito, por lo que es la palanca para determinar qué modelos puede ejecutar un cliente revendedor en su factura.

Una respuesta de espera mientras el cliente no tiene 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." }'

Cuando el saldo del cliente (o su grupo) está vacío, la IA no puede responder y el contacto no recibe nada. Con enabled: true, cada contacto que escribe durante la interrupción recibe message una vez (máximo 500 caracteres, enviado tal cual en cada canal), y la IA responde a esas conversaciones de verdad una vez que los créditos vuelven. enabled: false guarda el texto para más tarde; enabled: false sin message elimina la configuración. Es el mismo interruptor que Respuesta de espera cuando no hay créditos en el modal de edición de la subcuenta: consulte Una respuesta de espera mientras un cliente no tiene créditos.

Lo que paga un cliente por acción de IA y el margen de beneficio de la tarifa de WhatsApp

Dos formas de establecer su tarifa orientada al cliente, desde la más simple hasta la más 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 es el precio en créditos que consume el saldo PROPIO de la subcuenta por cada acción de IA del modelo Max: su margen de beneficio orientado al cliente sobre lo que realmente paga su fondo. null borra la anulación y vuelve al precio de lista de la plataforma. La tarifa debe ser al menos lo que cuesta una acción Max para su propio fondo (por lo que nunca puede cobrar a un cliente por debajo de su costo) y no más de 10 créditos; una solicitud fuera de ese rango se rechaza con el límite inferior calculado en el mensaje de error.

Para precios por tipo de acción en lugar de una tarifa Max plana, 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 es una FUSIÓN en el mapa existente del cliente: una clave que no menciona se deja como estaba, y null restablece esa clave a su valor predeterminado. Las claves reconocidas:

Clave Precios
AI_MESSAGE Una respuesta de IA
AI_TOOL_USE Una llamada a herramienta de IA
EVALUATION_CALL Una pasada de evaluación de chat
INTERRUPTION_HANDLING Manejo de una interrupción a mitad de respuesta
CONTACT_TAG Una etiqueta de contacto asignada por IA
CHAT_SUMMARY Un resumen de chat
wa_carrier_multiplier Un multiplicador de margen aplicado a cada tarifa de WhatsApp que no sea de IA que paga el cliente: alquiler mensual de números, tarifas de entrega en carriles gestionados y costos de transferencia de Meta/Twilio.

Las tarifas por acción deben ser un número mayor que 0 y hasta 10; wa_carrier_multiplier debe ser al menos 1 (sin descuentos por debajo del costo) y hasta 10. Enviar una clave no reconocida, o un valor fuera de rango, rechaza TODA la solicitud y nombra cada clave infractora, por lo que un error tipográfico nunca puede guardar silenciosamente un precio que en realidad no se aplica.

Si eres miembro de Champions Circle, insider-rate transfiere tu tarifa de 20% de descuento de Max/Lead Finder a un solo cliente en lugar de aplicarla a toda la agencia:

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

Activarla requiere que tu propia cuenta de agencia tenga realmente una membresía Circle; desactivarla nunca lo requiere, por lo que un miembro cuya membresía haya caducado siempre puede revertir los cambios de un cliente.

Bloquear secciones del manual de estrategias de un cliente

curl -X PUT "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/locked-bot-fields" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "locked_bot_fields": ["instructions", "rules"] }'

locked_bot_fields es una matriz extraída de instructions, goal, rules, personality, conclude_unless — REEMPLAZA la lista bloqueada del cliente. Una sección bloqueada es rechazada por el servidor si la propia SUB-CUENTA intenta cambiarla (directamente o mediante clave API), mientras que tú (a través de sub_account_id) y la vista de administrador del panel del cliente aún pueden editar cualquier cosa. Envía null (o []) para desbloquear todo. Útil para clientes con servicios gestionados donde tú eres dueño del manual de estrategias y se te juzga por el resultado.

Establecer las preferencias de notificación de un cliente en su nombre

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 reemplaza todo el conjunto de preferencias de notificación del cliente (no es una combinación por clave; envía todas las categorías que desees mantener, coincidiendo con cómo se guarda la página de Configuración de la propia subcuenta). Cada categoría bajo settings acepta enabled (booleano) y hasta tres channels de email, in_app, webhook. Envía null para restablecer a los valores predeterminados de la plataforma.

Los siete endpoints responden { "success": true, "data": { "subAccountUid": "...", ...the field(s) you set... } } y se registran en la auditoría con el valor antes/después. Errores comunes: 403 si tu cuenta no es de Agencia/Desarrollador o la subcuenta no es tuya para administrar, 400 si no es una subcuenta de agencia o un valor está fuera de rango.


Pausar a un cliente que ha suspendido su suscripción

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

Cuando un cliente suspende su suscripción con usted, pause su cuenta en lugar de eliminarla: todo lo que envían se detiene inmediatamente (mensajes salientes, difusiones, respuestas de IA en todos los canales) y, cuando inician sesión, ven un bloqueo de pantalla completa de Cuenta pausada (con su mensaje opcional) en lugar de la aplicación. No se elimina ni se desconecta nada: los agentes, las campañas, los canales conectados, los contactos y el historial de chat permanecen exactamente como están, por lo que reanudar la cuenta devuelve al cliente exactamente al punto donde lo dejó, sin necesidad de volver a realizar la configuración.

Campo Obligatorio Descripción
message No Se muestra al cliente en su pantalla de bloqueo. Déjelo vacío para usar el texto predeterminado.
reason No Nota interna de la agencia almacenada con la pausa y en el registro de auditoría; nunca se muestra al cliente.

cURL

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

Respuesta

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

Cuando el cliente regresa, POST /v1/subaccounts/SUB_ACCOUNT_UID/unpause (sin cuerpo) elimina el bloqueo, lo que permite que el envío de mensajes y las respuestas de la IA se reanuden de inmediato.

Información útil:

  • Es el mismo estado que el interruptor de bloqueo estricto (Hard blocked) del panel de control (Bloqueo / Pausa de una subcuenta): un cliente pausado a través de la API aparece como bloqueado en el panel de control y viceversa, y reanudar la cuenta elimina un bloqueo realizado desde cualquier lado. El estado actual se puede leer desde el campo agency_block en GET /v1/subaccounts (level de "none", "soft_blocked" o "hard_blocked").
  • Ambas llamadas son idempotentes. Pausar a un cliente que ya está pausado solo actualiza el mensaje, el motivo y la marca de tiempo; reanudar a un cliente activo no cambia nada.
  • No se envía un correo electrónico automático al cliente: muchas agencias utilizan marca blanca, por lo que informar al cliente queda a su discreción.
  • Su propia facturación de DM Champ no se ve afectada. Pausar a un cliente solo afecta su relación con él.
  • Los asistentes de IA también pueden hacer esto: el servidor MCP expone estos puntos finales como las herramientas pause_subaccount y unpause_subaccount.

Otorgar o deducir créditos directamente

POST /v1/subaccounts/credits

Añade o elimina una cantidad exacta de créditos del saldo de una subcuenta: el equivalente en la API al ajuste manual de crédito del panel de control. Este es un cambio de saldo único, distinto de las configuraciones recurrentes monthly_credits, roll_over_to_next_month, rollover_cap_months y rollover_expiry_days en PUT /v1/subaccounts/{subAccountUid}/limits.

Este es el único endpoint en esta página que identifica la subcuenta por correo electrónico en lugar de sub_account_id.

Campo Requerido Descripción
email El correo electrónico de la subcuenta, tal como existe bajo tu agencia.
amount Número de créditos distinto de cero. Positivo agrega, negativo deduce.
description No Se muestra junto al ajuste en el historial de créditos del cliente. Por defecto, aparece una línea genérica “Ajustado por la agencia vía 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" }'

Respuesta

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

Un amount negativo que llevaría el saldo por debajo de cero se rechaza con 400, indicándole el saldo disponible y lo que intentó deducir. Si el cliente tiene su propia facturación de Stripe (modo de reventa), una cantidad añadida también cuenta como créditos que compró, por lo que sobrevive a su próximo reinicio mensual de la misma manera que lo haría una recarga real; en un cliente asignado estándar, se trata como parte de su asignación recurrente. De cualquier manera, son una adición única, por lo que un límite de transferencia o una caducidad establecida en la cuenta (o su plan) nunca los recorta: solo la asignación recurrente y los créditos del plan están sujetos a ellos.


Leer las conversaciones de una subcuenta

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

Le permite crear una vista de supervisión o soporte de las conversaciones de un cliente sin tener que iniciar sesión en su cuenta. Primero, enumere sus contactos con una vista previa del último mensaje y, a continuación, lea el historial completo de mensajes de un contacto.

Listar contactos

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats?apiKey=YOUR_AGENCY_API_KEY&pageSize=25"
Parámetro de consulta Obligatorio Descripción
pageSize No Contactos por página. Predeterminado 25, máximo 50.
lastActivityAt No Cursor de paginación: pase el lastActivityAt de la página anterior para continuar.
searchQuery No Filtrar por nombre de contacto o número de teléfono.

Respuesta

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

Los contactos se ordenan por actividad más reciente primero. Siga paginando con lastActivityAt mientras hasMore sea true.

Leer los mensajes de un contacto

curl "https://api.dmchamp.com/v1/subaccounts/SUB_ACCOUNT_UID/chats/contact456/messages?apiKey=YOUR_AGENCY_API_KEY&pageSize=30"
Parámetro de consulta Obligatorio Descripción
pageSize No Mensajes por página. Predeterminado 30, máximo 100.
beforeTimestamp No Cursor de paginación: obtenga mensajes anteriores a esta marca de tiempo ISO.

Respuesta

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

Los mensajes se devuelven del más reciente al más antiguo; navegue hacia atrás por el historial con beforeTimestamp.


Leer el uso de créditos y el estado de las campañas en toda su cartera

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

Dos resúmenes estilo panel sobre todas las subcuentas que gestiona, para crear sus propios informes de agencia en lugar de hacer clic en cada cliente uno por uno.

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 Obligatorio Descripción
from / to Rango de fechas ISO.
subAccountId No Omítalo para obtener un resumen de toda la agencia, una fila por subcuenta. Inclúyalo para cambiar al modo de detalle: el resumen de esa subcuenta más sus registros de uso sin procesar y paginados.
limitCount No Solo modo de detalle. Predeterminado 500, máximo 2000.
startAfterTimestamp No Solo modo de detalle: cursor de paginación.
{
  "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
  }
}

Pase subAccountId y la misma respuesta también incluirá records: cargos individuales con amount, reason, campaignName, contactName y timestamp. Un cliente que gasta con su propia clave BYOK en lugar de con sus créditos tendrá las cifras de coste/token ocultas (costsRedacted: true); eso es telemetría de costes de la plataforma, no algo que deba mostrarse a un revendedor.

Estado de la campaña

curl "https://api.dmchamp.com/v1/subaccounts/campaign-status?apiKey=YOUR_AGENCY_API_KEY&pageSize=20"
Parámetro de consulta Requerido Descripción
pageSize No Subcuentas por página. Predeterminado 10, máximo 50.
lastDocumentId No Cursor de paginación.
searchQuery No Filtrar por nombre o correo electrónico de la subcuenta.
{
  "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 marca las subcuentas que merecen atención; por ejemplo, una campaña pausada o una a la que no se le ha asignado ningún canal. Utilice esto para crear un panel de control de estado para toda la cartera en lugar de abrir cada cliente para detectar una campaña estancada.

Para ver la mensajería de series temporales y la actividad de créditos de todos los clientes (una serie lista para gráficos en lugar de una instantánea puntual), consulte GET /analytics/agency-rollup en la guía de la API de Analytics.


Entregar una cuenta de cliente que ya esté configurada

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

Una instantánea es una plantilla reutilizable: uno o más agentes de IA junto con su base de conocimientos, herramientas y medios, capturados desde su propia cuenta. Dos endpoints la integran en su flujo de aprovisionamiento.

Automático: cada cliente nuevo la recibe al crearse. Marque una instantánea como predeterminada una vez y cada cuenta que cree a partir de entonces llegará con ella instalada. Esto cubre las cuentas creadas a través de POST /v1/subaccounts, las cuentas que cree en el panel de control y las cuentas creadas automáticamente cuando un cliente paga a través de su enlace de pago.

Primero, busque el id de la instantánea:

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

Luego, establézcala como predeterminada:

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

Esa es toda la integración. Envíe {"snapshot_id": null} para desactivarla de nuevo. Puede hacer lo mismo desde el panel de control haciendo clic en la estrella en la página de Instantáneas.

Para leer lo que está marcado actualmente (por ejemplo, antes de que un script de aprovisionamiento decida si establecer uno), GET /v1/snapshots/default devuelve { "success": true, "data": { "default_snapshot_id": "SNAPSHOT_ID" } }null cuando no hay nada marcado. GET /v1/snapshots (utilizado para encontrar el id anterior) devuelve el mismo default_snapshot_id junto con la matriz completa snapshots, por lo que la mayoría de las integraciones solo necesitan esa llamada. Los campos completos del objeto de instantánea se encuentran en la guía de Instantáneas.

Bajo demanda: instalar en una cuenta. Útil para la incorporación de un cliente existente o para proporcionar a un cliente una segunda plantilla más adelante.

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 sub_account_id y se instalará en su propia cuenta de agencia. Al igual que los endpoints /subaccounts, estos nombran la cuenta de destino en la ruta o el cuerpo en lugar de a través del parámetro sub_account_id ambiental.

Vale la pena saberlo antes de trabajar con esto:

  • Los agentes instalados comienzan en pausa. Conecte primero los canales del cliente y luego active el agente. Esto es válido tanto para la ruta automática como para la ruta bajo demanda.
  • El aprovisionamiento nunca falla debido a una instantánea. Si la instalación no puede completarse, la cuenta del cliente se crea y es utilizable de todos modos; simplemente llega vacía y puede aplicar la instantánea después.
  • Los canales, calendarios y conexiones OAuth nunca se copian. Cada cuenta conecta los suyos propios. Las herramientas que utilizan una clave API simple siguen funcionando de inmediato.
  • Aplicarla dos veces crea una segunda copia. No se sobrescribe nada.

Crea la plantilla directamente a través de la API

POST /v1/snapshots · agentes, funciones personalizadas y medios a través de la API

La sección anterior distribuye una instantánea creada por alguien en el panel de control. La parte de creación también está expuesta, por lo que todo el ciclo —ensamblar la configuración maestra una vez, capturarla y entregarla a cada cliente— puede ejecutarse desde el código.

Las piezas, en el orden en que las utiliza un script de aprovisionamiento:

  1. Crea tus funciones personalizadas. POST /v1/custom-functions crea una; GET /v1/custom-functions enumera las que tienes, y GET, PUT y DELETE en /v1/custom-functions/{customFunctionId} leen, actualizan y eliminan una. POST /v1/custom-functions/test realiza una prueba de ejecución de una definición antes de guardarla.
  2. Crea y configura el agente. POST /v1/agents lo crea, PUT /v1/agents/{agentId} lo actualiza, y PATCH /v1/agents/{agentId}/active con { "active": false } lo mantiene en pausa mientras trabajas (la misma llamada con true lo pone en funcionamiento). GET /v1/agents los enumera.
  3. Dale habilidades al agente. POST /v1/agents/{agentId}/custom-functions con { "custom_function_id": "..." } adjunta una función al agente; el DELETE /v1/agents/{agentId}/custom-functions/{customFunctionId} correspondiente la desvincula.
  4. Completa la biblioteca de medios. POST /v1/agents/{agentId}/media-library sube un elemento (JSON con base64Data, mimeType, title, description); GET enumera los elementos del agente, y PATCH/DELETE en /{itemId} actualizan o eliminan uno.
  5. Captúralo como una instantánea.
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 de ahí, se aplica la sección anterior: márcala como predeterminada para que cada cliente nuevo nazca con ella, o aplícala bajo demanda. Las tareas de mantenimiento se encuentran junto a esto: PATCH /v1/snapshots/{snapshotId} con { "name": "..." } cambia el nombre de una, DELETE /v1/snapshots/{snapshotId} elimina una (y le quita la marca de predeterminada si lo era), y GET /v1/snapshots/apply-targets enumera todas las cuentas en las que podrías realizar una instalación.

Los endpoints de agente, función personalizada y medios aceptan sub_account_id, por lo que las mismas llamadas también pueden mantener un agente directamente dentro de la cuenta de un cliente. Las llamadas de instantánea siempre actúan sobre tu cuenta de agencia: la plantilla reside contigo. Los esquemas completos de solicitud y respuesta para todos estos se encuentran en la Referencia de la API.


Gestiona tus niveles de precios a través de la API

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

Los planes que vendes en Modo SaaS → Niveles de precios se pueden leer y cambiar desde el código, de modo que tu propio panel de administración o script de aprovisionamiento puede añadir un plan, ajustar un precio o proporcionar un enlace de pago sin que nadie tenga que abrir el panel de control. Autentícate con tu clave API de agencia como en cualquier otra llamada de esta página; estos endpoints son de nivel de agencia, por lo que no requieren sub_account_id. Cada escritura ejecuta la misma validación y la misma sincronización de producto y precio de Stripe que al guardar en el panel de control, por lo que un plan creado aquí es indistinguible de uno configurado manualmente.

Lista tus niveles

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

Respuesta

{
  "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 nivel devuelve su tierIndex — su posición en tu lista de Planes, que es cómo lo direccionan las otras tres llamadas — y un checkout_url listo para compartir, el mismo enlace que te proporciona la pestaña Pagos, que ya apunta al dominio de marca blanca en el que se vende ese plan.

Añadir un nivel

El cuerpo es un objeto de nivel; se añade al final de tu 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"]
  }'

La respuesta contiene el nivel creado, incluyendo el tierIndex en el que se ubicó y su checkout_url.

Editar un nivel

Envía solo los campos que deseas cambiar; todo lo demás en el plan se deja como estaba.

curl -X PATCH "https://api.dmchamp.com/v1/agency/pricing-tiers/0" \
  -H "X-API-Key: YOUR_AGENCY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "price_cents": 3900, "trial_hard_expiry": true }'

Un campo que la API no reconoce es rechazado en lugar de ignorado, y el error lo identifica; así, un error tipográfico nunca puede escribir silenciosamente una configuración que parezca activa pero no haga nada. Cambiar el precio, los créditos, la moneda o la frecuencia de facturación crea un nuevo precio en tu Stripe; los clientes que ya se suscribieron permanecen en lo que contrataron.

Eliminar un nivel

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

La misma regla que en el panel de control: un plan que todavía tiene suscriptores activos no puede ser eliminado. La solicitud es rechazada, indicándote cuántos suscriptores tiene; cancélalos o migralos primero. Una eliminación exitosa responde con tus niveles restantes, ya renumerados.

Los campos de un nivel

Campo Qué es
label / description El nombre del plan y la línea opcional que se muestra en su página de pago.
credits Créditos que obtiene el cliente por mes en un plan mensual o anual, y por periodo de facturación en uno semanal.
price_cents Precio por intervalo de facturación, en la unidad monetaria más pequeña (2900 = $29.00). En un plan anual, este es el precio de todo el año.
currency Código ISO en minúsculas: usd, eur, gbp, etc.
billing_interval / billing_interval_count month (el predeterminado), year o week con un recuento de 1 a 52 para “cada N semanas”.
trial_days Duración de la prueba gratuita, de 0 a 90. 0 (u omitirlo) significa que no hay prueba.
trial_credits Créditos con los que el cliente comienza la prueba. De forma predeterminada, es el credits del plan.
trial_card_required false permite que el cliente comience la prueba sin ingresar una tarjeta. De forma predeterminada, es true.
trial_hard_expiry true devuelve los créditos de prueba no utilizados a su grupo y bloquea la cuenta del cliente cuando una prueba finaliza sin una actualización. De forma predeterminada, es false: consulte Caducidad estricta después de la prueba.
rollover_cap_months Meses de asignación que los clientes en este plan pueden transferir entre renovaciones: un número del 0 al 120, se permiten fracciones. 0 no transfiere nada; null (el predeterminado) significa que no hay límite. Consulte Limitar lo que se transfiere.
rollover_expiry_days Días después de los cuales los créditos no utilizados se eliminan en la siguiente renovación: un número entero del 1 al 3650. null (el predeterminado) significa que nunca caducan.
features / feature_settings Lo que obtienen los clientes en este plan: los mismos ID de función que en Elegir qué tipos de canal puede conectar un cliente.
team_seats_limit Asientos de equipo que otorga el plan: un número exacto, 0 para ninguno, -1 para ilimitado.
white_label_config En cuál de sus dominios de marca blanca se vende el plan.

Los campos de prueba solo tienen significado en un plan que tiene una prueba: guarde un nivel con trial_days: 0 y se eliminarán. Los ID de producto y precio de Stripe del plan se administran por usted y no se pueden configurar manualmente.

Tres cosas que debe tener en cuenta:

  • Los índices de nivel son posiciones, no identificadores permanentes. Eliminar un plan desplaza todos los planes posteriores una posición, por lo que debe volver a obtener la lista después de cualquier cambio, y volver a copiar los enlaces de pago que haya publicado, exactamente como lo haría después de eliminar un plan en el panel de control.
  • El modo SaaS debe configurarse primero. Estos puntos finales requieren una cuenta de agencia con marca blanca y una clave de Stripe ya guardada; sin ella, no hay ninguna cuenta de Stripe en la que puedan residir el producto y el precio del plan.
  • El límite es de veinte planes, igual que en el panel de control. El campo max_tiers en la respuesta de la lista le indica el límite actual.

Los esquemas completos de solicitud y respuesta se encuentran en la Referencia de la API, en Agencia.


Establezca su precio por crédito a través de la API

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

El precio que pagan los clientes por las recargas ad-hoc (Modo SaaS → Precios por crédito) también se puede leer y modificar mediante código. Esto está diseñado para casos en los que el precio debe ajustarse automáticamente: una agencia que vende créditos en una moneda pero cobra en otra puede permitir que una tarea programada revise el precio a medida que cambia el tipo de cambio, en lugar de que alguien lo edite manualmente cada semana.

Leer el precio actual

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

Respuesta

{
  "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 es el precio más bajo que permite la plataforma en esa moneda, por lo que una tarea puede verificar un nuevo precio antes de enviarlo. Los tres valores son null hasta que se haya establecido un precio.

Cambiarlo

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

Envíe solo lo que desea cambiar. price_per_credit_cents es el precio en la unidad monetaria más pequeña (130 = R$1.30); currency es un código ISO en minúsculas; note es una línea opcional de hasta 200 caracteres que se muestra a los clientes directamente debajo del precio por crédito en su página de Facturación; es útil para un precio de referencia en otra moneda, como “USD 0.25 por crédito a nuestra tasa de referencia”. Envíe "note": "" para eliminarlo. La respuesta tiene la misma forma que la lectura anterior, por lo que una tarea puede comparar y omitir la escritura cuando nada ha cambiado.

Se aplican las mismas reglas que en el panel de control: el precio no puede ser inferior al mínimo de la plataforma para esa moneda y la cuenta necesita marca blanca (white labeling). A diferencia de los endpoints de niveles de precios, no se requiere una clave de Stripe para leer o cambiar este valor.

Asigne a una tarea una clave que no pueda hacer nada más

Poner la clave completa de su agencia en un programador otorga más acceso del que necesita una actualización de precios. En su lugar, cree una clave con alcance limitado (scoped key) para el área de Precio de crédito de agencia: esa clave puede leer y cambiar el precio por crédito y nada más; no puede tocar subcuentas, planes, créditos ni su conexión con 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 respuesta contiene la nueva clave en api_key una sola vez; nunca se vuelve a mostrar, así que guárdela de inmediato. Establezca "read_only": true para una clave que solo necesite leer el precio, y añada "expires_at" (una fecha ISO) si desea que deje de funcionar por sí sola. Solo la clave del propietario de la cuenta puede crear claves con alcance limitado; enumérelas o revóquelas con GET /v1/api-keys y DELETE /v1/api-keys/{id}.


Permita que una subcuenta lea sus precios

GET /v1/subaccounts/agency-pricing

Todos los demás endpoints de esta página se llaman con su clave de agencia, apuntando opcionalmente a un cliente a través de sub_account_id. Este es lo opuesto: se llama con la propia clave de API de la subcuenta, sin sub_account_id, de modo que la propia página de recarga de un cliente (o una integración que usted cree para ellos) pueda mostrar lo que usted les cobra sin ver nunca su cuenta de agencia.

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

Respuesta

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

Esto refleja exactamente lo que GET /v1/agency/pricing-tiers y GET /v1/agency/credit-price le devuelven a usted como agencia, menos todo lo que el cliente no necesita ver (ids de Stripe, max_tiers, etc.). Solo funciona para una cuenta que sea realmente una subcuenta con una agencia vinculada; llamarlo desde su propia cuenta de agencia devuelve un error de permiso.


Aspectos a tener en cuenta

  • Utilice su clave de agencia. Autentique cada llamada con la clave de API de su cuenta de agencia, no la de la subcuenta. El parámetro sub_account_id es el que redirige la acción.
  • Los créditos provienen de la subcuenta. Las compras y los cargos recurrentes afectan al saldo de crédito de la subcuenta objetivo, no al suyo.
  • Un 404 significa “no es su subcuenta”. Verifique dos veces el id y que la cuenta sea una que usted gestione.
  • El parámetro es opcional en todos los lugares donde se acepta. Omítalo y el mismo endpoint actuará sobre su cuenta de agencia, por lo que puede reutilizar una integración para ambos casos.

Relacionado

  • Acceso a la API — autenticación, URL base, errores, límites de tasa.
  • Subcuentas — listar y gestionar las cuentas a las que puede dirigirse.
  • Recarga automática de subcuentas — otorgar créditos a una subcuenta mediante webhook + API.
  • API de campañas — crear, actualizar y copiar campañas, incluida la referencia completa de campos.
  • API de conexión de canales — conectar los canales de un cliente y dirigirlos a una campaña.
  • Guía de la API de Analytics (en la sección de API) — el resumen de subcuentas de la agencia y todos los demás endpoints de informes.
  • Instantáneas — qué captura una instantánea y cómo crear una en el panel de control.