Campanhas API
🎯 Visão Geral
A API de Campanhas Contínuas (Evergreen) permite adicionar contatos individualmente ou em lote a uma campanha ativa, com controle de agendamento por contato — envio imediato ou em data/hora específica.
Características Principais
- ✅ Autenticação via API Key: Todas as requisições usam Workspace API Key
- ✅ Adição de Contatos em Lote: Envie múltiplos contatos em uma única requisição
- ✅ Agendamento por Contato: Cada contato pode ter seu próprio horário de envio (
immediateouabsolute) - ✅ Criação Automática de Contatos: Contatos inexistentes são criados automaticamente via
identifier - ✅ Campos Customizados: Suporte a
cf_xxxxtop-level e objetocustom_fields - ✅ Cancelamento Granular: Cancele o envio de um contato específico sem afetar os demais
- ✅ Inspeção de Mensagens: Consulte status individual de cada mensagem da campanha
🔐 Autenticação
Todas as requisições requerem autenticação via Workspace API Key no header:
X-API-Key: your_workspace_api_key_here
Content-Type: application/json
Como Obter a API Key
-
Acesse o painel administrativo do workspace
Abra o painel administrativo do seu workspace.
-
Vá em Configurações → API Keys
Navegue até a seção de API Keys nas configurações.
-
Gere ou reutilize uma chave
Gere uma nova chave ou copie/use uma existente.
-
Mantenha a chave segura
Não compartilhe a chave e mantenha-a armazenada com segurança.
✅ Validação de Plano/Assinatura
A funcionalidade de Campaigns deve estar habilitada no plano/assinatura do workspace para usar esta API.
Resposta de Erro (quando a funcionalidade não estiver habilitada):
{
"error": "Forbidden",
"message": "Campaigns feature is not available in your current plan. Please upgrade to access this feature."
}
Status Code: 403 Forbidden
Nota: Endpoints de leitura (listar e inspecionar mensagens) podem funcionar mesmo sem a funcionalidade habilitada, permitindo visualizar o estado da campanha. Endpoints que adicionam contatos ou cancelam mensagens requerem a funcionalidade habilitada no plano.
📡 Base URL
https://api.blubash.io/api/v1/campaigns
⚙️ Pré-requisito: Configurar a Campanha na Plataforma
Campanhas Contínuas devem ser criadas e configuradas pelo painel da plataforma antes de usar a API.
Por quê:
- As regras de canal, template e rate limit são validadas no fluxo do produto.
- A configuração via plataforma é mais segura para templates e mensagens.
- Esta API cobre exclusivamente ingestão de audiência e disparo.
Passos recomendados
- Crie uma nova campanha com
kind = EVERGREENna plataforma. - Configure o canal, mensagem/template e regras de rate limit.
- Salve a campanha e copie o
campaignIdgerado.
Use esse campaignId em todos os endpoints abaixo.
🚀 Endpoints
Adicionar Contatos à Audiência
POST /api/v1/campaigns/:campaignId/audience
Adiciona um ou mais contatos à campanha e define o agendamento de envio por contato (array items).
Para adicionar um único contato, envie o array items com apenas um elemento — o endpoint é o mesmo.
Request Body:
{
"default_schedule_timezone": "America/Sao_Paulo",
"items": [
{
"contact_id": "<CONTACT_ID_1>",
"schedule": {
"type": "immediate"
}
},
{
"identifier": "5511999999999",
"name": "João Silva",
"email": "joao@acme.com",
"cf_plano": "pro",
"custom_fields": {
"cf_origem": "api"
},
"schedule": {
"type": "absolute",
"datetime": "2026-03-10T14:30:00.000Z"
}
},
{
"contact_id": "<CONTACT_ID_3>",
"schedule": {
"type": "absolute",
"datetime": "2026-03-11T09:00:00",
"timezone": "America/Sao_Paulo"
}
}
]
}
Campos por item:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
contact_id | string | Condicional¹ | ID de um contato existente no workspace |
identifier | string | Condicional¹ | Identificador do canal (ex: número WhatsApp) |
name | string | Não | Nome do contato (usado na criação) |
email | string | Não | Email do contato (usado na busca e criação) |
custom_fields | object | Não | Campos customizados como objeto |
cf_xxxx | unknown | Não | Campos customizados como chaves top-level |
schedule | object | Não | Configuração de agendamento (padrão: immediate) |
¹ Pelo menos um entre contact_id ou identifier é obrigatório.
Campo raiz default_schedule_timezone (opcional): Fuso horário IANA aplicado a todos os itens com datetime sem offset/Z que não especificaram schedule.timezone.
Resolução e Criação de Contatos
O sistema resolve o contato na seguinte ordem:
- Se
contact_idfor fornecido, usa o contato existente diretamente. - Se
identifierfor fornecido, busca o contato pelo identificador do canal (ex: número WhatsApp normalizado). - Se não encontrado e
emailestiver presente, busca o contato no workspace por email (case-insensitive):- Se encontrado e sem identificador para o canal da campanha, vincula o
identifierao contato. - Se encontrado mas com identificador diferente para o canal, retorna erro
400(evita mesclagem silenciosa de identidades).
- Se encontrado e sem identificador para o canal da campanha, vincula o
- Se ainda não encontrado, cria um novo contato com
name,emaileidentifierfornecidos.
Campos Customizados
Os campos customizados são aceitos nos dois formatos abaixo e mesclados antes de persistir:
- Top-level com prefixo
cf_:"cf_plano": "pro","cf_origem": "api" - Objeto
custom_fields:{ "custom_fields": { "cf_plano": "pro" } }
Agendamento por Contato
immediate: Enfileira e envia o mais rápido possível.absolute: Agenda o envio para um instante específico, armazenado em UTC.
Regras para absolute:
Formato do datetime | Comportamento |
|---|---|
Com Z ou offset numérico (+03:00, -0500) | Interpretado como instante absoluto; timezone é ignorado |
Sem offset (ex: 2026-03-11T09:00:00) | Requer schedule.timezone ou default_schedule_timezone para conversão a UTC |
Se datetime não tiver offset e nenhum fuso horário for fornecido, a requisição retornará erro 400.
Exemplos de schedule:
// Envio imediato
{ "type": "immediate" }
// Instante absoluto com offset embutido (timezone ignorado)
{
"type": "absolute",
"datetime": "2026-03-10T14:30:00.000-03:00"
}
// Horário local sem offset (requer timezone)
{
"type": "absolute",
"datetime": "2026-03-11T09:00:00",
"timezone": "America/Sao_Paulo"
}
// Horário UTC explícito
{
"type": "absolute",
"datetime": "2026-03-10T17:30:00.000Z"
}
Response (sucesso):
{
"items": [
{
"messageId": "<MESSAGE_ID>",
"contactId": "<CONTACT_ID_1>",
"scheduled_at": null,
"scheduled_at_utc": null,
"timezone": null
},
{
"messageId": "<MESSAGE_ID>",
"contactId": "<CONTACT_ID_2>",
"scheduled_at": "2026-03-10T14:30:00.000-03:00",
"scheduled_at_utc": "2026-03-10T17:30:00.000Z",
"timezone": "America/Sao_Paulo"
},
{
"messageId": "<MESSAGE_ID>",
"contactId": "<CONTACT_ID_3>",
"scheduled_at": "2026-03-11T09:00:00.000-03:00",
"scheduled_at_utc": "2026-03-11T12:00:00.000Z",
"timezone": "-03:00"
}
]
}
Campos da resposta por item:
| Campo | Descrição |
|---|---|
messageId | ID da mensagem criada (campaign_message.id) |
contactId | ID do contato resolvido/criado |
scheduled_at | Instante formatado no fuso IANA enviado (ou no offset do datetime). null se imediato |
scheduled_at_utc | Instante canônico sempre em UTC (...Z). null se imediato |
timezone | Nome IANA (ex: America/Sao_Paulo) ou offset (ex: -03:00). null se sem agendamento |
Cancelar Envio de uma Mensagem
POST /api/v1/campaigns/:campaignId/messages/:messageId/cancel
Cancela o envio de uma mensagem específica que ainda está na fila.
Apenas mensagens com status QUEUED podem ser canceladas. Mensagens já enviadas ou em processamento não são afetadas.
Response (sucesso):
{
"id": "<MESSAGE_ID>",
"status": "CANCELLED"
}
Listar Mensagens da Campanha
GET /api/v1/campaigns/:campaignId/messages?limit=50&offset=0
Retorna uma lista paginada das mensagens da campanha com seus respectivos status.
Parâmetros de Query:
limit(opcional): Itens por página (padrão: 50)offset(opcional): Deslocamento para paginação (padrão: 0)
Obter Mensagem por ID
GET /api/v1/campaigns/:campaignId/messages/:messageId
Retorna os detalhes de uma mensagem específica da campanha.
📨 Status de Mensagens
PENDING— Aguardando processamentoQUEUED— Enfileirada para envio (pode ser cancelada)SENDING— Em processo de envioSENT— Enviada com sucessoFAILED— Falha no envioCANCELLED— Cancelada via API
🔁 Fluxo Recomendado
- Configure a campanha Evergreen na plataforma e copie o
campaignId. - Adicione contatos via
POST /api/v1/campaigns/:id/audiencecom o arrayitems. - Para envio imediato, use
schedule.type = immediate. - Para envio agendado, use
schedule.type = absolutecom:- Um instante ISO com
Zou offset numérico, ou - Um
datetimesem offset +timezoneIANA (oudefault_schedule_timezoneno body).
- Um instante ISO com
- Se necessário, cancele um envio específico via
POST /api/v1/campaigns/:id/messages/:messageId/cancel. - Inspecione o status das mensagens via
GET /api/v1/campaigns/:id/messages.
📝 Exemplos Completos
Adicionar Contato com Envio Imediato
curl -X POST https://api.blubash.io/api/v1/campaigns/{campaignId}/audience \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"identifier": "5511999999999",
"name": "Maria Souza",
"schedule": {
"type": "immediate"
}
}
]
}'
Adicionar Contato com Envio Agendado (horário local)
curl -X POST https://api.blubash.io/api/v1/campaigns/{campaignId}/audience \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"default_schedule_timezone": "America/Sao_Paulo",
"items": [
{
"contact_id": "contact_abc123",
"schedule": {
"type": "absolute",
"datetime": "2026-04-01T10:00:00"
}
}
]
}'
Adição em Lote com Agendamentos Mistos
curl -X POST https://api.blubash.io/api/v1/campaigns/{campaignId}/audience \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"default_schedule_timezone": "America/Sao_Paulo",
"items": [
{
"contact_id": "contact_001",
"schedule": { "type": "immediate" }
},
{
"identifier": "5511888887777",
"name": "Pedro Lima",
"cf_plano": "enterprise",
"schedule": {
"type": "absolute",
"datetime": "2026-04-05T09:00:00",
"timezone": "America/Sao_Paulo"
}
},
{
"contact_id": "contact_003",
"schedule": {
"type": "absolute",
"datetime": "2026-04-06T12:00:00.000Z"
}
}
]
}'
Cancelar um Envio Agendado
curl -X POST https://api.blubash.io/api/v1/campaigns/{campaignId}/messages/{messageId}/cancel \
-H "X-API-Key: your_api_key"
Monitorar Mensagens da Campanha
curl -X GET "https://api.blubash.io/api/v1/campaigns/{campaignId}/messages?limit=50&offset=0" \
-H "X-API-Key: your_api_key"
🚨 Erros Comuns
| Status | Mensagem | Causa |
|---|---|---|
400 | Each item must provide contact_id or identifier | Item sem contact_id nem identifier |
400 | Identifier is invalid | identifier vazio ou inválido após normalização |
400 | schedule.timezone (IANA) is required when datetime has no UTC offset | datetime sem offset e sem timezone |
400 | Campaign is not an evergreen campaign | campaignId pertence a uma campanha não-Evergreen |
400 | Cannot add contacts to cancelled or failed campaigns | Campanha com status CANCELLED ou FAILED |
400 | Cannot add contacts while the campaign is paused. Resume the campaign first. | Campanha com status PAUSED |
400 | Contact found by email already has a different identifier for this campaign channel | Conflito de identificador ao buscar contato por email |
400 | Contact does not have a valid channel identifier for this campaign channel | Contato sem identificador válido para o canal da campanha |
403 | Campaigns feature is not available in your current plan | Recurso não habilitado na assinatura |
404 | Campaign not found | campaignId não existe no workspace |
🚨 Códigos de Status HTTP
200— Sucesso201— Criado com sucesso400— Requisição inválida401— Não autorizado (API Key inválida ou não fornecida)403— Proibido (Recurso não disponível na assinatura do workspace)404— Recurso não encontrado