Autenticacao
A API V2 suporta dois metodos de autenticacao:
| Metodo | Uso | Header |
|---|---|---|
| Credenciais de API | Integracoes automatizadas (servidor a servidor) | Authorization: Bearer <token> via token exchange |
| JWT Bearer Token | Sessoes de usuario (portal, backoffice) | Authorization: Bearer <token> |
Credenciais de API (recomendado para integracoes)
Emitidas por voce mesmo, no Portal (PCP). Use-as no fluxo Client Credentials (Token Exchange) para obter um JWT de curta duracao — e o metodo recomendado.
X-Client-Id/X-Client-Secret por requisicaoEnviar as credenciais direto nos headers em toda requisicao esta deprecated.
Migre para o token exchange (POST /v1/auth/token → Authorization: Bearer):
o secret trafega menos e o token carrega scopes verificados por rota.
O caminho por headers segue funcionando por compatibilidade — e, desde o item
022, tambem exige os scopes da credencial (403 scope_insufficient se
faltar) — mas sera removido em prazo a ser definido pelo owner.
Formato legado (compatibilidade, deprecated):
X-Client-Id: zk_live_...
X-Client-Secret: sk_live_... # ou rk_live_... (ver Tipos de chave)
Credenciais zk_live_* operam em Produção. Credenciais de Sandbox (zk_sbx_*; zk_test_* é o prefixo legado, ainda válido) operam no Sandbox, que está ativo para homologação de clientes. Veja Ambientes.
Como obter suas credenciais
Emita você mesmo, no Portal (PCP). Não é preciso abrir chamado nem esperar
provisionamento: o usuário master_user do originador cria a credencial na tela
Integração → Tokens de API.
- No Portal, acesse Integração → Tokens de API e clique em criar credencial.
- Dê um rótulo que identifique o consumidor (ex.:
ERP produção,job de conciliação). - Selecione os scopes que a integração realmente usa.
- O Portal devolve o par
client_id(zk_live_…) +client_secret(sk_live_…). Oclient_secreté exibido uma única vez — armazene-o imediatamente em um cofre de segredos (AWS Secrets Manager, Vault, etc.). Nunca o inclua no código-fonte ou em logs. - Valide a integração em Homologação/Sandbox com credenciais
zk_sbx_…(ouzk_test_…, legado) antes de ir para Produção.
O self-service ainda não oferece seletor de ambiente: as credenciais emitidas por ele são exclusivamente de Produção (zk_live_*). Credenciais de Sandbox (zk_sbx_*/sk_test_*; zk_test_* é o prefixo legado) continuam sendo provisionadas pela equipe da Zemo (Backoffice) durante o onboarding — peça-as ao seu contato informando razão social/CNPJ do originador, o contato técnico da integração e os scopes necessários.
Tipos de chave (SK x RK)
A tela de Tokens de API oferece a escolha explícita entre SK e RK na emissão — o default é RK, o tipo recomendado.
| Tipo | Prefixo do secret | O que é | Quando usar |
|---|---|---|---|
| SK (secret key) | sk_live_… | Chave plena: carrega exatamente as 11 scopes do recorte self-service (a tela oferece 14; as 3 extras são só-RK) | Integração única que faz tudo (consulta, cadastro e operação) |
| RK (restricted key) | rk_live_… | Chave restrita: carrega um recorte de scopes que você escolhe | Recomendado. Uma chave por consumidor, com o mínimo que ele precisa |
"Restrita" é uma garantia, não um estilo: uma RK nunca contém o catálogo
self-service completo — a emissão recusa (422) quando os scopes pedidos
incluem todos os do self-service, porque aí a chave seria tão ou mais ampla que
uma SK exibindo um prefixo que promete o contrário. Uma RK pode incluir
scopes técnicos específicos concedidos fora do PCP, desde que não reúna o
catálogo inteiro.
O client_id é zk_live_… nos dois casos — o que muda é o prefixo do secret,
para você reconhecer a natureza da chave no cofre sem consultar o Portal. O tipo é
declarado na emissão, nunca deduzido dos scopes: a chave guardada como
sk_live_… continua sendo SK mesmo que o catálogo de scopes cresça depois.
Uma exceção operacional que vale conhecer: credenciais provisionadas pela equipe
da Zemo (Backoffice) — o caminho de onboarding e de Sandbox — podem ter um
recorte de scopes e ainda assim aparecer como SK, porque esse caminho ainda
não declara o tipo. Vale o que está no campo scopes da credencial, que é o que
a API verifica em toda chamada.
Prefira RK: várias chaves restritas limitam o raio de um vazamento e permitem revogar um consumidor sem derrubar os outros. O teto de credenciais ativas (abaixo) já foi dimensionado para esse padrão.
Ciclo de vida da credencial (self-service no PCP). A revogação é feita pelo próprio originador: o usuário
master_userrevoga a credencial na tela de Tokens de API do Portal (não depende do Backoffice). Não existe endpoint de rotação — para trocar o segredo, siga o modelo de chave de acesso: crie uma credencial nova, migre o cliente e só então revogue a antiga. As duas ocupam slot enquanto ativas, e o teto é de 10 credenciais ativas por originador (a criação retorna409 active_credential_limit_reachedquando os 10 slots estão ocupados). As credenciais têm validade indefinida: não expiram sozinhas e o slot só é liberado por revogação. IP allowlist por credencial ainda não está disponível — nem no Portal, nem via API. Recomendamos trocar o secret a cada 90 dias pelo procedimento de substituição acima — é uma recomendação, não uma regra imposta pela API. Antes de produzir, percorra o Checklist de Go-Live.A revogação vale IMEDIATAMENTE, inclusive para um
access_tokenjá emitido. Além de impedir novas trocas de credencial por JWT, ela derruba os tokens em circulação: toda requisição autenticada por Bearer relê a credencial no banco, e credencial revogada (ou expirada) responde401 invalid_client_credentialsna hora — não há janela de até 15 minutos esperando o token expirar. O mesmo vale para uma redução de limite: passa a valer no request seguinte, sem esperar a renovação do token.
Se usar o SDK Python, a autenticacao e automatica:
import zemo
zemo.user = zemo.Originator(
client_id="zk_test_...",
client_secret="sk_test_...",
environment="https://receivables-api-sandbox.zemocapital.com",
)
Client Credentials (Token Exchange)
Para maior seguranca, o SDK troca automaticamente as credenciais de API por um JWT RS256 de curta duracao (15 min) via POST /v1/auth/token. O secret so trafega no wire uma vez a cada 15 minutos.
# Trocar credenciais por JWT
curl -X POST "https://receivables-api-sandbox.zemocapital.com/v1/auth/token" \
-H "Content-Type: application/json" \
-d '{"client_id": "zk_test_...", "client_secret": "sk_test_..."}'
# -> {"access_token": "eyJ...", "expires_in": 900, "scopes": [...]}
# Usar o JWT
curl "https://receivables-api-sandbox.zemocapital.com/v1/stock" \
-H "Authorization: Bearer eyJ..."
O token inclui scopes granulares (stock:read, operation:create, etc.) e e verificado em cada rota. Veja a tabela de scopes (e os scopes por endpoint na Referência Técnica).
JWT Bearer Token
Obtido via POST /v1/auth/login. Valido por 15 minutos.
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
O token JWT contem:
sub— ID do usuariooriginator_id— ID do originador (tenant)email— Email do usuariorole— Papel (OWNER,OPERATOR,READ_ONLY,FINANCIAL,COMPLIANCE)exp— Expiracao
Protecao contra brute force
Apos 5 tentativas falhadas, a conta e bloqueada por 30 minutos.
| Tentativa | Resultado |
|---|---|
| 1-4 (senha errada) | 401 invalid_credentials |
| 5 (senha errada) | 401 invalid_credentials — e a conta fica bloqueada |
| 6+ dentro de 30min, senha ERRADA | 401 invalid_credentials (nao conta nem estende o bloqueio) |
| 6+ dentro de 30min, senha CORRETA | 423 user_locked |
| Apos 30min | Desbloqueio automatico — o contador de falhas volta a zero |
O desbloqueio dos 30 minutos ZERA o contador: a janela recomeca do zero e uma nova trava volta a exigir 5 tentativas falhadas. Uma unica senha errada logo depois do desbloqueio nao re-bloqueia a conta.
O 423 so chega a quem PROVA a senha — o dono legitimo da conta. Para quem nao prova, a
resposta e sempre 401 invalid_credentials, identica a de um e-mail inexistente: a rota nao
revela se a conta existe.
Status e corpo sao iguais nos tres casos (e-mail inexistente, senha errada, conta bloqueada sem senha provada) — isso e garantia de contrato. O tempo de resposta e mitigado, nao garantido: o login executa a mesma verificacao de senha (mesmo custo de KDF) mesmo quando o e-mail nao existe, para que a latencia nao denuncie a existencia da conta. Como toda contramedida de canal lateral temporal, ela reduz o sinal — nao prova igualdade perfeita de tempo.
Tenant Isolation
Toda requisicao autenticada e automaticamente filtrada pelo originator_id do token. Um originador nunca acessa dados de outro.
Headers de resposta
Toda resposta inclui:
| Header | Descricao |
|---|---|
X-Request-Id | UUID unico da requisicao (para suporte) |
X-Zemo-Env | Ambiente (dev, sandbox, prod) |
X-Zemo-API-Version | Versao da API |