Nota de idioma
Esta versión en español es una traducción abreviada: las secciones «4. Personalization and locale», «8. Subscribe to campaign webhooks» y «Worked example: retail promo, draft to analytics» existen solo en inglés: /en/guides/campaign-end-to-end. Los bloques de código, rutas de endpoints, nombres de campos de API y códigos de error permanecen en inglés.Enviar una campaña de principio a fin
Esta guía recorre el ciclo de vida completo de una campaña por la API: crear un borrador, adjuntar una audiencia, verificar la personalización, ejecutar el dry-run previo, lanzar y medir el resultado. Una vez recorrido, la misma secuencia funciona para cada canal — SMS, WhatsApp, email, RCS, voice, push.1. Requisitos previos
- Una clave API con el scope
campaigns:write. Todas las lecturas de abajo (preview de audiencia, dry-run, estadísticas) también aceptancampaigns:read, pero las acciones de lanzamiento requieren escritura. Cree o edite claves en el dashboard bajo Settings → API keys. - Node SDK (opcional).
npm install @devotel-orbit/nodesi prefiere las pestañas SDK a cURL. - Una identidad de envío para su canal. Para SMS/MMS, un número o pool de remitentes con los registros adecuados (el A2P de EE. UU. requiere 10DLC); para WhatsApp, una WABA conectada; para email, un dominio remitente verificado.
- Una fuente de audiencia legitimada. Una lista de contactos, un segmento en vivo, un CSV de direcciones, una audiencia CRM externa (lista de HubSpot / reporte de Salesforce) o un conjunto elegido a mano. Las audiencias deben venir de destinatarios con opt-in — la supresión y las bajas se aplican en el envío, no quedan a cargo del remitente.
2. Crear la campaña borrador
Cree la campaña con un canal, una audiencia y unmessage_template. El template es opcional al crear — un borrador sin template no puede lanzarse — pero proporcionarlo desde el inicio mantiene el borrador completo.
La respuesta devuelve la campaña en estado
draft. Nada se envía hasta que el paso 6 la lance explícitamente.
3. Adjuntar y verificar la audiencia
Lista o segmento. Paseaudience_type: "list" | "segment" con un audience_id, o un descriptor CRM audience_source. Los segmentos se evalúan en vivo en el envío, así que un segmento que crece sigue funcionando.
Destinatarios CSV. Para una nómina puntual, POSTee las direcciones directamente en el array variables.csv_recipients de la campaña (E.164 para canales telefónicos).
Selección manual. audience_type: "manual" con variables.manual_contact_ids apunta a ids de contacto concretos — mismo cálculo de elegibilidad que una lista.
Antes de lanzar, cuente siempre en qué se resuelve la audiencia. POST /api/v1/campaigns/audience/preview acepta la misma forma de audiencia que lleva la campaña y devuelve matching_count más una muestra de 10 contactos:
channel, la respuesta también devuelve una proyección neta: coincidencias brutas menos filas de supresión, menos opt-outs del canal, menos contactos sin dirección entregable para ese canal. Si matching_count vuelve en 0, arregle la audiencia antes de seguir — aquí es donde itera.
5. Pre-vuelo: ejecutar el dry-run
Antes del lanzamiento, POSTee el dry-run. Es de solo lectura — no muta estado, no toca el wallet y no encola jobs.audience.total_in_audience— recuento bruto de coincidencias.audience.suppressed/opted_out/unreachable— las cohortes de la proyección neta.audience.deliverable— el recuento neto exacto que intentará el lanzamiento.cost.unit_price_cents/cost.total_cents— tasado con el mismo resolver que usa la ruta de envío.cost.balance_cents/cost.sufficient— comprobación del wallet; un dry-run en verde implica una puerta de saldo en verde al lanzar.quiet_hours.skipped_estimateyquiet_hours.window— proporción de saltos proyectada por las quiet hours locales del destinatario.warnings[]— avisos no bloqueantes, mostrados aparte de los fallos duros.
warnings: [] y cost.sufficient: true despeja el lanzamiento.
6. Lanzar y elegir la forma de envío
Lance conPOST /api/v1/campaigns/cmp_abc123/send (o scheduled_at para un lote diferido). Cuatro formas de envío entre las que elegir:
Blast. Un lote a una hora — la forma más simple; toda la audiencia entregable sale en una pasada al ritmo de throttle_rate.
Secuencia drip. type: "drip" con un array steps (hasta 50 pasos). Cada paso tiene su canal, su demora y su eventual condición de lectura.
Journey. type: "journey" — inscripción dirigida por eventos con analítica por nodo.
Escalera de respaldo entre canales. Para campañas omnicanal, el array channels es una cadena ordenada; cada entrada salvo la última lleva un disparador fallback_on (failed, no_delivery o no_engagement) y una ventana fallback_after_seconds.
Sea cual sea la forma, estos controles de ritmo aplican:
- Throttle.
throttle_rate(msg/s) limita el ritmo de envío — el defecto de la plataforma es 50 msg/s. - Smart send.
send_time_optimization: "recipient-optimal"programa cada destinatario en su próxima mejor ventana y reparte la entrega durante las 24 h siguientes. - Ventana de envío.
send_window: { start_local_hour, end_local_hour }difiere a los destinatarios cuya hora local cae fuera de la ventana.
7. Observar y medir
Estadísticas en vivo.GET /campaigns/:id/stats devuelve totales de sent, delivered, failed, opened, clicked, replied.
Lift de holdout. Si la campaña fijó un holdout (campaign_holdout_percent en variables), GET /campaigns/:id/holdout-lift compara la cohorte tratada con el control y devuelve un delta de conversión con intervalo de confianza — así ve si el mensaje batió a no enviar nada.
ROI / ROAS. GET /campaigns/:id/roas devuelve ingreso atribuido, embudo de clics e ingreso incremental del holdout; GET /campaigns/:id/cost y /campaigns/:id/export sirven para conciliar el gasto.
9. Solución de problemas
- La audiencia se resuelve a cero. Re-ejecute el preview de audiencia pasando
channel; la proyección neta indica qué cohorte la vació. - El dry-run muestra avisos en rojo. Las entradas de
warnings[]son explícitas — «no provider registered» significa que el canal no tiene identidad de envío configurada; «insufficient balance» significacost.sufficient: false. - El lanzamiento devuelve 402 o una forma pending-approval. Falló la comprobación de saldo o el circuito de aprobación está activo — recargue el wallet o espere la aprobación.
- Campaña journey atascada en paused. Una campaña se pausa sola al llegar a
credit_cap_usd_centso con una condición drip rota. Resuelva el bloqueo y luegoPOST /campaigns/:id/resume.