Campanhas

Liste campanhas, acompanhe métricas de entrega, adicione destinatários e controle o ciclo de vida (iniciar, pausar, retomar). Alguns endpoints (adicionar destinatários e relatório consolidado) exigem plano Enterprise.

escopo: campaigns:read

Lista as campanhas da empresa. Filtro: ?status=draft,sending

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": [
    {
      "id": "<uuid>",
      "name": "Promoção de Julho",
      "status": "sending",
      "type": "promotional",
      "total_recipients": 100,
      "messages_sent": 40,
      "messages_delivered": 38,
      "messages_failed": 1,
      "messages_replied": 5,
      "created_at": "2026-07-10T10:00:00.000Z",
      "started_at": "2026-07-10T10:05:00.000Z",
      "completed_at": null
    }
  ]
}

Exemplo

curl
curl -s -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns
escopo: campaigns:read

Status e métricas de entrega de uma campanha.

  • As três taxas vêm da mesma fonte da aba Campanhas de /relatorios, com a campanha inteira (todos os destinatários, sem janela de período): percentual de 0 a 100 com 1 casa decimal, denominador `sent` (destinatários com envio registrado).
  • `delivered` conta quem tem confirmação de entrega OU de leitura; `read` conta quem tem confirmação de leitura; `replied` conta quem respondeu à campanha.
  • Os campos `messages_*` e `*_cost_usd` são os contadores gravados na própria campanha e podem divergir das taxas; para números consistentes entre si use `/api/v1/campaigns/{id}/report`.
  • Quando o cálculo das taxas está indisponível, a campanha vem normalmente e `delivery_rate`, `read_rate` e `reply_rate` vêm `null` — trate `null` como "sem dado agora", nunca como zero.

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "id": "<uuid>",
    "name": "Promoção de Julho",
    "status": "sending",
    "type": "promotional",
    "total_recipients": 100,
    "messages_sent": 90,
    "messages_delivered": 85,
    "messages_read": 50,
    "messages_failed": 2,
    "messages_replied": 10,
    "estimated_cost_usd": 4.5,
    "actual_cost_usd": 3.9,
    "created_at": "2026-07-10T10:00:00.000Z",
    "started_at": "2026-07-10T10:05:00.000Z",
    "completed_at": null,
    "paused_at": null,
    "cancelled_at": null,
    "delivery_rate": 94.4,
    "read_rate": 55.6,
    "reply_rate": 11.1
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
500PROVIDER_ERRORErro interno — esta família de rotas (legada) usa o código PROVIDER_ERROR no 500

Exemplo

curl
curl -s -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns/{id}
escopo: campaigns:write

Inicia uma campanha em rascunho.

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "campaign_id": "<uuid>",
    "status": "sending",
    "total_recipients": 100
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
400INVALID_STATUSCampanha não está em rascunho (draft)
400MISSING_FIELDCampanha sem produto vinculado ou sem destinatários
500PROVIDER_ERRORErro interno — esta família de rotas (legada) usa o código PROVIDER_ERROR no 500

Exemplo

curl
curl -s -X POST -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns/{id}/start
escopo: campaigns:write

Pausa uma campanha em envio.

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "campaign_id": "<uuid>",
    "status": "paused"
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
400INVALID_STATUSCampanha não está em envio (sending)
500PROVIDER_ERRORErro interno — esta família de rotas (legada) usa o código PROVIDER_ERROR no 500

Exemplo

curl
curl -s -X POST -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns/{id}/pause
escopo: campaigns:write

Retoma uma campanha pausada.

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "campaign_id": "<uuid>",
    "status": "sending"
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
400INVALID_STATUSCampanha não está pausada
500PROVIDER_ERRORErro interno — esta família de rotas (legada) usa o código PROVIDER_ERROR no 500

Exemplo

curl
curl -s -X POST -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns/{id}/resume
escopo: campaigns:read

Lista paginada de destinatários. Parâmetros: ?page=1&limit=50&status=sent

  • Quando houver falha, `delivery_error` traz `{ code, description }`: use `code` para automação e `description` para exibir o significado em português. `error_message`/`failure_reason` continuam com o retorno bruto do provedor apenas por compatibilidade.
  • Ordenação: `sent_at` decrescente, destinatários ainda não enviados por último, com desempate por `id` — a ordem entre páginas é estável. Durante um disparo em andamento, destinatários recém-enviados sobem para o topo e podem deslocar as páginas seguintes.

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": [
    {
      "id": "<uuid>",
      "status": "failed",
      "scheduled_send_at": "2026-07-10T10:05:00.000Z",
      "attempt_count": 1,
      "sent_at": "2026-07-10T10:06:00.000Z",
      "delivered_at": null,
      "read_at": null,
      "failure_reason": "[131049] This message was not delivered to maintain healthy ecosystem engagement.",
      "delivery_error": {
        "code": "131049",
        "description": "Meta limitou: usuário recebeu marketing demais (de várias empresas)"
      },
      "contact_name": "João Silva",
      "contact_phone": "5548999990000"
    }
  ],
  "total": 100,
  "page": 1,
  "limit": 50
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa

Exemplo

curl
curl -s -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns/{id}/recipients
escopo: campaigns:writeEnterprise

Adiciona destinatários a uma campanha em rascunho/agendada (por contact_ids e/ou por telefone; máx. 100 por chamada).

  • Informe ao menos um contact_id ou um contato por telefone; o total combinado deve ser ≤ 100.

Modelo de envio

Corpo da requisição
{
  "contact_ids": [
    "<uuid>"
  ],
  "contacts": [
    {
      "phone": "5548999990000",
      "name": "João Silva"
    }
  ]
}

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "added": 5,
    "skipped_blocked": 0,
    "skipped_opted_out": 1,
    "already_present": 2,
    "not_found": 0,
    "total_recipients": 105
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
409CAMPAIGN_LOCKEDCampanha fora de draft/scheduled (inclui scheduled já vencido) — retorna o "status" atual

Exemplo

curl
curl -s -X POST -H "Authorization: Bearer <sua-key>" -H "Content-Type: application/json" \
  -d '{"contact_ids":["<uuid>"],"contacts":[{"phone":"5548999990000","name":"João Silva"}]}' \
  https://www.prosalab.com/api/v1/campaigns/{id}/recipients
escopo: campaigns:readEnterprise

Relatório consolidado: métricas, taxas e breakdown por status de destinatário.

  • `metrics` é a campanha inteira, na mesma fonte da aba Campanhas de /relatorios: todos os destinatários, sem janela de período.
  • `sent` = destinatários com envio registrado; `delivered` = com confirmação de entrega OU de leitura; `read` = com confirmação de leitura; `replied` = que responderam à campanha; `failed` = com status de falha e sem confirmação de entrega nem de leitura.
  • Taxas (`delivery_rate`, `read_rate`, `reply_rate`) em percentual de 0 a 100 com 1 casa decimal, todas sobre `sent`.
  • `costs` segue as mesmas regras do bloco `costs` de `/api/v1/reports/campaigns`, sempre em R$ (BRL).
  • `recipients_by_status` é o estado da fila de envio: contagem exata por status, sempre com os nove status (`pending`, `queued`, `processing`, `sent`, `delivered`, `read`, `failed`, `skipped`, `cancelled`). O status quase nunca avança com o recibo da Meta, por isso `delivered` e `read` aqui não coincidem com `metrics` — para resultado use `metrics`.

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "campaign": {
      "id": "<uuid>",
      "name": "Promoção de Julho",
      "status": "sending",
      "created_at": "2026-07-10T10:00:00.000Z",
      "started_at": "2026-07-10T10:05:00.000Z",
      "completed_at": null
    },
    "metrics": {
      "recipients": 100,
      "sent": 90,
      "delivered": 85,
      "read": 50,
      "replied": 10,
      "failed": 2,
      "delivery_rate": 94.4,
      "read_rate": 55.6,
      "reply_rate": 11.1,
      "costs": {
        "amount": null,
        "known_amount": 31.2,
        "coverage": 0.9444,
        "sent": 90,
        "resolved": 80,
        "free": 0,
        "not_billed": 0,
        "void": 0,
        "not_applicable": 0,
        "historical": 0,
        "pending": 5,
        "status": "partial",
        "basis": [
          "usd_rate_x_ptax_venda"
        ]
      }
    },
    "recipients_by_status": [
      {
        "status": "pending",
        "count": 5
      },
      {
        "status": "queued",
        "count": 3
      },
      {
        "status": "processing",
        "count": 0
      },
      {
        "status": "sent",
        "count": 88
      },
      {
        "status": "delivered",
        "count": 0
      },
      {
        "status": "read",
        "count": 0
      },
      {
        "status": "failed",
        "count": 2
      },
      {
        "status": "skipped",
        "count": 2
      },
      {
        "status": "cancelled",
        "count": 0
      }
    ]
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
422PERIOD_TOO_LARGEO cálculo da campanha excedeu o tempo limite da consulta; tente novamente mais tarde
500INTERNAL_ERRORErro interno

Exemplo

curl
curl -s -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/campaigns/{id}/report
escopo: campaigns:write

Adiciona contatos (por nome e telefone) e inicia a campanha em um único request.

Modelo de envio

Corpo da requisição
{
  "contacts": [
    {
      "name": "João Silva",
      "phone": "5548999990000"
    }
  ]
}

Resposta (200)

Corpo da resposta
{
  "success": true,
  "data": {
    "campaign_id": "<uuid>",
    "campaign_status": "sending",
    "total_recipients": 105,
    "imported": 5,
    "skipped": 0,
    "errors": []
  }
}

Erros

StatusCódigoQuando ocorre
404NOT_FOUNDCampanha não existe ou pertence a outra empresa
400INVALID_STATUSCampanha cancelada ou com falha
400MISSING_FIELDSem produto vinculado, sem contatos válidos ou lote > 100
500PROVIDER_ERRORErro interno — esta família de rotas (legada) usa o código PROVIDER_ERROR no 500

Exemplo

curl
curl -s -X POST -H "Authorization: Bearer <sua-key>" -H "Content-Type: application/json" \
  -d '{"contacts":[{"name":"João Silva","phone":"5548999990000"}]}' \
  https://www.prosalab.com/api/v1/campaigns/{id}/send
Campanhas — Prosalab Developers