Pular para o conteúdo principal

Instalação e OAuth

A instalação é o OAuth 2.0 authorization code com PKCE (S256). O resultado é um par de tokens daquela empresa.

Seu backend Botzetta (admin logado) API da Plataforma
1. GET /botzetta/instalar
gera verifier, challenge e state
302 → <Botzetta>/apps/instalar?… ──► 2. tela de consentimento
3. admin autoriza
4. GET <redirect_uri>?code&state ◄──── 302 de volta
5. confere o state
POST /plataforma/v1/oauth/token ─────────────────────────────────────► 6. access + refresh da empresa

1. URL de instalação​

É o endpoint do seu backend cadastrado como URL de instalação (o portal e os clientes abrem ele). A cada acesso:

  1. gere o code_verifier: 32 bytes aleatórios em base64url (43 caracteres);
  2. calcule o code_challenge = base64url(SHA-256(code_verifier)), sem =;
  3. gere um state aleatório;
  4. guarde verifier e state do lado do servidor por 10 minutos, e amarre o state a este navegador (cookie HttpOnly);
  5. redirecione para a tela de consentimento:
GET <URL do Botzetta>/apps/instalar
?client_id=bzt_meuapp_…
&redirect_uri=https://meuapp.exemplo.com/botzetta/callback
&response_type=code
&state=<state>
&code_challenge=<challenge>
&code_challenge_method=S256
import { createHash, randomBytes } from "node:crypto";

const verifier = randomBytes(32).toString("base64url");
const challenge = createHash("sha256").update(verifier).digest("base64url");
const state = randomBytes(24).toString("base64url");

2. Consentimento (no Botzetta)​

O Botzetta pede login, se preciso, e mostra ao admin o app, a empresa, os escopos com rótulo e risco, o seu e-mail de suporte e a sua política de privacidade. O consentimento é tudo ou nada.

O adminO Botzetta redireciona para
Autoriza<redirect_uri>?code=bzc_…&state=<state>
Cancela<redirect_uri>?error=access_denied&state=<state>

Link inválido (client_id desconhecido, redirect_uri fora do cadastro, PKCE ausente) não redireciona: a tela mostra o erro. Também não instala se o plano da empresa não inclui apps de parceiros, se o app privado já atingiu o limite de empresas ou se a versão ativa ainda depende de revisão.

3. Callback: trocar o código​

No redirect_uri, confira o state (o mesmo que você guardou e o do cookie) antes de qualquer coisa. Depois troque o código em POST /plataforma/v1/oauth/token (postOauthToken):

POST https://api.botzetta.com/plataforma/v1/oauth/token
Content-Type: application/json

{
"grant_type": "authorization_code",
"code": "bzc_…",
"redirect_uri": "https://meuapp.exemplo.com/botzetta/callback",
"code_verifier": "<verifier>",
"client_id": "bzt_meuapp_…",
"client_secret": "bzcs_…"
}
{
"access_token": "eyJhbGciOiJSUzI1NiIs…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "bzr_…",
"escopos": ["usuarios:ler", "pessoas:ler"],
"companyId": 88,
"instalacaoId": 412
}

O endpoint aceita JSON ou application/x-www-form-urlencoded. Guarde os tokens por companyId, cifrados, junto com instalacaoId e a validade (agora + expires_in).

Regras do código: uso único, vale 10 minutos, o redirect_uri tem de ser o mesmo da autorização e o code_verifier tem de conferir. Errar o PKCE ou o redirect invalida o código. Reusar um código já trocado revoga os tokens daquela instalação.

4. Renovar o access token​

O access token vale 1 hora. Renove com o refresh:

POST https://api.botzetta.com/plataforma/v1/oauth/token
Content-Type: application/json

{ "grant_type": "refresh_token", "refresh_token": "bzr_…", "client_id": "bzt_meuapp_…", "client_secret": "bzcs_…" }

A resposta tem o mesmo formato, com um refresh novo. O refresh é rotativo:

  • salve o par novo antes de usar o access token novo. Se a gravação falhar depois de o Botzetta ter rotacionado, o refresh antigo já não vale;
  • reusar um refresh já usado revoga a família inteira (ERR_OAUTH_REFRESH_INVALIDO) e o admin precisa reinstalar. A exceção são 30 segundos depois do uso: aí o Botzetta entende como renovação concorrente e recusa sem revogar. Releia o par salvo e use o novo;
  • faça uma renovação por empresa por vez (trava no banco ou fila por companyId);
  • renove um pouco antes de expirar (ex.: faltando 1 minuto), ou quando uma chamada voltar 401.

O refresh vale 90 dias. Uma empresa que não usa o app por mais tempo precisa reinstalar.

5. Revogar​

Para encerrar a integração com uma empresa do seu lado, revogue o refresh. A resposta é sempre 200 (não revela se o token existia):

POST https://api.botzetta.com/plataforma/v1/oauth/revogar
Content-Type: application/json

{ "token": "bzr_…", "client_id": "bzt_meuapp_…", "client_secret": "bzcs_…" }

Desinstalação e reinstalação​

Quando a empresa desinstala o app no Botzetta:

  • todos os refresh da instalação são revogados e o access token deixa de valer (403 ERR_APP_NAO_HABILITADO);
  • o app recebe o webhook app.desinstalado;
  • um token emitido antes da desinstalação nunca volta a valer, mesmo que a empresa reinstale: a reinstalação passa pelo fluxo inteiro de novo e gera tokens novos.

Erros do OAuth​

O formato é o da API ({ "error": "ERR_…", "message": "…" }), não o do RFC 6749.

CódigoHTTPQuando
ERR_CREDENCIAIS_INVALIDAS401client_id ou client_secret errados ou revogados
ERR_OAUTH_PARAMETRO400Parâmetro faltando ou inválido
ERR_OAUTH_CODIGO_INVALIDO400Código expirado, já usado, ou PKCE/redirect que não conferem
ERR_OAUTH_REFRESH_INVALIDO400Refresh inválido, expirado, revogado ou reusado
ERR_GRANT_NAO_PERMITIDO400grant_type que apps de parceiro não usam (client_credentials)
ERR_LIMITE_REQUISICOES429Muitas chamadas. Respeite o Retry-After

O /oauth/token tem limites por IP e por client_id. Renovações (refresh_token) têm um teto próprio de 300 por minuto, pensado para quem renova os tokens de muitas empresas.