Toda chamada à Partner API é assinada. Não existe token de sessão, não existe OAuth e a credencial nunca sai do seu servidor.

Credenciais

A PrismaPay emite três valores para o seu ambiente:
O secret assina as requisições. Se ele vazar, qualquer pessoa dentro da sua faixa de IP consegue movimentar as contas que você gerencia. Guarde em cofre de segredos, nunca em repositório, nunca no aplicativo, nunca no navegador.

Headers de toda requisição

Requisições que alteram estado exigem um header a mais:

A string canônica

Quatro partes, separadas por ponto:
1

timestamp

O mesmo valor que você envia em X-Timestamp. Unix time em segundos, como texto.
2

METHOD

O método HTTP em maiúsculas: GET, POST.
3

canonicalPath

O caminho decodificado que você chamou, incluindo /v1, mais a query canônica quando houver parâmetros. Exemplo: /v1/balance.
4

sha256hex(rawBody)

SHA-256 em hexadecimal dos bytes exatos do corpo. Para GET, use string vazia: o hash de "".

Query canônica

Se a requisição tem parâmetros de query, eles entram na assinatura em ordem determinística:
  1. Ordene as chaves alfabeticamente.
  2. Dentro de uma chave repetida, ordene os valores.
  3. Renderize cada par como encodeURIComponent(chave)=encodeURIComponent(valor).
  4. Junte com & e prefixe com ?.
Sem parâmetros, não acrescente nada.
O passo 2 existe porque o servidor aceita chave repetida na assinatura. Nenhuma rota atual usa parâmetro repetido, então na prática o passo 1 já resolve. Deixe o passo 2 implementado mesmo assim: ele é barato agora e evita uma falha silenciosa quando um parâmetro de lista aparecer.
Ordenar apenas as chaves e esquecer os valores é o erro que passa em todo teste simples. Ordene os dois.
O servidor assina o mesmo caminho decodificado que ele usa para rotear. Assine o caminho exatamente como você chama. Não faça percent-encoding do caminho por conta própria.

Assinador de referência em Node.js

Uso:
Envie exatamente a mesma string que você usou para calcular o hash. Se você serializar o objeto duas vezes, a ordem das chaves pode mudar e a assinatura não bate. Calcule o corpo uma vez, guarde na variável, use nos dois lugares.

Escopos

Cada credencial carrega uma lista de escopos e cada rota exige o seu. Uma chamada autenticada sem o escopo correto responde 403 insufficient_scope.
Toda credencial carrega accounts:read; ele não pode ser removido. E payments:create é recusado no momento da criação da credencial, não apenas ausente por configuração. Enquanto isso durar, as rotas PIX permanecem fora de alcance, e o 403 insufficient_scope nem chega a ser testado porque as rotas não estão montadas.

Regras que o servidor aplica

A requisição precisa sair de um IP que você registrou conosco. Envie os IPs de saída (egress) dos seus servidores antes de começar. Uma chamada de IP não registrado responde 401 unauthorized.
O X-Timestamp precisa estar a até 5 minutos do relógio do servidor, para frente ou para trás. Mantenha NTP ativo nos seus servidores.
Cada assinatura vale uma vez. Reenviar a mesma assinatura dentro da janela é tratado como replay e recusado. Toda nova tentativa precisa de timestamp novo e assinatura nova, inclusive o retry de um 503.
Um corpo acima de 1 MB é recusado com 413 request_body_too_large. Essa verificação acontece depois da chave, do IP e do timestamp: um corpo grande vindo de IP não liberado responde 401, não 413.
Ao estourar, a resposta é 429 rate_limit_exceeded com o header Retry-After: 60. Existe também um limite por IP, acima desse. Ver Erros e retries.

Por que o erro de autenticação é sempre o mesmo

Chave desconhecida, IP fora da allowlist, timestamp velho, assinatura errada e replay respondem todos 401 unauthorized, sem detalhe. Isso é proposital: a resposta não pode ajudar alguém a descobrir se uma chave existe ou se um IP está liberado. Ao depurar um 401, verifique nesta ordem:
  1. O Key ID está correto e ativo.
  2. O IP de saída do servidor está na allowlist.
  3. O relógio do servidor está sincronizado.
  4. A string canônica tem as quatro partes, com o caminho igual ao chamado.
  5. Você não está reenviando uma assinatura já usada.