Autenticação HMAC-SHA256
Visão geral dos três headers obrigatórios, da fórmula do payload assinado e do ciclo de vida de uma requisição autenticada. Leia antes das receitas por linguagem.
1. Headers obrigatórios
Toda requisição autenticada à API Pública Sivoe deve enviar
três headers. O backend rejeita imediatamente
qualquer requisição que omita um deles com
401 AUTH_MISSING_HEADER.
| Header | Conteúdo | Validação |
|---|---|---|
X-API-Key |
Identificador público da chave | Formato svp_live_[0-9a-f]{32} |
X-Timestamp |
Unix epoch em segundos (UTC) | Janela ±300s contra relógio do servidor |
X-Signature |
HMAC-SHA256 do payload, hex lowercase (64 chars) | Assinado com seu api_secret |
Content-Type |
application/json (quando houver body) |
Opcional em GET sem body |
2. Fórmula do payload assinado
Você assina exatamente esta string:
payload = timestamp + "." + UPPER(method) + " " + path_com_query + "\n" + body
signature = HMAC-SHA256(payload, api_secret) // hex lowercase
Notas críticas
methodem maiúsculas (GET,POST...).path_com_queryé oREQUEST_URIexatamente como enviado — inclua a query string (?a=1&b=2).bodyé o corpo cru. ParaGETsem body, use string vazia.- O separador entre
method uriebodyé uma única quebra de linha\n(LF), nunca\r\n. - Não envie body sanitizado/normalizado — assine exatamente o que será enviado.
\n e não \r\n?
Porque o gateway monta o payload em PHP com a string literal
"\n" (LF). Bibliotecas HTTP que normalizam EOL
para CRLF ao serializar quebram a assinatura.
Assine sobre a forma final do body antes de qualquer transporte.
3. Ciclo de vida de uma requisição autenticada
- Cliente calcula
X-Timestamp, monta o payload e assina comapi_secret. - Cliente envia a requisição com os 3 headers (
X-API-Key,X-Timestamp,X-Signature). - Gateway valida o formato dos headers, a janela ±300s e refaz o HMAC com o secret armazenado.
- Gateway resolve a clínica da chave e abre conexão com o tenant correspondente.
- Gateway valida o escopo (
pacientes:read,exames:read,laudos:read,agenda:read,agenda:write) contra o endpoint. - Gateway chama o backend e serializa a resposta (cold ~2300ms ou hot <800ms — ver §5).
- Gateway retorna o envelope JSON com
meta.request_id(use em tickets de suporte).
4. Janela anti-replay (±300s)
X-Timestamp é validado contra o relógio do servidor
com tolerância de ±300 segundos (5 minutos para
cada lado). Se o relógio do seu cliente derivar mais que isso,
você recebe 401 AUTH_TIMESTAMP_EXPIRED.
- NTP é fortemente recomendado. Em servidores Linux, ative
chronyousystemd-timesyncd. - No Windows, o serviço
w32timenormalmente é suficiente; em VMs antigas pode precisar de ajuste de fuso. - Em PowerShell 5.1,
Get-Date -UFormat %stem bug conhecido — use[DateTimeOffset]::UtcNow.ToUnixTimeSeconds().
5. Cache de Authorization — cold call vs hot call
O gateway faz uma autenticação interna no backend antes de processar cada requisição. Essa autenticação leva ~1.9–2.0 segundos — é a maior parte da latência observada. Para amortizar esse custo, o gateway mantém um cache local de autenticação por tenant com TTL de 300 segundos.
| Cenário | Latência média (DEV) | Notas |
|---|---|---|
| Cold call (1ª após inatividade) | ~2300 ms | Authorization regenerado do zero |
| Hot call (cache válido) | ~600–800 ms | Cache hit + cURL backend + serializer |
6. Quando renovar credenciais
- Rotação preventiva: recomendada a cada 90 dias. Solicite ao suporte Sivoe em contato@roomtec.com.br.
- Suspeita de vazamento: rotacione imediatamente — o cache de autenticação invalida automaticamente quando o secret muda.
- O
api_keypermanece o mesmo na rotação; somente oapi_secretmuda. Você não precisa atualizar nenhuma whitelist no seu lado. - O
api_secreté entregue uma única vez — guarde em cofre/HSM imediatamente.
7. Próximo passo — escolha sua linguagem
Com a teoria firme, vá para a receita prática:
- Receita Bash + openssl + curl
- Receita Python (
hmac+requests) - Receita Node.js 18+ (
crypto+fetch) - Receita PHP 8+ (
hash_hmac+ cURL/Guzzle)
Outras linguagens (Go, Ruby, C#, Java) seguem a mesma fórmula: adapte o pseudocódigo da seção 2.