Skip to content

Autenticação ​

Toda chamada ao /v1 leva uma chave de API no header Authorization:

Authorization: Bearer edu_<prefixo>_<segredo>

A empresa vem da própria chave. Não existe parâmetro de empresa em nenhuma rota — uma chave enxerga exatamente uma empresa, e nenhum dado de outra.

Escopos ​

Os escopos da chave são as mesmas permissões que o Edusati usa no painel. Ao criar a chave você escolhe quais liberar.

Quem pode criar a chave

Uma chave enxerga a instituição inteira — ela não tem recorte próprio por unidade ou por programa. Por isso só quem já tem acesso à instituição inteira consegue emitir uma. Se a pessoa que cuida da integração enxerga apenas uma unidade (ou apenas alguns programas), o painel recusa a criação: peça a chave a quem tem acesso total.

EscopoO que abre
surveys:readGET /forms, GET /forms/{id}
reports:readGET /forms/{id}/responses, GET /responses/{id}, GET /forms/{id}/stats
invites:readGET /forms/{id}/invites
invites:writePOST /forms/{id}/invites, POST /invites/{id}/revoke
invites:sendPOST /forms/{id}/invites/send

GET /v1/me funciona com qualquer chave válida, sem escopo.

Por que invites:send é separado de invites:write

Enviar consome a quota mensal de mensagens da empresa — ou seja, custa dinheiro. Uma integração que só precisa gerar links (para distribuir pelo seu próprio sistema) deve receber invites:write e nada mais.

Peça o mínimo. Uma chave nunca pode ter mais permissões do que quem a criou, e escopo a menos é o tipo de erro que aparece na hora — escopo a mais é o tipo que só aparece no incidente.

Chamar uma rota sem o escopo devido responde 403 FORBIDDEN. Para descobrir o que a sua chave tem, consulte GET /v1/me.

Limite de requisições ​

O limite é por chave, não por IP:

  • Padrão: 60 requisições por minuto. O valor efetivo da sua chave vem em apiKey.rateLimitPerMin no GET /v1/me, e pode ser ajustado pelo administrador da conta.
  • Estourar responde 429 com error.code: RATE_LIMITED e o header retry-after em segundos.

Contar por chave é o que torna o limite previsível para você: um servidor atrás de NAT não divide a cota com terceiros, e trocar de IP não zera nem multiplica nada.

js
async function chamar(url, opts) {
  const res = await fetch(url, opts);
  if (res.status === 429) {
    const espera = Number(res.headers.get('retry-after') ?? 60);
    await new Promise((r) => setTimeout(r, espera * 1000));
    return chamar(url, opts);          // uma retentativa após a janela
  }
  return res;
}

Respeite o retry-after em vez de tentar de novo imediatamente — repetir na mesma janela só gasta o limite da janela seguinte.

Rotas caras

GET /forms/{id}/stats varre as respostas do período para agregar. Ela tem um teto próprio, mais apertado que o da chave. Use-a sob demanda (ao abrir um painel, num relatório diário), nunca em laço.

Formato da chave ​

edu_a1b2c3d4e5f60718_9f8e7d6c5b4a39281706f5e4d3c2b1a0…
    └──── prefixo ───┘└──────────── segredo ───────────┘

O prefixo é público: é o que aparece na lista de chaves do painel e o que permite identificar qual chave é qual. O segredo só existe na resposta da criação — guardamos apenas um hash dele, então nem nós conseguimos exibi-lo de novo.

Na prática, isso significa que o prefixo é seguro para colocar em log (chave a1b2c3d4e5f60718 falhou), e o token inteiro nunca é.

Ciclo de vida ​

Revogar é o caminho normal de desligar uma integração: a chave para de funcionar imediatamente e a linha continua na lista, com o histórico de uso. Excluir remove a chave da lista. Os dois barram a autenticação na hora.

expiresAt é opcional e útil para acessos temporários (uma consultoria, uma migração). Depois da data, a chave responde 401.

lastUsedAt mostra quando a chave foi usada pela última vez — bom para descobrir chaves esquecidas antes de removê-las. É atualizado com atraso de até 5 minutos.

Trocar uma chave sem downtime ​

Não há rotação automática. O procedimento seguro é:

  1. Crie a chave nova com os mesmos escopos
  2. Faça o deploy da sua aplicação com o token novo
  3. Confirme pelo lastUsedAt da chave antiga que ela parou de ser usada
  4. Revogue a antiga

Erros de autenticação ​

SituaçãoResposta
Header ausente ou malformado401 · Invalid API key
Chave inexistente ou segredo errado401 · Invalid API key
Chave revogada ou excluída401 · API key revoked
Chave vencida (expiresAt)401 · API key expired
Chave válida, sem o escopo da rota403 · FORBIDDEN

Formato inválido, chave inexistente e segredo errado dão a mesma resposta de propósito — distinguir permitiria descobrir quais prefixos existem por tentativa e erro.

Boas práticas ​

  • Nunca no cliente. A chave é credencial de servidor. Em código de browser ou app móvel, ela é pública na prática — qualquer pessoa a extrai do bundle.
  • Uma chave por integração, não uma compartilhada. É o que permite revogar uma sem derrubar as outras, e o que faz o lastUsedAt significar alguma coisa.
  • No cofre de segredos, não no repositório. Se um token for para o Git, revogue-o: o histórico do Git não esquece.
  • Trate 401 como fatal, não como transitório. Repetir com uma chave revogada nunca vai funcionar; alerte alguém em vez de entrar em laço.

Documentação da API pública do Edusati