# DoneTalk API (Español): Desarrolladores # API de DoneTalk La API permite que su sistema (ERP, CRM, sitio, automatización) haga en DoneTalk lo que se hace en pantalla: crear y enviar campañas de WhatsApp, registrar y actualizar contactos, enviar mensajes, seguir y cerrar conversaciones, agendar citas y recibir avisos de todo lo que pasa. - **Dirección:** `https://api.donetalk.com/v1/c/{empresa}`, donde `{empresa}` es el identificador de su empresa en DoneTalk. - **Formato:** JSON, fechas en ISO 8601 (UTC), ids en UUID, dinero en micros (1.000.000 = 1 unidad de moneda). - **Especificación completa:** [OpenAPI](https://api.donetalk.com/v1/openapi.json?lang=es), para generar código o importar en Postman. ## Primeros pasos 1. Un administrador crea la clave en **Configuración › API** en DoneTalk y marca qué puede hacer. Para empezar sin riesgo, elija **Prueba**: lo simula todo y no envía nada. 2. Verifique la clave: ```bash curl https://api.donetalk.com/v1/c/{empresa}/me \ -H "Authorization: Bearer $DONETALK_KEY" ``` 3. Cree una campaña con la lista de contactos en la propia llamada, revise el costo y envíela. La guía [Campañas, de principio a fin](/es/desarrolladores/campanas/) muestra cada paso. 4. Registre una dirección de su sistema para recibir los [avisos](/es/desarrolladores/avisos/): entregado, leído, respondido, conversación concluida con su desenlace. ## Pruébelo ahora, sin cuenta La empresa de demostración `demo` acepta la clave de prueba pública de abajo. Todo es simulado: las respuestas tienen el formato real, con datos de ejemplo, y nada se guarda ni se envía. ```bash export DONETALK_KEY=dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr curl -X POST https://api.donetalk.com/v1/c/demo/campaigns \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Primera campaña", "audience": {"kind": "contacts", "people": [{"phone": "+5548999990001", "name": "Ana"}]}}' ``` ## Qué cubre la API | Área | Qué se puede hacer | | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | [Campañas](/es/desarrolladores/referencia/campaigns/) | crear, revisar costo y reglas, probar, enviar o programar, pausar, reanudar, cancelar, reenviar fallas, ver cada destinatario y los resultados | | [Segmentos](/es/desarrolladores/referencia/segments/) | grupos de contactos por condiciones, contar y buscar | | [Contactos](/es/desarrolladores/referencia/contacts/) | crear, actualizar o importar hasta 1.000 a la vez, etiquetas, consentimiento, fichas de contexto, borrar a pedido del titular | | [Campos](/es/desarrolladores/referencia/contact-fields/) | ver y crear los campos de los contactos | | [Plantillas](/es/desarrolladores/referencia/templates/) | las plantillas aprobadas por Meta, con variables y botones | | [Mensajes](/es/desarrolladores/referencia/messages/) y [conversaciones](/es/desarrolladores/referencia/conversations/) | enviar una plantilla a un teléfono, texto y archivos en la ventana de 24 h, cerrar con desenlace | | [Números, equipos y etiquetas](/es/desarrolladores/referencia/numbers-teams-and-tags/) | para elegir el número que envía y el equipo que recibe las respuestas | | [Agenda](/es/desarrolladores/referencia/scheduling/) | horarios libres, agendar, reprogramar y cancelar | | [Avisos](/es/desarrolladores/referencia/webhooks/) | crear y seguir las direcciones que reciben los eventos | ## Antes de pasar a producción - Use una clave por sistema, solo con los alcances que necesita ([Claves y alcances](/es/desarrolladores/claves-y-alcances/)). - Envíe `Idempotency-Key` en creaciones y envíos y respete el límite de 600 llamadas por minuto ([Errores y límites](/es/desarrolladores/errores-y-limites/)). - Verifique la firma de cada aviso ([Avisos](/es/desarrolladores/avisos/)). --- # Claves y alcances ## Crear una clave En **Configuración › API**, un administrador crea la clave y elige: - **Nombre:** el sistema que la usará (ej.: "ERP de la empresa"). - **Entorno:** **Producción** actúa de verdad; **Prueba** lo simula todo ([Modo de prueba](/es/desarrolladores/modo-prueba/)). - **Qué puede hacer la clave:** los alcances de abajo. Una llamada fuera de los alcances de la clave devuelve `403 insufficient_scope`, con los alcances que sirven en `details.required`. - **Enviar campañas sin esperar aprobación:** sin esto, las campañas de esta clave siguen la regla de aprobación de la empresa (el presupuesto siempre vale). - **Válida hasta** y **solo desde estas direcciones IP**, opcionales. La clave entera se muestra una sola vez, al crearla. Guárdela como una contraseña. Las claves de producción empiezan con `dt_live_`, las de prueba con `dt_test_`. ## Autenticar Envíe la clave en cada llamada: ```http Authorization: Bearer dt_live_... ``` `Authorization: ApiKey dt_live_...` también funciona. La empresa viene de la dirección (`/v1/c/{empresa}/...`) y debe ser la de la clave. ## Alcances | Grupo | Alcance | Qué permite | |---|---|---| | Campañas | `campaigns:read` | Ver campañas y resultados | | Campañas | `campaigns:write` | Crear y editar borradores | | Campañas | `campaigns:send` | Enviar, pausar y cancelar | | Contactos | `contacts:read` | Ver contactos y los valores de los campos | | Contactos | `contacts:write` | Crear y actualizar contactos | | Contactos | `fields:read` | Ver la lista de campos | | Contactos | `fields:write` | Crear campos | | Contactos | `contacts:delete` | Borrar datos de contactos (LGPD) | | Plantillas | `templates:read` | Ver plantillas | | Plantillas | `templates:write` | Crear plantillas y enviarlas a Meta | | Mensajes y conversaciones | `messages:send_template` | Enviar plantillas | | Mensajes y conversaciones | `messages:send_text` | Enviar texto y archivos (ventana de 24 h) | | Mensajes y conversaciones | `conversations:read` | Ver conversaciones y mensajes | | Mensajes y conversaciones | `conversations:write` | Cerrar y reabrir conversaciones | | Flujos y agenda | `flows:start` | Iniciar flujos | | Flujos y agenda | `appointments:read` | Ver citas | | Flujos y agenda | `appointments:write` | Agendar, reprogramar y cancelar citas | | Otros | `webhooks:manage` | Gestionar avisos (webhooks) | | Otros | `reports:read` | Ver informes y costos | | Otros | `workspace:read` | Ver números, equipos y etiquetas | | Otros | `integrations:outboundpro` | Conectar OutboundPro Conversas | ## Claves antiguas Las claves creadas antes de los alcances (`dsf_live_...`) siguen funcionando con el acceso de integración que tenían. Al elegir alcances para una de ellas, queda limitada a ellos. ## Seguridad - Una clave por sistema, con el mínimo de alcances. - Si una clave se filtra, revóquela en Configuración › API: deja de funcionar al instante. - La creación, edición y revocación quedan en la Auditoría, con quién lo hizo. --- # Modo de prueba Una clave de **Prueba** (`dt_test_...`) responde como una de producción, con datos de ejemplo. Nada se guarda, ningún mensaje sale y nada se cobra. - Cada llamada se verifica con las mismas reglas que en producción: un campo incorrecto da el mismo `422 validation_failed`. - La respuesta tiene el formato real, con `"test": true` y el encabezado `DoneTalk-Test: true`. - `GET /me` responde de verdad, para verificar la clave. - Los alcances, el límite de llamadas y `Idempotency-Key` funcionan como en producción. ## Simular un error Envíe el encabezado `DoneTalk-Simulate` con el código del error para recibir exactamente la respuesta que daría producción: ```bash curl -X POST https://api.donetalk.com/v1/c/demo/campaigns \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "DoneTalk-Simulate: template_not_approved" \ -H "Content-Type: application/json" \ -d '{"name": "Prueba"}' ``` Códigos aceptados: `unauthorized`, `api_key_invalid`, `api_key_expired`, `api_key_address_not_allowed`, `insufficient_scope`, `not_available_to_api_keys`, `not_available_to_test_keys`, `permission_denied`, `integration_template_only`, `not_found`, `campaign_not_found`, `contact_not_found`, `validation_failed`, `campaign_not_editable`, `template_not_approved`, `campaign_audience_empty`, `contact_exists`, `window_closed`, `idempotency_key_reused`, `idempotency_in_progress`, `rate_limited`, `internal_error`. ## Teléfonos mágicos En cualquier campo de teléfono, estos números provocan un comportamiento conocido: | Teléfono | Qué pasa | |---|---| | `+550000000400` | `validation_failed` (422) | | `+550000000404` | `contact_not_found` (404) | | `+550000000409` | `contact_exists` (409) | | `+550000000429` | `rate_limited` (429) | | `+550000000500` | `internal_error` (500) | | `+550000000131` | message.failed / campaign.recipient.failed: `131026` | | `+550000000470` | message.failed / campaign.recipient.failed: `131047` | ## Avisos de prueba Un envío con una clave de prueba (un mensaje, una campaña) manda a los avisos de la empresa la secuencia que mandaría producción, con segundos de diferencia: enviado, entregado, leído y, en una campaña, respondido y concluido. Con un teléfono mágico de falla, llega la falla. El sobre trae `"test": true`. ## Empresa de demostración Para probar sin cuenta, use la empresa `demo` con la clave pública: ```bash export DONETALK_KEY=dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr curl https://api.donetalk.com/v1/c/demo/me -H "Authorization: Bearer $DONETALK_KEY" ``` Solo simula: no se puede hacer nada real con ella. --- # Errores, límites y buenas prácticas ## Formato de los errores Todo error vuelve así: ```json { "error": "validation_failed", "message": "Algún campo es incorrecto. `details` dice cuál y por qué.", "details": { "name": ["Required"] }, "request_id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" } ``` - `error` es el código estable: su sistema decide qué hacer a partir de él. - `message` explica, en el idioma del encabezado `Accept-Language` (portugués, inglés o español; inglés por omisión). - `request_id` identifica la llamada: cítelo al hablar con soporte. Puede enviar el suyo en `X-Request-Id`. | HTTP | Código | Qué hacer | |---|---|---| | 401 | `unauthorized` | Falta la clave. Envíe Authorization: Bearer . | | 401 | `api_key_invalid` | Clave inválida o revocada. Revísela o cree otra en Configuración › API. | | 401 | `api_key_expired` | La clave venció. Cree otra en Configuración › API. | | 403 | `api_key_address_not_allowed` | Esta clave no acepta llamadas desde esta dirección IP. Agregue la dirección a la clave. | | 403 | `insufficient_scope` | La clave no tiene el alcance de esta llamada. `details.required` indica cuáles sirven. | | 403 | `not_available_to_api_keys` | Esta llamada no forma parte de la API pública. | | 403 | `not_available_to_test_keys` | Esta llamada no tiene modo de prueba: use una clave de producción. | | 403 | `permission_denied` | La clave no puede hacer esto. | | 403 | `integration_template_only` | Texto y archivos piden el alcance messages:send_text; sin él, solo plantillas aprobadas. | | 404 | `not_found` | No encontrado. | | 404 | `campaign_not_found` | Campaña no encontrada en esta empresa. | | 404 | `contact_not_found` | Contacto no encontrado en esta empresa. | | 422 | `validation_failed` | Algún campo es incorrecto. `details` dice cuál y por qué. | | 409 | `campaign_not_editable` | La campaña ya no es borrador; solo un borrador se puede editar o enviar. | | 409 | `template_not_approved` | Meta aún no aprobó la plantilla. Espere la aprobación o elija otra. | | 409 | `campaign_audience_empty` | Nadie del público puede recibir la campaña. Vea los motivos en la vista previa. | | 409 | `contact_exists` | Ya existe un contacto con este teléfono. `details.contactId` dice cuál. | | 409 | `window_closed` | La ventana de 24 horas está cerrada: solo una plantilla aprobada puede iniciar la conversación. | | 409 | `idempotency_key_reused` | Esta Idempotency-Key ya se usó con otra solicitud. Use una clave nueva por solicitud. | | 409 | `idempotency_in_progress` | La primera solicitud con esta Idempotency-Key aún está en curso. Reintente en un momento. | | 429 | `rate_limited` | Límite de 600 llamadas por minuto. Espere los segundos de Retry-After. | | 500 | `internal_error` | Error de nuestro lado. Ya fuimos avisados; reintente y cite el request_id si persiste. | ## Límite de llamadas Cada clave puede hacer 600 llamadas por minuto. Toda respuesta dice dónde está: ```http RateLimit-Limit: 600 RateLimit-Remaining: 587 RateLimit-Reset: 41 ``` Pasado el límite, la respuesta es `429 rate_limited` con `Retry-After` (segundos). Espere ese tiempo y reintente. El envío de una campaña no cuenta: quien envía es DoneTalk, al ritmo que Meta permite para el número. ## Reintentar sin duplicar Envíe `Idempotency-Key` (hasta 200 letras, números, `_ . : -`) en creaciones y envíos. Si la red falla y envía la misma llamada otra vez con la misma clave dentro de 24 horas, recibe la primera respuesta, con `Idempotent-Replayed: true`, y nada se hace dos veces. La misma clave con otra solicitud devuelve `409 idempotency_key_reused`. ```http Idempotency-Key: pedido-88213-campana ``` ## Paginación - **Campañas:** `limit` y `cursor`; la respuesta trae `nextCursor` (null en la última página). - **Contactos:** `limit` y `before` (el `lastActivityAt` del último de la página). - **Destinatarios de una campaña:** `limit` y `offset`, o `format=csv` para todo. ## Versiones La v1 solo gana cosas nuevas: más campos y llamadas, nunca un cambio en lo que existe. Ignore los campos que no conoce. Si algún día algo debe cambiar, nace la v2 y la v1 sigue funcionando por 12 meses, con aviso. --- # Avisos (webhooks) DoneTalk avisa a su sistema lo que pasa, con un POST firmado a una dirección suya: una campaña empezó o terminó, un mensaje fue entregado o leído, un contacto respondió, una conversación concluyó con su desenlace. ## Registrar una dirección En **Configuración › Integraciones › Webhooks de salida**, o por la API con el alcance `webhooks:manage`: ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/webhooks \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://su-sistema.com/donetalk/avisos", "events": ["campaign.completed", "campaign.recipient.replied", "conversation.closed"]}' ``` La respuesta trae el `secret` una sola vez: guárdelo para verificar las firmas. ## Qué llega ```http POST /donetalk/avisos HTTP/1.1 Content-Type: application/json User-Agent: DoneTalk-Webhooks/1.0 DoneTalk-Signature: t=1792756800,v1=5f0c… X-DoneTalk-Event: conversation.closed X-DoneTalk-Delivery: 01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f ``` ```json { "id": "01a3e4f5-…", "type": "conversation.closed", "occurredAt": "2026-10-24T12:20:41.000Z", "customerId": "01a0c0de-…", "data": { "...": "el contenido del evento" } } ``` Los avisos de una clave de prueba traen `"test": true`. ## Verificar la firma `DoneTalk-Signature` trae `t` (la hora del envío, en segundos) y `v1`, el HMAC SHA-256 de `"."` con su `secret`. Rechace avisos con un `t` de hace más de 5 minutos: así nadie reenvía un aviso antiguo. ```js import crypto from "node:crypto"; function avisoValido(rawBody, header, secret) { const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("="))); if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; const esperado = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"); return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1)); } ``` ```python import hmac, hashlib, time def aviso_valido(raw_body: bytes, header: str, secret: str) -> bool: parts = dict(p.split("=", 1) for p in header.split(",")) if abs(time.time() - int(parts["t"])) > 300: return False esperado = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(esperado, parts["v1"]) ``` El encabezado antiguo `x-donetalk-signature` (`sha256=` + HMAC del cuerpo, sin hora) sigue junto hasta el 21/01/2027. ## Responder y reintentos Responda `2xx` en hasta 10 segundos; haga el trabajo pesado después. Sin `2xx`, DoneTalk reintenta a 1 min, 5 min, 30 min, 2 h y 12 h. Tras 20 fallas seguidas la dirección aparece como "Con fallos" (sigue recibiendo). Un mismo aviso puede llegar más de una vez: use su `id` para procesarlo una vez. El orden de llegada no está garantizado: use `occurredAt`. ## Eventos | Evento | Cuándo llega | |---|---| | `conversation.opened` | Una conversación empezó (el contacto escribió o hizo clic en un anuncio). | | `conversation.closed` | Una conversación concluyó, con el desenlace, quién la concluyó (persona, asistente de IA o regla automática), la nota de cierre, el contacto, el equipo, las etiquetas, cuánto duró y la campaña de origen. | | `conversation.assigned` | Una conversación fue asignada a una persona. | | `conversation.transferred` | Una conversación pasó a otro equipo o persona. | | `conversation.reopened` | Una conversación concluida fue reabierta. | | `contact.updated` | Los datos de un contacto cambiaron. | | `contact.consent_changed` | El contacto aceptó o rechazó recibir mensajes de una finalidad (marketing, por ejemplo). | | `message.received` | El contacto envió un mensaje. | | `message.sent` | Un mensaje nuestro salió hacia WhatsApp. | | `message.delivered` | Un mensaje llegó al teléfono del contacto. | | `message.read` | El contacto leyó un mensaje. | | `message.failed` | Un mensaje no pudo entregarse; `error.code` es el código de Meta. | | `flow.event` | Un flujo llegó a un bloque “Registrar evento”, con el nombre y los datos que define el bloque. | | `appointment.booked` | Una cita fue agendada. | | `appointment.rescheduled` | Una cita cambió de horario. | | `appointment.cancelled` | Una cita fue cancelada. | | `appointment.confirmed` | El contacto confirmó la cita. | | `appointment.attended` | El contacto asistió. | | `appointment.no_show` | El contacto no asistió. | | `campaign.started` | La campaña empezó a enviar; su lista quedó cerrada. | | `campaign.paused` | La campaña se pausó: por una persona, la API o una regla (plantilla pausada, calidad baja, muchas bajas, presupuesto). | | `campaign.resumed` | La campaña volvió a enviar. | | `campaign.completed` | La campaña terminó de enviar, con sus totales. | | `campaign.cancelled` | La campaña fue cancelada. | | `campaign.recipient.sent` | El mensaje de la campaña salió hacia un contacto. | | `campaign.recipient.delivered` | El mensaje de la campaña llegó al contacto. | | `campaign.recipient.read` | El contacto leyó el mensaje de la campaña. | | `campaign.recipient.replied` | El contacto respondió a la campaña (la primera respuesta), por texto o tocando un botón. | | `campaign.recipient.failed` | El mensaje de la campaña falló para un contacto; `errorCode` es el código de Meta. | | `campaign.recipient.opted_out` | El contacto pidió no recibir más campañas (botón “Parar promociones” o rechazo en Meta). | ## Ejemplo de cada evento ### conversation.opened Una conversación empezó (el contacto escribió o hizo clic en un anuncio). ```json { "id": "01a3e4f5-…", "type": "conversation.opened", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channelId": "01a0cccc-0000-7000-8000-000000000002", "handler": "flow", "source": "inbound" } } ``` ### conversation.closed Una conversación concluyó, con el desenlace, quién la concluyó (persona, asistente de IA o regla automática), la nota de cierre, el contacto, el equipo, las etiquetas, cuánto duró y la campaña de origen. ```json { "id": "01a3e4f5-…", "type": "conversation.closed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channelId": "01a0cccc-0000-7000-8000-000000000002", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "outcome": "converted", "isSuccess": true, "closedBy": { "kind": "member", "id": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "name": "Tayomara Batista" }, "actorKind": "member", "openedAt": "2026-10-24T12:00:04.000Z", "firstResponseAt": "2026-10-24T12:05:10.000Z", "messagesIn": 6, "messagesOut": 7, "outcomeLabel": { "pt-BR": "Venda", "en": "Sale", "es": "Venta" }, "outcomeCategory": "success", "note": "Fechou o plano anual com o cupom ANA10.", "contact": { "name": "Ana Souza", "phone": "5548999990001" }, "team": { "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "name": "Vendas" }, "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" } } ], "durationSeconds": 1237, "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b" } } ``` ### conversation.assigned Una conversación fue asignada a una persona. ```json { "id": "01a3e4f5-…", "type": "conversation.assigned", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "reason": "distribution", "previousAssigneeId": null, "actorKind": "system" } } ``` ### conversation.transferred Una conversación pasó a otro equipo o persona. ```json { "id": "01a3e4f5-…", "type": "conversation.transferred", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": null, "previousTeamId": null, "previousAssigneeId": null, "previousHandler": "flow", "actorKind": "flow", "reason": "Gestor de conta: Tayomara Batista" } } ``` ### conversation.reopened Una conversación concluida fue reabierta. ```json { "id": "01a3e4f5-…", "type": "conversation.reopened", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" } } ``` ### contact.updated Los datos de un contacto cambiaron. ```json { "id": "01a3e4f5-…", "type": "contact.updated", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "changes": [ "fields", "displayName" ] } } ``` ### contact.consent_changed El contacto aceptó o rechazó recibir mensajes de una finalidad (marketing, por ejemplo). ```json { "id": "01a3e4f5-…", "type": "contact.consent_changed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channel": "whatsapp", "purpose": "marketing", "status": "opted_out", "source": "keyword", "occurredAt": "2026-10-24T12:06:00.000Z" } } ``` ### message.received El contacto envió un mensaje. ```json { "id": "01a3e4f5-…", "type": "message.received", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channelId": "01a0cccc-0000-7000-8000-000000000002", "type": "text" } } ``` ### message.sent Un mensaje nuestro salió hacia WhatsApp. ```json { "id": "01a3e4f5-…", "type": "message.sent", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "providerMessageId": "wamid.HBgMNTU0ODk5OTk5MDAwMRUCABEYEjE=" } } ``` ### message.delivered Un mensaje llegó al teléfono del contacto. ```json { "id": "01a3e4f5-…", "type": "message.delivered", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "delivered", "occurredAt": "2026-10-24T12:00:06.000Z" } } ``` ### message.read El contacto leyó un mensaje. ```json { "id": "01a3e4f5-…", "type": "message.read", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "read", "occurredAt": "2026-10-24T12:03:51.000Z" } } ``` ### message.failed Un mensaje no pudo entregarse; `error.code` es el código de Meta. ```json { "id": "01a3e4f5-…", "type": "message.failed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "failed", "occurredAt": "2026-10-24T12:00:06.000Z", "error": { "code": "131026", "detail": "Message undeliverable" } } } ``` ### flow.event Un flujo llegó a un bloque “Registrar evento”, con el nombre y los datos que define el bloque. ```json { "id": "01a3e4f5-…", "type": "flow.event", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "name": "lead.qualified", "data": { "plano": "anual", "origem": "site" } } } ``` ### appointment.booked Una cita fue agendada. ```json { "id": "01a3e4f5-…", "type": "appointment.booked", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.rescheduled Una cita cambió de horario. ```json { "id": "01a3e4f5-…", "type": "appointment.rescheduled", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 1, "previousStartsAt": "2026-10-27T12:00:00.000Z", "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.cancelled Una cita fue cancelada. ```json { "id": "01a3e4f5-…", "type": "appointment.cancelled", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "cancelled", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": "2026-10-26T18:00:00.000Z", "cancelledByKind": "contact", "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.confirmed El contacto confirmó la cita. ```json { "id": "01a3e4f5-…", "type": "appointment.confirmed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "confirmed", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": "2026-10-26T14:00:00.000Z", "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.attended El contacto asistió. ```json { "id": "01a3e4f5-…", "type": "appointment.attended", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "attended", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.no_show El contacto no asistió. ```json { "id": "01a3e4f5-…", "type": "appointment.no_show", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "no_show", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### campaign.started La campaña empezó a enviar; su lista quedó cerrada. ```json { "id": "01a3e4f5-…", "type": "campaign.started", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "running", "audience": 1240, "skipped": 24, "startedAt": "2026-10-24T12:00:00.000Z" } } ``` ### campaign.paused La campaña se pausó: por una persona, la API o una regla (plantilla pausada, calidad baja, muchas bajas, presupuesto). ```json { "id": "01a3e4f5-…", "type": "campaign.paused", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "paused", "reason": "optout_rate", "by": "system" } } ``` ### campaign.resumed La campaña volvió a enviar. ```json { "id": "01a3e4f5-…", "type": "campaign.resumed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "running", "by": "api_key" } } ``` ### campaign.completed La campaña terminó de enviar, con sus totales. ```json { "id": "01a3e4f5-…", "type": "campaign.completed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "completed", "totals": { "audience": 1216, "sent": 1216, "delivered": 1198, "read": 874, "replied": 141, "failed": 18, "skipped": 24, "optedOut": 6 } } } ``` ### campaign.cancelled La campaña fue cancelada. ```json { "id": "01a3e4f5-…", "type": "campaign.cancelled", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "cancelled", "by": "member" } } ``` ### campaign.recipient.sent El mensaje de la campaña salió hacia un contacto. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.sent", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "at": "2026-10-24T12:00:04.000Z" } } ``` ### campaign.recipient.delivered El mensaje de la campaña llegó al contacto. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.delivered", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "at": "2026-10-24T12:00:06.000Z" } } ``` ### campaign.recipient.read El contacto leyó el mensaje de la campaña. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.read", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "at": "2026-10-24T12:03:51.000Z" } } ``` ### campaign.recipient.replied El contacto respondió a la campaña (la primera respuesta), por texto o tocando un botón. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.replied", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "buttonIndex": 0, "text": "Quero o cupom" } } ``` ### campaign.recipient.failed El mensaje de la campaña falló para un contacto; `errorCode` es el código de Meta. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.failed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "errorCode": "131026" } } ``` ### campaign.recipient.opted_out El contacto pidió no recibir más campañas (botón “Parar promociones” o rechazo en Meta). ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.opted_out", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "via": "button" } } ``` --- # Campañas, de principio a fin Una campaña envía una plantilla aprobada por Meta, desde uno de sus números, a una lista de contactos, y lleva las respuestas a quien usted elija (un equipo, un flujo o un asistente de IA). Esta guía hace una campaña entera por la API. Pruébelo todo antes con la [clave de demostración](/es/desarrolladores/modo-prueba/). ## 1. Lo que necesita antes ```bash curl https://api.donetalk.com/v1/c/{empresa}/channels -H "Authorization: Bearer $DONETALK_KEY" curl https://api.donetalk.com/v1/c/{empresa}/templates -H "Authorization: Bearer $DONETALK_KEY" curl https://api.donetalk.com/v1/c/{empresa}/teams -H "Authorization: Bearer $DONETALK_KEY" ``` - **Número (`channelId`):** desde dónde sale el mensaje. - **Plantilla (`templateId`):** una plantilla `approved` de la cuenta del número. Sus variables aparecen en el texto como `{{1}}`, `{{2}}`. - **Equipo (`reply.id`):** quién recibe las respuestas. ## 2. Crear el borrador, con la lista ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Idempotency-Key: reactivacion-2026-10" \ -H "Content-Type: application/json" \ -d '{ "name": "Reactivación · octubre", "channelId": "…", "templateId": "…", "variables": [ { "slot": "body.1", "source": "first_name", "fallback": "hola" }, { "slot": "body.2", "source": "value.cupon", "format": "upper" } ], "audience": { "kind": "contacts", "people": [ { "phone": "+5548999990001", "name": "Ana Souza", "values": { "cupon": "ana10" } }, { "phone": "+5548999990002", "name": "Bruno Lima", "values": { "cupon": "bru15" } } ] }, "reply": { "kind": "team", "id": "…" }, "startAt": "2026-10-24T12:00:00.000Z" }' ``` - **Público:** `people` trae el teléfono, el nombre y los valores de cada persona (hasta 20.000; cada teléfono se vuelve un contacto, creado o actualizado, lo que pide también el alcance `contacts:write`). También puede usar contactos existentes (`contactIds`), un segmento (`{"kind": "segment", "segmentId": "…"}`) o un filtro. - **Variables:** cada `{{n}}` de la plantilla viene de `name`, `first_name`, `phone`, un campo del contacto (`field.`), un valor de la lista (`value.`) o un texto fijo. `fallback` entra cuando falta el valor. - **Cuándo:** sin `startAt` empieza al enviar; con él, queda programada. Por omisión solo envía de lunes a viernes, de 9:00 a 18:00, en la zona horaria de la empresa (`sendWindow`). ## 3. Revisar antes de enviar ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/message-preview -H "Authorization: Bearer $DONETALK_KEY" curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/review -H "Authorization: Bearer $DONETALK_KEY" ``` La vista previa muestra el texto de cinco personas y las variables vacías. La revisión trae el costo estimado (hasta), el límite diario del número, los presupuestos y si necesitará aprobación. `POST /campaigns/{id}/test` envía el mensaje a su teléfono. ## 4. Enviar ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/submit -H "Authorization: Bearer $DONETALK_KEY" ``` La respuesta dice `running` (empezó), `scheduled` (programada) o `pending_approval` (la regla de la empresa pide aprobación, y alguien la aprueba en la app). Una clave marcada "Enviar campañas sin esperar aprobación" no espera. Quien recibió marketing en los últimos 7 días, pidió salir o está bloqueado queda fuera; la vista previa del público dice cuántos y por qué. ## 5. Seguirla Por los [avisos](/es/desarrolladores/avisos/), sin consultar: `campaign.started`, `campaign.recipient.sent`, `.delivered`, `.read`, `.replied`, `.failed`, `.opted_out` y `campaign.completed`, con los totales. Cuando la conversación que abrió la campaña concluye, llega `conversation.closed` con el desenlace y el `campaignId`. O consultando: ```bash curl "https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}" -H "Authorization: Bearer $DONETALK_KEY" curl "https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/recipients?status=replied" -H "Authorization: Bearer $DONETALK_KEY" ``` ## 6. Pausar, reanudar, cancelar, reenviar `POST /campaigns/{id}/pause`, `/resume`, `/cancel`. Las fallas que vale la pena repetir vuelven a la cola con `POST /campaigns/{id}/retry` (todas, o solo algunos contactos o códigos de error). La campaña también se pausa sola si Meta pausa la plantilla, baja la calidad del número, muchos piden salir o se acaba el presupuesto. --- # Para IAs y agentes Esta documentación está hecha para que una IA la lea y la pruebe, sin cuenta y sin riesgo. ## Dónde leer - [llms.txt](/es/desarrolladores/llms.txt): el índice, con un enlace a cada página en Markdown. - [llms-full.txt](/es/desarrolladores/llms-full.txt): toda la documentación en un solo archivo. - Cada página también existe en Markdown: cambie la barra final de la dirección por `.md` (ej.: `/es/desarrolladores/campanas.md`). - [OpenAPI](https://api.donetalk.com/v1/openapi.json?lang=es): cada llamada, campo, alcance, error y ejemplo. `x-webhooks` trae los eventos; `x-errors`, los errores; `x-test-mode`, el modo de prueba. ## Probar de verdad, sin riesgo La empresa `demo` acepta la clave de prueba pública `dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr`. Solo simula: verifica las solicitudes con las reglas reales y responde en el formato real, con datos de ejemplo, sin guardar ni enviar nada. ```bash export DONETALK_KEY=dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr curl https://api.donetalk.com/v1/c/demo/me -H "Authorization: Bearer $DONETALK_KEY" ``` Para ver un error, pídalo con `DoneTalk-Simulate: ` ([Modo de prueba](/es/desarrolladores/modo-prueba/)). ## Una instrucción lista para pegar en una IA > Lee https://donetalk.com/es/desarrolladores/llms-full.txt y, usando la empresa demo con la clave de prueba pública, crea una campaña para dos contactos con un cupón por persona, revísala y envíala. Después muestra cómo mi sistema sabría que un contacto respondió. ## Reglas para agentes - Use una clave de **Prueba** mientras desarrolla; producción solo después. - Envíe `Idempotency-Key` en cada creación y envío. - Respete `Retry-After` en un `429`. - Nunca envíe mensajes a números reales sin el consentimiento del contacto: el marketing pide opt-in. --- # Cuenta ## Quién es la clave `GET /v1/c/{slug}/me` · Alcances: cualquier clave La empresa, el nombre de la clave, si es de producción o prueba, sus alcances y el límite de llamadas. Una buena primera llamada. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/me" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "memberId": "01a1b2c3-d4e5-7f60-8a9b-0c1d2e3f4a5b", "role": "integration", "permissions": [ "api.use", "campaigns.read", "campaigns.start", "campaigns.write", "contacts.read", "contacts.write" ], "company": { "slug": "captei", "name": "Captei" }, "key": { "name": "ERP Captei", "prefix": "dt_live_7Hq2mV0c", "environment": "live", "scopes": [ "campaigns:read", "campaigns:write", "campaigns:send", "contacts:write" ], "legacy": false, "skipApproval": false, "expiresAt": null }, "rateLimit": { "limit": 600, "windowSeconds": 60 } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Campañas ## Listar campañas `GET /v1/c/{slug}/campaigns` · Alcances: `campaigns:read` Las más nuevas primero, cada una con sus números. Filtre por `status`. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `status` | string | no | hasta 40 caracteres | | `limit` | integer | no | hasta 200; mínimo 1; default `200` | | `cursor` | string | no | hasta 200 caracteres | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "campaigns": [ { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "draft", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": null, "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } ], "nextCursor": null } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Crear una campaña `POST /v1/c/{slug}/campaigns` · Alcances: `campaigns:write` Crea un borrador. Nada se envía hasta `submit`. El público es un segmento, un filtro o una lista de contactos: por id (`contactIds`) o por teléfono (`people`), con valores propios de cada persona para las variables `value.`. Cada teléfono se vuelve un contacto, creado o actualizado, lo que pide también el alcance contacts:write. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `name` | string | sí | hasta 120 caracteres | | `channelId` | string (uuid) | no | null | | `templateId` | string (uuid) | no | null | | `variables` | lista de objeto | no | hasta 40 | | `variables[].slot` | string | sí | | | `variables[].source` | uno de `name`, `first_name`, `phone`, `fixed` · string | sí | | | `variables[].value` | string | no | hasta 500 caracteres | | `variables[].format` | uno de `none`, `title`, `upper`, `lower`, `first` | no | default `"none"` | | `variables[].fallback` | string | no | hasta 200 caracteres; default `""` | | `buttons` | lista de objeto | no | hasta 10 | | `buttons[].index` | integer | sí | hasta 9 | | `buttons[].action` | uno de `route`, `optout`, `none` | sí | | | `audience` | objeto | no | null | | `audience.kind` | uno de `segment` | sí | | | `audience.segmentId` | string (uuid) | sí | | | `audience.conditions` | lista de objeto | sí | hasta 20 | | `audience.conditions[].field` | string | sí | hasta 80 caracteres | | `audience.conditions[].op` | uno de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sí | | | `audience.conditions[].value` | string · number · boolean · uno de `null` | no | | | `audience.contactIds` | lista de string (uuid) | no | hasta 20000; default `[]` | | `audience.people` | lista de objeto | no | hasta 20000 | | `audience.people[].phone` | string | sí | hasta 40 caracteres | | `audience.people[].name` | string | no | hasta 200 caracteres | | `audience.people[].fields` | object | no | | | `audience.people[].tags` | lista de string | no | hasta 20 | | `audience.people[].values` | object | no | | | `audience.values` | object | no | | | `excludeOpen` | boolean | no | | | `frequencyDays` | integer | no | hasta 90; null | | `startAt` | string (date-time) | no | null | | `sendWindow` | lista de objeto | no | hasta 14 | | `sendWindow[].day` | integer | sí | hasta 7; mínimo 1 | | `sendWindow[].from` | string | sí | | | `sendWindow[].to` | string | sí | | | `reply` | objeto | no | | | `reply.kind` | uno de `team`, `flow`, `assistant` | no | default `"team"` | | `reply.id` | string (uuid) | no | default `null`; null | | `reply.goal` | string | no | hasta 200 caracteres; default `null`; null | | `successDays` | integer | no | hasta 60; mínimo 1 | | `stopRules` | objeto | no | | | `stopRules.templatePaused` | boolean | no | default `true` | | `stopRules.qualityLow` | boolean | no | default `true` | | `stopRules.optoutRate` | number | no | hasta 0.5; mínimo 0.005; default `0.03`; null | | `stopRules.budget` | boolean | no | default `true` | | `budgetMicros` | integer | no | hasta 1000000000000000; null | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Reativação · outubro", "channelId": "01a0cccc-0000-7000-8000-000000000002", "templateId": "01a0cad0-0000-7000-8000-000000000002", "variables": [ { "slot": "body.1", "source": "first_name", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "people": [ { "phone": "+5548999990001", "name": "Ana Souza", "values": { "cupom": "ana10" } }, { "phone": "+5548999990002", "name": "Bruno Lima", "values": { "cupom": "bru15" } } ] }, "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701" }, "startAt": "2026-10-24T12:00:00.000Z" }' ``` ### Respuesta 201 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "draft", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": null, "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } } ``` ### Errores posibles - `400` `template_other_account` - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Ver una campaña `GET /v1/c/{slug}/campaigns/{id}` · Alcances: `campaigns:read` La campaña con su embudo: enviadas, entregadas, leídas, respuestas, fallas, éxitos y costo (en micros: 1.000.000 = 1 unidad de moneda). ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "running", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": "2026-10-24T12:00:00.000Z", "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Editar un borrador `PATCH /v1/c/{slug}/campaigns/{id}` · Alcances: `campaigns:write` Solo un borrador cambia. Envíe solo lo que cambia. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `name` | string | no | hasta 120 caracteres | | `channelId` | string (uuid) | no | null | | `templateId` | string (uuid) | no | null | | `variables` | lista de objeto | no | hasta 40 | | `variables[].slot` | string | sí | | | `variables[].source` | uno de `name`, `first_name`, `phone`, `fixed` · string | sí | | | `variables[].value` | string | no | hasta 500 caracteres | | `variables[].format` | uno de `none`, `title`, `upper`, `lower`, `first` | no | default `"none"` | | `variables[].fallback` | string | no | hasta 200 caracteres; default `""` | | `buttons` | lista de objeto | no | hasta 10 | | `buttons[].index` | integer | sí | hasta 9 | | `buttons[].action` | uno de `route`, `optout`, `none` | sí | | | `audience` | objeto | no | null | | `audience.kind` | uno de `segment` | sí | | | `audience.segmentId` | string (uuid) | sí | | | `audience.conditions` | lista de objeto | sí | hasta 20 | | `audience.conditions[].field` | string | sí | hasta 80 caracteres | | `audience.conditions[].op` | uno de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sí | | | `audience.conditions[].value` | string · number · boolean · uno de `null` | no | | | `audience.contactIds` | lista de string (uuid) | no | hasta 20000; default `[]` | | `audience.people` | lista de objeto | no | hasta 20000 | | `audience.people[].phone` | string | sí | hasta 40 caracteres | | `audience.people[].name` | string | no | hasta 200 caracteres | | `audience.people[].fields` | object | no | | | `audience.people[].tags` | lista de string | no | hasta 20 | | `audience.people[].values` | object | no | | | `audience.values` | object | no | | | `excludeOpen` | boolean | no | | | `frequencyDays` | integer | no | hasta 90; null | | `startAt` | string (date-time) | no | null | | `sendWindow` | lista de objeto | no | hasta 14 | | `sendWindow[].day` | integer | sí | hasta 7; mínimo 1 | | `sendWindow[].from` | string | sí | | | `sendWindow[].to` | string | sí | | | `reply` | objeto | no | | | `reply.kind` | uno de `team`, `flow`, `assistant` | no | default `"team"` | | `reply.id` | string (uuid) | no | default `null`; null | | `reply.goal` | string | no | hasta 200 caracteres; default `null`; null | | `successDays` | integer | no | hasta 60; mínimo 1 | | `stopRules` | objeto | no | | | `stopRules.templatePaused` | boolean | no | default `true` | | `stopRules.qualityLow` | boolean | no | default `true` | | `stopRules.optoutRate` | number | no | hasta 0.5; mínimo 0.005; default `0.03`; null | | `stopRules.budget` | boolean | no | default `true` | | `budgetMicros` | integer | no | hasta 1000000000000000; null | ### Ejemplo de solicitud ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/campaigns/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Reativação · outubro (2)", "frequencyDays": 7 }' ``` ### Respuesta 200 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "draft", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": null, "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } } ``` ### Errores posibles - `400` `template_other_account` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `campaign_not_editable` - `422` `validation_failed` - `429` `rate_limited` ## Borrar una campaña `DELETE /v1/c/{slug}/campaigns/{id}` · Alcances: `campaigns:write` Borradores, canceladas y concluidas. Una campaña enviando debe cancelarse antes. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/campaigns/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Duplicar `POST /v1/c/{slug}/campaigns/{id}/duplicate` · Alcances: `campaigns:write` Un borrador nuevo con la misma configuración y el mismo público. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/duplicate" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 201 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Poner la imagen o documento del encabezado `PUT /v1/c/{slug}/campaigns/{id}/header` · Alcances: `campaigns:write` Para plantillas con encabezado de medio: suba el archivo con `POST /uploads` y pase el `uploadId`. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `uploadId` | string (uuid) | sí | | ### Ejemplo de solicitud ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/campaigns/:id/header" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "uploadId": "01a3d1e2-f3a4-7b5c-8d6e-7f8091a2b3c4" }' ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `campaign_not_editable` - `422` `validation_failed` - `429` `rate_limited` ## Vista previa del público `POST /v1/c/{slug}/campaigns/{id}/audience-preview` · Alcances: `campaigns:read` Cuántos la reciben y cuántos quedan fuera, por motivo: bloqueado, sin WhatsApp, pidió salir, repetido, frecuencia de marketing, conversación abierta. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/audience-preview" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "found": 1264, "excluded": { "blocked": 0, "no_whatsapp": 2, "opted_out": 18, "duplicate": 0, "frequency": 4, "open_conversation": 0 }, "openConversations": 3, "receive": 1240, "samples": [ { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "address": "5548999990001" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Vista previa del mensaje `POST /v1/c/{slug}/campaigns/{id}/message-preview` · Alcances: `campaigns:read` Cómo llega el mensaje a cinco personas del público y qué variables quedarían vacías. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/message-preview" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "slots": [ "body.1", "body.2" ], "quickReplies": [ { "index": 0, "text": "Quero o cupom" } ], "samples": [ { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "text": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "missing": [] } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Revisar: costo, controles y aprobación `POST /v1/c/{slug}/campaigns/{id}/review` · Alcances: `campaigns:read` El costo estimado (hasta), el límite diario del número, los presupuestos, cuántas personas quedarían sin alguna variable y si la campaña necesitará aprobación. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/review" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "estimate": { "currency": "BRL", "people": 1240, "totalMicros": 77824000, "markets": [ { "market": "BR", "people": 1240, "rateMicros": 62760, "micros": 77822400 } ] }, "checks": { "templateApproved": true, "channelActive": true, "quality": "GREEN", "dailyLimit": 1000, "days": 2, "budgets": [], "campaignBudgetMicros": null, "missingVariables": 0 }, "approval": { "required": false, "approvers": [] } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Enviar una prueba `POST /v1/c/{slug}/campaigns/{id}/test` · Alcances: `campaigns:write` Envía el mensaje a un teléfono (el suyo), sin contar en los números de la campaña. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `phone` | string | sí | hasta 40 caracteres | | `name` | string | no | hasta 200 caracteres | | `values` | object | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/test" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5548999990009", "name": "Leo", "values": { "cupom": "teste10" } }' ``` ### Respuesta 200 ```json { "ok": true, "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889" } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `template_not_approved` - `422` `validation_failed` - `429` `rate_limited` ## Enviar o programar `POST /v1/c/{slug}/campaigns/{id}/submit` · Alcances: `campaigns:send` Con `startAt` en el futuro queda programada; sin él, empieza ahora. Si la regla de aprobación de la empresa lo pide, queda `pending_approval` hasta que alguien la apruebe en la app, salvo que la clave tenga “Enviar sin esperar aprobación”. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `approverId` | string (uuid) | no | default `null`; null | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/submit" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` ### Respuesta 200 ```json { "status": "scheduled" } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `campaign_not_editable` - `409` `template_not_approved` - `409` `campaign_audience_empty` - `422` `validation_failed` - `429` `rate_limited` ## Pausar `POST /v1/c/{slug}/campaigns/{id}/pause` · Alcances: `campaigns:send` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/pause" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "status": "paused" } ``` ### Errores posibles - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Reanudar `POST /v1/c/{slug}/campaigns/{id}/resume` · Alcances: `campaigns:send` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/resume" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "status": "running" } ``` ### Errores posibles - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Cancelar `POST /v1/c/{slug}/campaigns/{id}/cancel` · Alcances: `campaigns:send` Deja de enviar para siempre. Lo enviado sigue contando en los resultados. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/cancel" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "status": "cancelled" } ``` ### Errores posibles - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Reenviar las fallas `POST /v1/c/{slug}/campaigns/{id}/retry` · Alcances: `campaigns:send` Vuelve a la cola quien falló: todos, o solo algunos contactos o códigos de error. Las fallas que no tiene sentido repetir quedan fuera. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `contactIds` | lista de string (uuid) | no | hasta 20000 | | `errorCodes` | lista de string | no | hasta 50 | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/retry" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "errorCodes": [ "131049" ] }' ``` ### Respuesta 200 ```json { "requeued": 12 } ``` ### Errores posibles - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Destinatarios, uno por uno `GET /v1/c/{slug}/campaigns/{id}/recipients` · Alcances: `campaigns:read` Cada contacto con el estado del mensaje, la respuesta, el botón tocado y la conversación que abrió, con su desenlace. `status` filtra; `format=csv` descarga todo. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `status` | string | no | hasta 20 caracteres | | `limit` | integer | no | hasta 500; mínimo 1; default `100` | | `offset` | integer | no | default `0` | | `format` | uno de `json`, `csv` | no | default `"json"` | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns/:id/recipients" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "recipients": [ { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "externalRef": "erp-88213", "address": "5548999990001", "status": "read", "skipReason": null, "errorCode": null, "sentAt": "2026-10-24T12:00:04.000Z", "deliveredAt": "2026-10-24T12:00:06.000Z", "readAt": "2026-10-24T12:03:51.000Z", "repliedAt": "2026-10-24T12:04:02.000Z", "buttonIndex": 0, "optedOutAt": null, "successAt": null, "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "nextAttemptAt": null, "conversation": { "status": "closed", "handler": "human", "lastInboundAt": "2026-10-24T12:09:10.000Z", "lastMessageAt": "2026-10-24T12:20:41.000Z", "lastMessageBy": "member", "closedAt": "2026-10-24T12:20:41.000Z", "closedBy": "member", "outcome": { "code": "converted", "category": "success", "label": { "pt-BR": "Venda", "en": "Sale", "es": "Venta" }, "note": "Fechou o plano anual com o cupom ANA10." } }, "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" } } ] } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Fallas, botones y clics `GET /v1/c/{slug}/campaigns/{id}/insights` · Alcances: `campaigns:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns/:id/insights" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "failures": [ { "code": "131026", "count": 9, "waiting": 0 } ], "skipped": [ { "reason": "opted_out", "count": 18 } ], "buttons": [ { "index": 0, "text": "Quero o cupom", "taps": 96 } ], "links": [], "perHour": [ { "hour": "2026-10-24T12:00:00.000Z", "count": 640 } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` --- # Segmentos ## Listar segmentos `GET /v1/c/{slug}/segments` · Alcances: `contacts:read` · `campaigns:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/segments" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "segments": [ { "id": "01a1a0b0-1c2d-7e3f-8a9b-0c1d2e3f4a5b", "name": "Clientes do plano anual", "conditions": [ { "field": "field.plano", "op": "eq", "value": "anual" } ], "count": 312, "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Crear un segmento `POST /v1/c/{slug}/segments` · Alcances: `contacts:write` Un grupo de contactos por condiciones: etiqueta, origen, último desenlace, días desde la última conversación o el alta, consentimiento de marketing, nombre, WhatsApp y cualquier campo (`field.`). ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `name` | string | sí | hasta 120 caracteres | | `conditions` | lista de objeto | sí | hasta 20 | | `conditions[].field` | string | sí | hasta 80 caracteres | | `conditions[].op` | uno de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sí | | | `conditions[].value` | string · number · boolean · uno de `null` | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/segments" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Clientes do plano anual", "conditions": [ { "field": "field.plano", "op": "eq", "value": "anual" } ] }' ``` ### Respuesta 201 ```json { "segment": { "id": "01a1a0b0-1c2d-7e3f-8a9b-0c1d2e3f4a5b" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Editar un segmento `PUT /v1/c/{slug}/segments/{id}` · Alcances: `contacts:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `name` | string | sí | hasta 120 caracteres | | `conditions` | lista de objeto | sí | hasta 20 | | `conditions[].field` | string | sí | hasta 80 caracteres | | `conditions[].op` | uno de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sí | | | `conditions[].value` | string · number · boolean · uno de `null` | no | | ### Ejemplo de solicitud ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/segments/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Clientes do plano anual", "conditions": [ { "field": "field.plano", "op": "eq", "value": "anual" } ] }' ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Borrar un segmento `DELETE /v1/c/{slug}/segments/{id}` · Alcances: `contacts:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/segments/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Contar quién entra `POST /v1/c/{slug}/segments/count` · Alcances: `contacts:read` · `campaigns:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `conditions` | lista de objeto | sí | hasta 20 | | `conditions[].field` | string | sí | hasta 80 caracteres | | `conditions[].op` | uno de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sí | | | `conditions[].value` | string · number · boolean · uno de `null` | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/segments/count" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "conditions": [ { "field": "tag", "op": "has", "value": "01a12150-3610-7c00-b680-188c2b4c7313" } ] }' ``` ### Respuesta 200 ```json { "count": 312 } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Buscar contactos por condiciones `POST /v1/c/{slug}/contacts/search` · Alcances: `contacts:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `segmentId` | string (uuid) | no | | | `conditions` | lista de objeto | no | hasta 20; default `[]` | | `conditions[].field` | string | sí | hasta 80 caracteres | | `conditions[].op` | uno de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sí | | | `conditions[].value` | string · number · boolean · uno de `null` | no | | | `q` | string | no | hasta 100 caracteres | | `limit` | integer | no | hasta 200; mínimo 1; default `50` | | `offset` | integer | no | hasta 1000000; default `0` | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/search" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "conditions": [ { "field": "marketing", "op": "eq", "value": "opted_in" } ], "limit": 50 }' ``` ### Respuesta 200 ```json { "total": 312, "marketingAllowed": 298, "contacts": [ { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "source": "api", "fields": { "cpf": "529.982.247-25", "plano": "anual" }, "isBlocked": false, "address": "5548999990001", "marketing": "opted_in", "lastOutcome": "converted", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "lastActivityAt": "2026-10-22T18:40:02.000Z", "createdAt": "2026-09-23T22:19:30.396Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Contactos ## Listar contactos `GET /v1/c/{slug}/contacts` · Alcances: `contacts:read` Los más activos primero. `q` busca por nombre o teléfono; `tag` filtra por etiqueta; `before` (el `lastActivityAt` del último) trae la página siguiente. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `q` | string | no | hasta 200 caracteres | | `limit` | integer | no | hasta 100; mínimo 1; default `50` | | `before` | string (date-time) | no | | | `tag` | string (uuid) | no | | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contacts" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "contacts": [ { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "address": "5548999990001", "channelKind": "whatsapp", "source": "api", "externalRef": "erp-88213", "fields": { "cpf": "529.982.247-25", "plano": "anual" }, "isBlocked": false, "lastActivityAt": "2026-10-22T18:40:02.000Z", "createdAt": "2026-09-23T22:19:30.396Z", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ] } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Crear un contacto `POST /v1/c/{slug}/contacts` · Alcances: `contacts:write` Para crear o actualizar varios a la vez (o uno que quizás exista), use `POST /contacts/import`. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `displayName` | string | sí | hasta 200 caracteres | | `phone` | string | sí | | | `locale` | uno de `pt-BR`, `es`, `en` | no | | | `fields` | object | no | | | `externalRef` | string | no | hasta 200 caracteres | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "displayName": "Ana Souza", "phone": "+5548999990001", "externalRef": "erp-88213", "fields": { "cpf": "529.982.247-25" } }' ``` ### Respuesta 201 ```json { "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "address": "5548999990001" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `409` `contact_exists` - `422` `validation_failed` - `429` `rate_limited` ## Crear o actualizar contactos (hasta 1.000) `POST /v1/c/{slug}/contacts/import` · Alcances: `contacts:write` Por teléfono: los existentes se actualizan (nombre, campos, etiquetas), los nuevos se crean. Cada fila vuelve con el id del contacto. Una fila con problema no detiene las demás. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `rows` | lista de objeto | sí | hasta 1000 | | `rows[].phone` | string | sí | hasta 40 caracteres | | `rows[].name` | string | no | hasta 200 caracteres | | `rows[].fields` | object | no | | | `rows[].tags` | lista de string | no | hasta 20 | | `rows[].externalRef` | string | no | hasta 200 caracteres | | `rows[].marketingOptIn` | boolean | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/import" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "rows": [ { "phone": "+5548999990001", "name": "Ana Souza", "tags": [ "VIP" ], "externalRef": "erp-88213" }, { "phone": "48 99999-0002", "name": "Bruno Lima", "fields": { "plano": "mensal" }, "marketingOptIn": true } ] }' ``` ### Respuesta 200 ```json { "created": 1, "updated": 1, "errors": [ { "row": 2, "reason": "invalid_phone" } ], "contacts": [ { "row": 0, "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "created": false }, { "row": 1, "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9", "created": true } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Ver un contacto `GET /v1/c/{slug}/contacts/{id}` · Alcances: `contacts:read` El contacto con sus campos, números, consentimientos, últimas conversaciones y etiquetas, y las definiciones de campos de la empresa. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contacts/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "address": "5548999990001", "channelKind": "whatsapp", "source": "api", "externalRef": "erp-88213", "fields": { "cpf": "529.982.247-25", "plano": "anual" }, "isBlocked": false, "lastActivityAt": "2026-10-22T18:40:02.000Z", "createdAt": "2026-09-23T22:19:30.396Z", "firstName": "Ana", "lastName": "Souza", "locale": "pt-BR", "timezone": null, "blockedReason": null }, "identities": [ { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9", "channel_kind": "whatsapp", "address": "5548999990001", "external_id": null, "provider_display_name": "Ana", "is_primary": true, "last_seen_at": "2026-10-22T18:40:02.000Z" } ], "consents": [ { "purpose": "marketing", "channel_kind": "whatsapp", "status": "opted_in", "source": "api", "occurred_at": "2026-10-01T10:00:00.000Z" } ], "conversations": [ { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "status": "closed", "source_kind": "campaign", "imported_from": null, "created_at": "2026-10-24T12:00:04.000Z", "closed_at": "2026-10-24T12:20:41.000Z", "channel_id": "01a0cccc-0000-7000-8000-000000000002", "outcome_code": "converted", "is_success": true } ], "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "fieldDefinitions": [ { "key": "cpf", "label": { "pt-BR": "CPF", "en": "CPF", "es": "CPF" }, "type": "cpf", "options": null, "ai_extractable": true, "required": false, "sort": 1 } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Editar un contacto `PATCH /v1/c/{slug}/contacts/{id}` · Alcances: `contacts:write` `fields` se combina con los campos del contacto; envíe `null` en un campo para borrarlo. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `displayName` | string | no | hasta 200 caracteres | | `firstName` | string | no | hasta 100 caracteres; null | | `lastName` | string | no | hasta 100 caracteres; null | | `locale` | uno de `pt-BR`, `es`, `en` | no | null | | `externalRef` | string | no | hasta 200 caracteres; null | | `fields` | object | no | | | `isBlocked` | boolean | no | | | `blockedReason` | string | no | hasta 200 caracteres; null | ### Ejemplo de solicitud ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/contacts/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "fields": { "plano": "anual" }, "externalRef": "erp-88213" }' ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Registrar consentimiento `POST /v1/c/{slug}/contacts/{id}/consents` · Alcances: `contacts:write` Opt-in u opt-out por finalidad (atención, utilidad, marketing). Un opt-out de marketing saca al contacto de las campañas de marketing. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `purpose` | uno de `service`, `utility`, `marketing` | sí | | | `status` | uno de `opted_in`, `opted_out` | sí | | | `source` | uno de `form`, `import`, `api`, `message`, `keyword` | no | default `"form"` | | `evidence` | object | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/:id/consents" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "purpose": "marketing", "status": "opted_in", "source": "api" }' ``` ### Respuesta 201 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Poner una etiqueta `PUT /v1/c/{slug}/contacts/{id}/tags/{tagId}` · Alcances: `contacts:write` Puede iniciar los flujos que empiezan cuando se pone esta etiqueta. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | | `tagId` | El id de la etiqueta. | ### Ejemplo de solicitud ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/contacts/:id/tags/:tagId" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Quitar una etiqueta `DELETE /v1/c/{slug}/contacts/{id}/tags/{tagId}` · Alcances: `contacts:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | | `tagId` | El id de la etiqueta. | ### Ejemplo de solicitud ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/contacts/:id/tags/:tagId" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Fichas de contexto `GET /v1/c/{slug}/contacts/{id}/context-cards` · Alcances: `contacts:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "cards": [ { "key": "erp", "source": "ERP Captei", "title": "Cliente desde 2023", "status": "Plano anual", "tone": "success", "fields": [ { "label": "Pedidos", "value": "14" } ], "link": { "url": "https://erp.captei.com.br/clientes/88213", "label": "Abrir no ERP" }, "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Mostrar una ficha a quien atiende `PUT /v1/c/{slug}/contacts/{id}/context-cards/{key}` · Alcances: `contacts:write` Una ficha de su sistema que aparece junto a la conversación (plan, pedidos, saldo). La misma `key` reemplaza la anterior. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | | `key` | La clave (del campo o de la ficha). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `title` | string | sí | hasta 120 caracteres | | `source` | string | no | hasta 60 caracteres | | `status` | string | no | hasta 60 caracteres; null | | `tone` | uno de `neutral`, `success`, `warning`, `danger`, `info` | no | default `"neutral"` | | `fields` | lista de objeto | no | hasta 12; default `[]` | | `fields[].label` | string | sí | hasta 60 caracteres | | `fields[].value` | string | sí | hasta 300 caracteres | | `link` | objeto | no | null | | `link.url` | string (uri) | sí | hasta 2000 caracteres | | `link.label` | string | no | hasta 60 caracteres | ### Ejemplo de solicitud ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards/:key" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Cliente desde 2023", "source": "ERP Captei", "status": "Plano anual", "tone": "success", "fields": [ { "label": "Pedidos", "value": "14" } ], "link": { "url": "https://erp.captei.com.br/clientes/88213", "label": "Abrir no ERP" } }' ``` ### Respuesta 200 ```json { "card": { "key": "erp", "source": "ERP Captei", "title": "Cliente desde 2023", "status": "Plano anual", "tone": "success", "fields": [ { "label": "Pedidos", "value": "14" } ], "link": { "url": "https://erp.captei.com.br/clientes/88213", "label": "Abrir no ERP" }, "updatedAt": "2026-10-23T13:02:11.000Z" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Quitar una ficha `DELETE /v1/c/{slug}/contacts/{id}/context-cards/{key}` · Alcances: `contacts:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | | `key` | La clave (del campo o de la ficha). | ### Ejemplo de solicitud ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards/:key" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Borrar los datos del contacto (LGPD) `POST /v1/c/{slug}/contacts/{id}/erase` · Alcances: `contacts:delete` A pedido del titular: el contacto y sus mensajes se anonimizan para siempre. No se puede deshacer. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/:id/erase" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` --- # Campos de contactos ## Listar los campos de contactos `GET /v1/c/{slug}/contact-fields` · Alcances: `fields:read` · `contacts:read` Los campos de la empresa (clave, nombre en tres idiomas, tipo, opciones). Los valores de cada contacto vienen en `fields` del contacto. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contact-fields" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "fields": [ { "key": "cpf", "label": { "pt-BR": "CPF", "en": "CPF", "es": "CPF" }, "type": "cpf", "options": null, "aiExtractable": true, "aiExtractionHint": null, "required": false, "sort": 1, "isActive": true } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Crear un campo `POST /v1/c/{slug}/contact-fields` · Alcances: `fields:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `key` | string | sí | | | `label` | string · object | sí | | | `type` | uno de `text`, `number`, `date`, `boolean`, `select`, `phone`, `email`, `cpf`, `cnpj` | sí | | | `options` | lista de string | no | hasta 50; null | | `aiExtractable` | boolean | no | default `false` | | `aiExtractionHint` | string | no | hasta 300 caracteres; null | | `required` | boolean | no | default `false` | | `sort` | integer | no | hasta 1000 | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contact-fields" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "key": "plano", "label": "Plano", "type": "select", "options": [ "mensal", "anual" ] }' ``` ### Respuesta 201 ```json { "field": { "key": "cpf", "label": { "pt-BR": "CPF", "en": "CPF", "es": "CPF" }, "type": "cpf", "options": null, "aiExtractable": true, "aiExtractionHint": null, "required": false, "sort": 1, "isActive": true } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Editar un campo `PATCH /v1/c/{slug}/contact-fields/{key}` · Alcances: `fields:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `key` | La clave (del campo o de la ficha). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `label` | string · object | no | | | `options` | lista de string | no | hasta 50; null | | `aiExtractable` | boolean | no | | | `aiExtractionHint` | string | no | hasta 300 caracteres; null | | `required` | boolean | no | | | `sort` | integer | no | hasta 1000 | | `isActive` | boolean | no | | ### Ejemplo de solicitud ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/contact-fields/:key" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "options": [ "mensal", "semestral", "anual" ] }' ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Plantillas ## Listar plantillas `GET /v1/c/{slug}/templates` · Alcances: `templates:read` · `campaigns:write` · `messages:send_template` Las plantillas de mensaje de cada cuenta de WhatsApp, con el estado en Meta, categoría y componentes (las variables `{{1}}` están en el texto). ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/templates" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "templates": [ { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "language": "pt_BR", "category": "marketing", "status": "approved", "quality": "GREEN", "accountId": "01a0cccc-0000-7000-8000-000000000001", "accountName": "Captei WABA", "components": [ { "type": "BODY", "text": "Oi {{1}}! Seu cupom {{2}} vale até sexta. Quer usar agora?" }, { "type": "BUTTONS", "buttons": [ { "type": "QUICK_REPLY", "text": "Quero o cupom" } ] } ], "rejectionReason": null, "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Mensajes ## Enviar una plantilla a un teléfono `POST /v1/c/{slug}/messages/template` · Alcances: `messages:send_template` En la conversación abierta del contacto, o en una nueva, atendida como el número atiende lo que llega. El contacto se crea si no existe. `idempotencyKey` (o el encabezado Idempotency-Key) evita enviar dos veces. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `phone` | string | sí | | | `contactName` | string | no | hasta 200 caracteres | | `channelId` | string (uuid) | no | | | `templateId` | string (uuid) | sí | | | `body` | lista de string | no | hasta 20; default `[]` | | `header` | lista de string | no | hasta 5; default `[]` | | `buttons` | object | no | default `{}` | | `handling` | uno de `number`, `team` | no | default `"number"` | | `assigneeEmail` | string (email) | no | hasta 320 caracteres | | `idempotencyKey` | string | sí | hasta 200 caracteres | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/messages/template" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5548999990001", "contactName": "Ana Souza", "templateId": "01a0cad0-0000-7000-8000-000000000002", "body": [ "Ana", "ANA10" ], "idempotencyKey": "pedido-88213-lembrete" }' ``` ### Respuesta 201 ```json { "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "status": "queued" }, "conversation": { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" }, "replay": false } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `409` `template_not_approved` - `422` `validation_failed` - `429` `rate_limited` ## Estado de un mensaje y la respuesta `GET /v1/c/{slug}/messages/{id}` · Alcances: `conversations:read` · `messages:send_template` · `messages:send_text` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/messages/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "direction": "outbound", "from": null, "type": "template", "text": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "status": "read", "errorCode": null, "createdAt": "2026-10-23T13:02:11.000Z", "sentAt": "2026-10-23T13:02:12.000Z", "deliveredAt": "2026-10-23T13:02:13.000Z", "readAt": "2026-10-23T13:05:40.000Z", "reply": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9", "type": "button", "text": "Quero o cupom", "at": "2026-10-23T13:05:52.000Z" } } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Mensajes de un teléfono `GET /v1/c/{slug}/messages` · Alcances: `conversations:read` Los mensajes de un teléfono desde un momento, los más nuevos primero. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `phone` | string | sí | | | `since` | string (date-time) | sí | | | `channelId` | string (uuid) | no | | | `direction` | uno de `inbound`, `outbound` | no | | | `limit` | integer | no | hasta 100; mínimo 1; default `20` | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/messages" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "messages": [ { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "direction": "outbound", "from": null, "type": "template", "text": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "status": "read", "errorCode": null, "createdAt": "2026-10-23T13:02:11.000Z", "sentAt": "2026-10-23T13:02:12.000Z", "deliveredAt": "2026-10-23T13:02:13.000Z", "readAt": "2026-10-23T13:05:40.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Conversaciones ## Listar conversaciones `GET /v1/c/{slug}/conversations` · Alcances: `conversations:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `view` | uno de `mine`, `team`, `queue`, `waiting_contact`, `snoozed`, `closed`, `mentions`, `all` | no | default `"mine"` | | `limit` | integer | no | hasta 100; mínimo 1; default `50` | | `before` | string (date-time) | no | | | `q` | string | no | hasta 200 caracteres | | `tag` | string (uuid) | no | | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/conversations" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "conversations": [ { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "status": "active", "handler": "human", "priority": "normal", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "unreadCount": 1, "lastMessageAt": "2026-10-23T13:05:52.000Z", "lastInboundAt": "2026-10-23T13:05:52.000Z", "sessionWindowEndsAt": "2026-10-24T13:05:52.000Z", "snoozedUntil": null, "sourceKind": "campaign", "createdAt": "2026-10-23T13:02:11.000Z", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "address": "5548999990001" }, "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "lastMessage": { "body": "Quero o cupom", "direction": "inbound", "type": "button", "status": "received" } } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Abrir una conversación con una plantilla `POST /v1/c/{slug}/conversations` · Alcances: `messages:send_template` Para un contacto existente. `assigneeMemberId` elige quién atiende; sin él, espera la respuesta y entra en la cola del equipo. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `contactId` | string (uuid) | sí | | | `channelId` | string (uuid) | no | | | `templateId` | string (uuid) | sí | | | `parameters` | object | no | default `{}` | | `headerUploadId` | string (uuid) | no | | | `headerLink` | string (uri) | no | hasta 2000 caracteres | | `teamId` | string (uuid) | no | null | | `goal` | string | no | hasta 60 caracteres | | `assigneeMemberId` | string (uuid) | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "templateId": "01a0cad0-0000-7000-8000-000000000002", "parameters": { "1": "Ana" } }' ``` ### Respuesta 201 ```json { "conversation": { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" }, "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `409` `template_not_approved` - `422` `validation_failed` - `429` `rate_limited` ## Ver una conversación `GET /v1/c/{slug}/conversations/{id}` · Alcances: `conversations:read` La conversación con sus mensajes, eventos (asignaciones, transferencias) y, al cerrarse, el desenlace. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/conversations/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "conversation": { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "status": "active", "handler": "human", "priority": "normal", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "unreadCount": 1, "lastMessageAt": "2026-10-23T13:05:52.000Z", "lastInboundAt": "2026-10-23T13:05:52.000Z", "sessionWindowEndsAt": "2026-10-24T13:05:52.000Z", "snoozedUntil": null, "sourceKind": "campaign", "createdAt": "2026-10-23T13:02:11.000Z", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "address": "5548999990001" }, "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "lastMessage": { "body": "Quero o cupom", "direction": "inbound", "type": "button", "status": "received" }, "goal": null, "outcome": null, "closedAt": null }, "messages": [ { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "direction": "outbound", "author": { "kind": "campaign", "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b" }, "type": "template", "body": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "status": "read", "error": null, "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "createdAt": "2026-10-23T13:02:11.000Z" } ], "pinned": [], "events": [] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Enviar un mensaje en la conversación `POST /v1/c/{slug}/conversations/{id}/messages` · Alcances: `messages:send_template` · `messages:send_text` `type: template` con el alcance messages:send_template. `text` y `media` (archivo de `POST /uploads`) piden messages:send_text y la ventana de 24 horas abierta. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `type` | uno de `text` | sí | | | `text` | string | sí | hasta 4096 caracteres | | `replyToProviderMessageId` | string | no | | | `linkPreview` | boolean | no | | | `gateDecisionId` | string (uuid) | no | | | `gateAction` | uno de `accepted`, `edited`, `overridden` | no | | | `templateId` | string (uuid) | sí | | | `parameters` | object | no | default `{}` | | `headerUploadId` | string (uuid) | no | | | `headerLink` | string (uri) | no | hasta 2000 caracteres | | `uploadId` | string (uuid) | sí | | | `caption` | string | no | hasta 1024 caracteres | | `contactIds` | lista de string (uuid) | sí | hasta 10 | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations/:id/messages" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "text", "text": "Oi Ana! Seu pedido saiu para entrega." }' ``` ### Respuesta 202 ```json { "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "status": "queued", "createdAt": "2026-10-23T13:02:11.000Z", "media": null } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `403` `integration_template_only` - `409` `window_closed` - `422` `validation_failed` - `429` `rate_limited` ## Concluir con un desenlace `POST /v1/c/{slug}/conversations/{id}/close` · Alcances: `conversations:write` `outcomeCode` viene de `GET /outcomes`. Con `ifNoReplyHours`, cierra solo si el contacto no responde en ese plazo. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `outcomeCode` | string | sí | hasta 60 caracteres | | `note` | string | no | hasta 4000 caracteres | | `ifNoReplyHours` | integer | no | hasta 720; mínimo 1 | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations/:id/close" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "outcomeCode": "converted", "note": "Fechou o plano anual." }' ``` ### Respuesta 200 ```json { "ok": true, "isSuccess": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Reabrir `POST /v1/c/{slug}/conversations/{id}/reopen` · Alcances: `conversations:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations/:id/reopen" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Subir un archivo `POST /v1/c/{slug}/uploads` · Alcances: `messages:send_text` · `campaigns:write` · `messages:send_template` multipart/form-data con el campo `file` (e `intent`: media, document, audio, sticker). Devuelve el `id` para enviar en un mensaje o poner en el encabezado de una campaña. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud `multipart/form-data`: `file` + `intent` (media, document, audio, sticker). ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/uploads" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 201 ```json { "upload": { "id": "01a3d1e2-f3a4-7b5c-8d6e-7f8091a2b3c4", "mime": "image/jpeg", "sizeBytes": 182340, "filename": "cupom.jpg", "kind": "image", "voice": false, "conversion": null, "durationMs": null, "width": 1080, "height": 1080 } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Números, equipos y etiquetas ## Números de WhatsApp `GET /v1/c/{slug}/channels` · Alcances: `workspace:read` · `campaigns:write` · `messages:send_template` · `templates:read` Los números de la empresa, con la calidad y el límite diario que Meta dio a cada uno. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/channels" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "channels": [ { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei", "phone": "554896429898", "status": "active", "quality": "GREEN", "messagingTier": "TIER_1K", "account": { "id": "01a0cccc-0000-7000-8000-000000000001", "name": "Captei WABA" }, "currency": "BRL", "handling": { "mode": "flow", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "flowId": "01a0d60a-3fc1-7df5-a07c-9769fd5701e6", "assistantId": null }, "createdAt": "2026-09-22T20:14:21.670Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Equipos `GET /v1/c/{slug}/teams` · Alcances: `workspace:read` · `campaigns:write` Para enviar las respuestas de una campaña al equipo correcto (`reply.id`). ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/teams" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "teams": [ { "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "name": "Vendas", "description": null, "isActive": true, "distributionMode": "least_busy", "businessHoursId": null, "members": [ { "id": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "name": "Tayomara Batista", "presence": "online" } ] } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Etiquetas `GET /v1/c/{slug}/tags` · Alcances: `workspace:read` · `contacts:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/tags" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e", "appliesTo": "both", "isActive": true, "contacts": 128, "conversations": 40 } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Desenlaces `GET /v1/c/{slug}/outcomes` · Alcances: `workspace:read` · `conversations:read` · `conversations:write` Cómo puede concluir una conversación (venta, sin interés, resuelto…), con el código usado en `close` y en los avisos. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/outcomes" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "outcomes": [ { "id": "01a0cb22-0000-7000-8000-00000000000a", "code": "converted", "label": { "pt-BR": "Venda", "en": "Sale", "es": "Venta" }, "category": "success", "is_success": true, "requires_note": false, "reopen_allowed": true, "sort": 1 } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Agenda ## Tipos de cita `GET /v1/c/{slug}/appointment-types` · Alcances: `appointments:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointment-types" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "types": [ { "id": "01a1228c-c58f-796a-b3aa-54a953711c71", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "name": "Visita ao imóvel", "durationMin": 60, "agendaName": "Visitas aos imóveis", "timezone": "America/Sao_Paulo", "isActive": true } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Horarios libres `GET /v1/c/{slug}/appointment-types/{id}/slots` · Alcances: `appointments:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `from` | string (date-time) | no | | | `to` | string (date-time) | no | | | `limit` | integer | no | hasta 500; mínimo 1; default `100` | | `contactId` | string (uuid) | no | | | `memberId` | string (uuid) | no | | | `exclude` | string (uuid) | no | | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointment-types/:id/slots" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "timezone": "America/Sao_Paulo", "durationMin": 60, "slots": [ { "start": "2026-10-27T13:00:00.000Z", "end": "2026-10-27T14:00:00.000Z", "memberIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ] } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Citas `GET /v1/c/{slug}/appointments` · Alcances: `appointments:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Parámetros de consulta | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `from` | string (date-time) | no | | | `to` | string (date-time) | no | | | `agendaId` | string (uuid) | no | | | `memberId` | string (uuid) | no | | | `mine` | integer | no | hasta 1; default `0` | | `status` | string | no | | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointments" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "appointments": [ { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Agendar `POST /v1/c/{slug}/appointments` · Alcances: `appointments:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `typeId` | string (uuid) | sí | | | `contactId` | string (uuid) | sí | | | `startsAt` | string (date-time) | sí | | | `conversationId` | string (uuid) | no | null | | `memberId` | string (uuid) | no | null | | `answers` | object | no | | | `notes` | string | no | hasta 2000 caracteres; null | | `force` | boolean | no | | | `confirm` | boolean | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/appointments" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "startsAt": "2026-10-27T13:00:00.000Z", "answers": { "imovel": "AP-2231" } }' ``` ### Respuesta 201 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Ver una cita `GET /v1/c/{slug}/appointments/{id}` · Alcances: `appointments:read` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointments/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" }, "notices": [], "events": [], "history": [] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Reprogramar `POST /v1/c/{slug}/appointments/{id}/reschedule` · Alcances: `appointments:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `startsAt` | string (date-time) | sí | | | `memberId` | string (uuid) | no | null | | `force` | boolean | no | | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/appointments/:id/reschedule" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "startsAt": "2026-10-28T13:00:00.000Z" }' ``` ### Respuesta 200 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Cancelar `POST /v1/c/{slug}/appointments/{id}/cancel` · Alcances: `appointments:write` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `reason` | string | no | hasta 300 caracteres; null | | `notify` | boolean | no | default `true` | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/appointments/:id/cancel" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "Cliente pediu" }' ``` ### Respuesta 200 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "cancelled", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Avisos (webhooks) ## Listar avisos `GET /v1/c/{slug}/webhooks` · Alcances: `webhooks:manage` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/webhooks" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "webhooks": [ { "id": "01a0cb03-417a-7da4-9ae2-70bc321eeef5", "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ], "status": "active", "failureCount": 0, "createdBy": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Crear un aviso `POST /v1/c/{slug}/webhooks` · Alcances: `webhooks:manage` Una dirección de su sistema y los eventos que recibe. El `secret` vuelve una sola vez: guárdelo para verificar las firmas. ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `url` | string (uri) | sí | hasta 2000 caracteres | | `events` | lista de uno de `conversation.opened`, `conversation.closed`, `conversation.assigned`, `conversation.transferred`, `conversation.reopened`, `contact.updated`, `contact.consent_changed`, `message.received`, `message.sent`, `message.delivered`, `message.read`, `message.failed`, `flow.event`, `appointment.booked`, `appointment.rescheduled`, `appointment.cancelled`, `appointment.confirmed`, `appointment.attended`, `appointment.no_show`, `campaign.started`, `campaign.paused`, `campaign.resumed`, `campaign.completed`, `campaign.cancelled`, `campaign.recipient.sent`, `campaign.recipient.delivered`, `campaign.recipient.read`, `campaign.recipient.replied`, `campaign.recipient.failed`, `campaign.recipient.opted_out` | sí | hasta 30 | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/webhooks" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ] }' ``` ### Respuesta 201 ```json { "webhook": { "id": "01a0cb03-417a-7da4-9ae2-70bc321eeef5", "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ], "status": "active", "failureCount": 0, "createdBy": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z" }, "secret": "dsf_whsec_4Jx…" } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Editar un aviso `PATCH /v1/c/{slug}/webhooks/{id}` · Alcances: `webhooks:manage` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Cuerpo de la solicitud | Campo | Tipo | Obligatorio | Detalles | |---|---|---|---| | `url` | string (uri) | no | hasta 2000 caracteres | | `events` | lista de uno de `conversation.opened`, `conversation.closed`, `conversation.assigned`, `conversation.transferred`, `conversation.reopened`, `contact.updated`, `contact.consent_changed`, `message.received`, `message.sent`, `message.delivered`, `message.read`, `message.failed`, `flow.event`, `appointment.booked`, `appointment.rescheduled`, `appointment.cancelled`, `appointment.confirmed`, `appointment.attended`, `appointment.no_show`, `campaign.started`, `campaign.paused`, `campaign.resumed`, `campaign.completed`, `campaign.cancelled`, `campaign.recipient.sent`, `campaign.recipient.delivered`, `campaign.recipient.read`, `campaign.recipient.replied`, `campaign.recipient.failed`, `campaign.recipient.opted_out` | no | hasta 30 | | `status` | uno de `active`, `paused` | no | | ### Ejemplo de solicitud ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/webhooks/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "paused" }' ``` ### Respuesta 200 ```json { "webhook": { "id": "01a0cb03-417a-7da4-9ae2-70bc321eeef5", "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ], "status": "active", "failureCount": 0, "createdBy": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z" } } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Borrar un aviso `DELETE /v1/c/{slug}/webhooks/{id}` · Alcances: `webhooks:manage` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/webhooks/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "ok": true } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Enviar un aviso de prueba `POST /v1/c/{slug}/webhooks/{id}/test` · Alcances: `webhooks:manage` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/webhooks/:id/test" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 202 ```json { "deliveryId": "01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f", "eventId": "01a3c0de-8b22-7c33-9d44-0e55f6677889" } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Entregas recientes `GET /v1/c/{slug}/webhooks/{id}/deliveries` · Alcances: `webhooks:manage` ### Parámetros de la dirección | Campo | Detalles | |---|---| | `slug` | El identificador de la empresa en DoneTalk (el de la clave). | | `id` | El id del registro. | ### Ejemplo de solicitud ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/webhooks/:id/deliveries" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Respuesta 200 ```json { "deliveries": [ { "id": "01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f", "eventId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "eventType": "campaign.recipient.replied", "attempt": 1, "status": "delivered", "responseCode": 200, "responseMs": 84, "nextAttemptAt": null, "createdAt": "2026-10-24T12:04:03.000Z" } ] } ``` ### Errores posibles - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited`