Autenticação
Toda chamada da API leva a chave no cabeçalho Authorization, no formato Bearer:
Authorization: Bearer fh_live_sua_chaveEsse é o único jeito aceito. Chave em parâmetro de consulta não é lida, porque endereço com chave dentro vaza em log de proxy, em histórico de navegador e no cabeçalho Referer.
Formato da chave
Seção intitulada “Formato da chave”fh_live_ + 43 caracteres de corpo + 6 de verificaçãoSão 57 caracteres no total. Exemplo do que o painel mostra na lista de chaves: fh_live_7Qx4Kd, os 14 primeiros caracteres. É esse trecho que GET /public/v1/me devolve em key.prefix, e é por ele que você sabe qual chave está em uso sem precisar da chave inteira.
Os 6 últimos caracteres são um verificador calculado a partir do resto. A API usa o verificador para recusar chave digitada errada sem nem ir ao banco.
O verificador também deixa o formato fácil de procurar: uma regra que case fh_live_ seguido de 43 caracteres de corpo e 6 de verificação acerta quase sempre. Essa regra é você quem configura, na varredura de segredo do seu provedor de git ou na sua própria esteira. Nenhum provedor reconhece este formato sozinho.
O prefixo fh_test_ fica reservado e nunca é emitido. Não existe chave de teste porque não existe ambiente de teste.
Chaves emitidas na primeira versão da API, sem os 6 caracteres de verificação, continuam valendo.
Idioma das mensagens
Seção intitulada “Idioma das mensagens”O cabeçalho Accept-Language escolhe o idioma do campo message do erro. São aceitos pt-BR (padrão), en e es, e o peso q é respeitado. O campo code é sempre o mesmo, em inglês: programe por ele.
Toda recusa de autenticação responde a mesma coisa
Seção intitulada “Toda recusa de autenticação responde a mesma coisa”Quando a API não aceita a chave, a resposta é sempre esta, com HTTP 401:
{ "error": { "type": "authentication_error", "code": "api_key_invalid", "message": "Chave de API inválida, revogada ou expirada.", "request_id": "0a8c1f2e-3b4d-4c5f-9a6b-7c8d9e0f1a2b", "doc_url": "https://docs.fatureihoje.com/errors#api_key_invalid" }}Ela é igual para todos estes casos:
- cabeçalho
Authorizationausente ou fora do formato Bearer; - chave com formato inválido, ou com o verificador errado;
- chave que não existe;
- chave revogada;
- chave expirada;
- chave cujo membro foi suspenso, removido ou teve o acesso desativado;
- empresa inativa;
- IP de origem fora da lista de IPs permitidos da chave.
Isso é de propósito. Uma resposta diferente por motivo diria a quem está testando chaves ao acaso quando ele acertou uma chave real e errou só o IP. O custo é seu, na hora de depurar, e o resto desta página existe para compensar isso.
Como descobrir o motivo
Seção intitulada “Como descobrir o motivo”A resposta não diz, mas o painel diz. Confira nesta ordem:
- O cabeçalho.
Authorization: Bearer <chave>, um espaço só, sem aspas em volta da chave. - A chave. Copiada inteira, sem espaço nem quebra de linha no fim. Compare os 14 primeiros caracteres com o prefixo que o painel mostra.
- O estado da chave. O painel marca cada chave como Ativa, Em rotação, Expirada ou Revogada.
- A lista de IPs. Se a chave tem lista, o IP de saída do seu servidor precisa estar nela.
- O endereço. Só
api.fatureihoje.comresponde/public/v1. O host do painel devolve 404. - O registro de uso. No menu da chave, em Ver uso. Ele mostra as chamadas dos últimos 30 dias com data, método, rota, status, duração, IP e
request_id. Chamada recusada entra no registro quando a API reconhece de qual chave se trata: chave revogada, expirada, rotacionada, membro suspenso, usuário desativado ou IP fora da lista. É assim que você descobre tanto o IP errado quanto uma chave sua batendo de um lugar em que ela não deveria estar.
Os dois do meio são os menos óbvios, e por isso valem o aviso: suspender um membro da equipe ou desativar o usuário dele derruba a integração que a chave dele representa, sem nenhum outro sinal. Se uma integração parou no mesmo dia em que alguém saiu da equipe, é quase sempre isso.
Duas recusas não geram linha nenhuma: token que não é de nenhuma chave, porque não há empresa a quem atribuir a tentativa, e empresa inativa, porque nesse caso o painel inteiro está bloqueado e o problema não é a chave. Se nada aparece em Ver uso, comece conferindo essas duas.
Guarde o request_id
Seção intitulada “Guarde o request_id”Toda resposta traz o cabeçalho Request-Id, e o corpo de erro repete o valor em request_id. É por ele que o suporte acha a chamada.
curl -i https://api.fatureihoje.com/public/v1/me \ -H "Authorization: Bearer $FH_API_KEY"-i imprime os cabeçalhos da resposta junto com o corpo.
const res = await fetch('https://api.fatureihoje.com/public/v1/me', { headers: { Authorization: `Bearer ${process.env.FH_API_KEY}` },});
console.log(res.status, res.headers.get('request-id'));<?php
$requestId = null;
$ch = curl_init('https://api.fatureihoje.com/public/v1/me');curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('FH_API_KEY')], CURLOPT_HEADERFUNCTION => function ($ch, $header) use (&$requestId) { if (stripos($header, 'request-id:') === 0) { $requestId = trim(substr($header, strlen('request-id:'))); }
return strlen($header); },]);
curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $status, ' ', $requestId, PHP_EOL;import osimport urllib.errorimport urllib.request
request = urllib.request.Request( "https://api.fatureihoje.com/public/v1/me", headers={"Authorization": f"Bearer {os.environ['FH_API_KEY']}"},)
try: with urllib.request.urlopen(request) as response: print(response.status, response.headers["Request-Id"])except urllib.error.HTTPError as failure: print(failure.code, failure.headers["Request-Id"])Não repita a chamada em laço
Seção intitulada “Não repita a chamada em laço”A API conta as falhas de autenticação por IP de origem. Passando de 60 falhas por minuto, as chamadas seguintes daquele IP recebem 429 com o cabeçalho Retry-After, mesmo que a chave esteja certa. Quem usa a chave certa nunca gasta esse orçamento.
Ao receber 401, pare e conserte a configuração. Repetir a mesma chamada errada só atrasa a volta.
IPs permitidos
Seção intitulada “IPs permitidos”Cada chave aceita uma lista de até 20 endereços ou faixas. Lista vazia aceita qualquer IP.
Formatos aceitos, IPv4 e IPv6:
198.51.100.7198.51.100.0/242001:db8::12001:db8::/32Endereço solto vale como a máquina exata (/32 no IPv4, /128 no IPv6).
A máscara é aplicada ao salvar. Se você digitar 203.0.113.5/24, a entrada é guardada como 203.0.113.0/24, porque é isso que a faixa significa. O painel mostra o valor já normalizado: o que está na tela é exatamente o que vale.
Entrada inválida não é aceita nem descartada em silêncio: o painel recusa o formulário. Descartar em silêncio poderia esvaziar a lista, e lista vazia libera qualquer IP.
Chamada vinda de IP fora da lista responde o mesmo 401 de chave inválida, e a tentativa aparece em Ver uso com o IP que chegou.
Expiração
Seção intitulada “Expiração”Na criação você escolhe entre não expirar, 30 dias, 90 dias ou 1 ano. Depois da data, a chave responde 401 como qualquer chave inválida. Chave com prazo reduz o estrago se um dia ela vazar.
Rotação
Seção intitulada “Rotação”Rotacionar gera uma chave nova com o mesmo nome, as mesmas permissões, o mesmo membro, a mesma lista de IPs e a mesma data de expiração, e coloca a antiga para morrer sozinha.
No painel: menu da chave, Rotacionar. Você escolhe por quanto tempo a antiga continua valendo: parar agora, 1 hora ou 24 horas. Nesse período as duas chaves respondem, e é isso que deixa trocar o segredo nos seus sistemas sem derrubar a integração.
Passo a passo:
- Rotacione escolhendo o período de convivência.
- Copie a chave nova, que também aparece uma vez só.
- Troque o segredo nos seus sistemas e faça um
GET /public/v1/mecom a chave nova. - Revogue a antiga assim que confirmar. Não precisa esperar o período acabar.
Enquanto a antiga não morre, ela fica com o estado Em rotação no painel.
Quatro detalhes que costumam pegar:
- A chave nova herda a data de expiração da antiga. Rotacionar uma chave que expira semana que vem devolve uma chave que também expira semana que vem. Rotação troca o segredo, não renova prazo: para ganhar prazo, crie uma chave nova.
- Durante a convivência as duas chaves contam na cota de chaves ativas do plano. A rotação em si não é barrada por isso, mas criar mais uma chave é, até a antiga morrer.
- A chave antiga já rotacionada não pode ser rotacionada de novo. Quem rotaciona duas vezes rotaciona a chave nova.
- Na chave antiga, uma data de expiração anterior ao fim da convivência vence a convivência: ela morre na data, não no fim do período escolhido.
Revogação
Seção intitulada “Revogação”Revogar no painel encerra a chave na hora. A chamada seguinte com ela recebe 401. Não há desfazer, e não há período de carência: se a chave vazou, é isso que se faz primeiro.
OWNER e ADMIN da empresa recebem e-mail quando uma chave é criada, rotacionada ou revogada.
Próximo passo
Seção intitulada “Próximo passo”- Permissões: o que a chave pode fazer depois de autenticada.
- Referência: as rotas publicadas, campo a campo.