Referência: OAuth2 client credentials
Resposta rápida: Obtenha
access_tokenem{{TOKEN_URL}}comgrant_type=client_credentialseclient_id/client_secretno corpo (Basic auth responde 401), semscope, enviando certificado, chave e CA do banco; useAuthorization: Beareratéexpires_in.
Endpoints (happy path)
| Método | Path | Uso |
|---|---|---|
| POST | {{TOKEN_URL}} | Emitir access_token |
Contrato
OAuth2 client credentials + mTLS. Schemas de cob/pix no OpenAPI BACEN. URL de token é específica do PSP (Modobank) — placeholder até confirmação oficial.
Corpo da requisição, application/x-www-form-urlencoded:
| Campo | Valor |
|---|---|
grant_type | client_credentials |
client_id | credencial gerada no Internet Banking |
client_secret | idem |
scope | não enviar |
Resposta: access_token, expires_in e campos de Keycloak (not-before-policy, refresh_expires_in).
Divergências do padrão, medidas em produção
| Esperado pela leitura do padrão | Comportamento real |
|---|---|
Basic client_id:client_secret | 401 — credenciais têm de ir no body |
scope com os escopos do produto | 401 invalid_scope quando a conta não tem escopos atribuídos |
| Cadeia TLS pública | CA privada; sem ela o handshake falha antes do HTTP |
Escopos são propriedade da credencial, não da requisição: o que a conta tem é o que vale. Isso também rege os recursos de webhook (webhook.write, webhookrec.write, webhookcobr.write) — se o recurso responde 403, o caminho é pedir o escopo ao banco, não mandá-lo no token.
Notas Modobank
- Snippets:
snippets/*/token.* - Não embutir secret em repositório ou prompt de vibecode com valores reais.
- Um
client_idde produção costuma codificar identificadores da conta — trate como dado sensível de negócio, ainda que não seja segredo criptográfico.