Primeiros passos em 5 minutos
Este é o caminho inteiro, do zero até a primeira resposta.
Antes de começar
Seção intitulada “Antes de começar”- A empresa precisa estar num plano que inclui a API, a partir do Start.
- Você precisa ser OWNER ou ADMIN dela. Só esses dois papéis criam chave.
- Tenha a sua senha do painel à mão: o formulário de criação pede a senha.
1. Criar a chave
Seção intitulada “1. Criar a chave”No painel, abra Configurações, vá na aba API e clique em Nova chave.
| Campo | O que preencher |
|---|---|
| Nome | Para reconhecer depois qual sistema usa esta chave, como “ERP da loja” |
| O que esta chave pode fazer | Marque só o que a integração usa. Veja Permissões |
| Expiração | Não expira, 30 dias, 90 dias ou 1 ano |
| IPs permitidos | Opcional. Um por linha, IP ou faixa. Vazio aceita qualquer IP |
| Senha | A sua senha do painel |
Copie a chave e guarde em cofre de segredo ou em variável de ambiente do seu servidor. Nunca no código, nunca em repositório, nunca no navegador.
2. Guardar a chave no ambiente
Seção intitulada “2. Guardar a chave no ambiente”export FH_API_KEY="fh_live_sua_chave"Os exemplos abaixo leem a chave dessa variável. Assim ela não fica escrita no arquivo que você versiona.
3. Fazer a primeira chamada
Seção intitulada “3. Fazer a primeira chamada”GET /public/v1/me responde de quem é a chave. É a chamada certa para confirmar que tudo está no lugar antes de escrever o resto da integração.
curl https://api.fatureihoje.com/public/v1/me \ -H "Authorization: Bearer $FH_API_KEY" \ -H "Accept-Language: pt-BR"const res = await fetch('https://api.fatureihoje.com/public/v1/me', { headers: { Authorization: `Bearer ${process.env.FH_API_KEY}`, 'Accept-Language': 'pt-BR', },});
const body = await res.json();
if (!res.ok) { throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`);}
console.log(body.organization.name, body.key.permissions);Rode com node me.mjs. Node.js 18 ou mais novo, que já traz fetch.
<?php
$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'), 'Accept-Language: pt-BR', ],]);
$raw = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$body = json_decode($raw, true);
if ($status !== 200) { throw new RuntimeException($status . ' ' . $body['error']['code'] . ': ' . $body['error']['message']);}
echo $body['organization']['name'], PHP_EOL;Rode com php me.php. Precisa das extensões curl e json, que vêm ligadas na maioria das instalações.
import jsonimport 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']}", "Accept-Language": "pt-BR", },)
try: with urllib.request.urlopen(request) as response: body = json.load(response)except urllib.error.HTTPError as failure: error = json.load(failure)["error"] raise SystemExit(f"{failure.code} {error['code']}: {error['message']}")
print(body["organization"]["name"], body["key"]["permissions"])Rode com python3 me.py. Só biblioteca padrão, nada para instalar.
4. A resposta
Seção intitulada “4. A resposta”{ "object": "api_key_context", "organization": { "id": "0f3a5f1e-9f7a-4f2b-8f4c-2a1d9e6b7c30", "name": "Marcenaria Souza", "timezone": "America/Sao_Paulo", "currency": "BRL" }, "key": { "id": "6d2c8b41-77a3-4a5e-9c10-3b8f0d5e41aa", "name": "ERP da loja", "prefix": "fh_live_7Qx4Kd", "permissions": ["clients:read", "leads:create"], "expires_at": null }, "acting_as": { "member_id": "b1d4e2f0-5c69-4a31-9d77-8e2c4f6a0b53", "name": "Ana Souza", "role": "owner" }, "limits": { "requests_per_minute": 60 }}| Campo | O que é |
|---|---|
organization | A empresa dona da chave, com o fuso e a moeda que ela usa |
key.prefix | O começo da chave, o mesmo que o painel mostra na lista. Serve para saber qual chave está em uso |
key.permissions | O que esta chave pode fazer, no formato modulo:acao |
key.expires_at | Data de expiração em ISO 8601, ou null quando a chave não expira |
acting_as | O membro da empresa que a chave representa, e o papel dele |
limits.requests_per_minute | Chamadas por minuto da empresa, somando todas as chaves. null quer dizer sem teto |
A Referência traz esses campos um a um, com tipo e formato.
5. Quando vier 401
Seção intitulada “5. Quando vier 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" }}Essa é a resposta de qualquer recusa de autenticação, sempre igual. Ela não diz qual foi o motivo de propósito. Confira nesta ordem:
- O cabeçalho é
Authorization: Bearer <chave>, com um espaço só entreBearere a chave. - A chave foi copiada inteira, sem espaço nem quebra de linha no fim.
- A chave não está revogada nem expirada. O painel mostra o estado de cada chave.
- Se a chave tem lista de IPs, o IP de saída do seu servidor está na lista.
- O endereço é
api.fatureihoje.com. O host do painel não responde/public/v1.
Em seguida, abra Ver uso no menu da chave, no painel. Ele mostra as chamadas dos últimos 30 dias com data, método, rota, status, duração, IP e request_id, inclusive as recusadas. É ali que se vê o IP que o seu servidor está usando de verdade.
Guarde o request_id da resposta. É por ele que o suporte acha a chamada.
Próximo passo
Seção intitulada “Próximo passo”- Autenticação: formato da chave, lista de IPs, rotação e revogação.
- Permissões: por que uma chave com permissão ainda pode receber 403.