# 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.<clave>`. 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`

