Pular para o conteúdo principal

Chamar a API

Com o access token de uma instalação, o app chama https://api.botzetta.com/plataforma/v1 em nome daquela empresa. A empresa vem do token: não há cabeçalho para escolher outra.

GET https://api.botzetta.com/plataforma/v1/usuarios
Authorization: Bearer <access token da empresa>
Accept: application/json
{ "dados": [{ "id": 7, "nome": "Ana Souza", "perfil": "admin" }] }

Cada endpoint, com parâmetros, respostas e o escopo que exige, está na Referência da API. Neste guia, cada endpoint citado leva o operationId da especificação OpenAPI entre parênteses, com link para a página dele, por exemplo GET /usuarios (getUsuarios).

Convenções​

ItemComo é
FormatoJSON (upload de mídia em multipart/form-data)
NomesRecursos no plural, em português (/pessoas, /oportunidades); campos em camelCase
DatasISO 8601, em UTC
Paginação?pagina=1&porPagina=50 (máximo 200) → { dados, pagina, porPagina, total }
Histórico de mensagensPor cursor: ?limite= e ?cursor= → { dados, proximoCursor }. Repasse o proximoCursor como veio; null é o fim
RastreioMande X-Request-Id e ele volta na resposta. Inclua-o quando falar com o suporte
CompatibilidadeMudanças na v1 são aditivas: ignore campos que não conhece

Erros​

Todo erro tem o mesmo formato:

{ "error": "ERR_ESCOPO_INSUFICIENTE", "message": "texto em português" }

Trate pelo código (error), não pela mensagem. Os mais comuns:

CódigoHTTPO que fazer
ERR_TOKEN_INVALIDO401Renove o token e repita uma vez. Se voltar, a instalação acabou
ERR_APP_NAO_HABILITADO403A empresa desinstalou o app, o plano não permite mais ou o app foi suspenso. Pare de chamar para essa empresa
ERR_ESCOPO_INSUFICIENTE403O escopo não está entre os efetivos. Peça na próxima versão; a empresa precisa consentir
ERR_EMPRESA_DIVERGENTE400Você mandou X-Botzetta-Empresa diferente da empresa do token. Não mande o cabeçalho
ERR_ASSINATURA_VENCIDA / ERR_ASSINATURA_BLOQUEADA403A assinatura da empresa está pendente: escritas são recusadas, leituras continuam
ERR_NAO_ENCONTRADO404Não existe ou é de outra empresa (a API não distingue)
ERR_VALIDACAO400Corpo ou consulta inválidos; message diz o campo
ERR_CONFLITO409Conflito de estado. Pode tentar de novo depois
ERR_OPERACAO_RECUSADA403Uma regra do Botzetta recusou a operação. Não é token nem escopo: não renove
ERR_LIMITE_REQUISICOES429Espere o Retry-After (segundos)
ERR_INTERNO500Tente de novo com espera crescente

A lista completa fica em Erros, na Referência da API.

Limites​

Detalhes e cabeçalhos em Limites e idempotência.

  • 600 requisições por minuto por app e por empresa. Acima disso, 429 ERR_LIMITE_REQUISICOES com Retry-After.
  • Envio de mensagem para número avulso (fora do cadastro de pessoas): até 200 por dia por app e empresa (429 ERR_LIMITE_ENVIO_AVULSO). Envios por pessoaId não contam: prefira-os.
  • Prefira webhooks a consultar a API em intervalos. Para sincronizar, use os filtros atualizadoDesde das listagens de tickets e oportunidades.

Idempotência​

Todo POST que cria um registro ou envia uma mensagem exige o cabeçalho Idempotency-Key (até 7 dias, por empresa e por rota):

POST https://api.botzetta.com/plataforma/v1/mensagens
Authorization: Bearer <access token da empresa>
Content-Type: application/json
Idempotency-Key: pedido-9812-confirmacao

{ "whatsappId": 12, "destino": { "pessoaId": 345 }, "conteudo": { "texto": "Seu pedido 9812 foi confirmado." } }
  • Mesma chave e mesmo corpo → a mesma resposta, sem repetir o efeito, com Idempotency-Replay: true.
  • Mesma chave com corpo diferente → 422 ERR_IDEMPOTENCY_KEY_REUTILIZADA.
  • Chave ainda em processamento → 409 ERR_REQUISICAO_EM_ANDAMENTO.
  • Respostas 5xx, 409 e 429 não são gravadas: a mesma chave serve para tentar de novo.

Derive a chave do seu evento de negócio (ex.: pedido-9812-confirmacao), nunca do número da tentativa: se a primeira tentativa der timeout depois que a mensagem saiu, a segunda recebe o replay em vez de enviar de novo. PATCH, PUT e ações de estado (mover, ganhar, perder, reabrir, opt-out) não exigem a chave, porque repetir dá o mesmo resultado.

Enviar mensagens​

POST /mensagens (postMensagens, escopo mensagens:enviar) envia pelo WhatsApp da empresa:

  • destino: { "pessoaId": 345 } (recomendado), { "contatoId": 77 } (contato do atendimento, inclusive grupo) ou { "numero": "5511999990000" };
  • pessoa ou número com opt-out → 422 ERR_DESTINO_OPT_OUT. É resultado final (LGPD): não tente de novo e mostre ao cliente quem ficou de fora;
  • 409 ERR_WHATSAPP_DESCONECTADO pode ser tentado de novo mais tarde; 422 ERR_DESTINO_SEM_WHATSAPP não.

As conexões de WhatsApp da empresa estão em GET /whatsapps (getWhatsapps).

Exemplo: ler pessoas​

async function listarPessoas(accessToken, pagina = 1) {
const resp = await fetch(`https://api.botzetta.com/plataforma/v1/pessoas?pagina=${pagina}&porPagina=100`, {
headers: { Authorization: `Bearer ${accessToken}`, Accept: "application/json" }
});
const corpo = await resp.json();
if (!resp.ok) throw new Error(`${corpo.error}: ${corpo.message}`);
return corpo; // { dados: [{ id, nome, … }], pagina, porPagina, total }
}

GET /pessoas (getPessoas) exige pessoas:ler; o detalhe com os contatos de WhatsApp é GET /pessoas/{id} (getPessoasId).

Dados pessoais

Tudo o que o app lê é dado pessoal de clientes da empresa (LGPD). Guarde só o necessário, não ponha em logs e apague quando a empresa desinstalar o app. Veja Obrigações.