Autenticação

OAuth2 client_credentials (RFC 6749 §4.4). As credenciais de longa duração são trocadas por um access_token de curta duração, usado nas demais chamadas.

Endpoint

POST /oauth/token
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=<escopos>
Parâmetro Obrigatório Valor
grant_type sim client_credentials
scope não Escopos separados por espaço. Omitido, concede todos os do client_id.

Resposta 200:

{
  "access_token": "<jwt>",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "payments:write payments:read"
}

Não há refresh token. Expirado o access_token, repita a requisição acima.

Escopos

Escopo Permissão
payments:write Criar e capturar cobranças
payments:read Consultar cobranças
refunds:write Cancelar e estornar
webhooks:write Gerenciar endpoints de webhook

Escopo requisitado além do concedido ao client_id retorna 400 invalid_scope. Não há concessão parcial silenciosa.

Endpoints exigem escopo específico. Token sem o escopo exigido retorna 403 insufficient_scope, com o escopo faltante na mensagem.

Token

JWT assinado em ES256, curva P-256. Validade de 900 segundos.

{
  "iss": "https://api-crpay.deskhotel.com.br",
  "aud": "https://api-crpay.deskhotel.com.br",
  "sub": "ten_01KYFJZ09JYEYH5QKK2CDAZC22",
  "client_id": "test_794243d7b8541c078903cc4a80a6ccac",
  "scope": "payments:write payments:read",
  "env": "test",
  "jti": "1f6a...",
  "iat": 1785082124,
  "exp": 1785083024
}
Claim Conteúdo
sub Identificador do tenant
env test ou live
scope Escopos concedidos, separados por espaço
jti Identificador único do token

Validação da assinatura

Chaves públicas em GET /.well-known/jwks.json. Resposta cacheável por 300 segundos.

import { createRemoteJWKSet, jwtVerify } from 'jose';

const jwks = createRemoteJWKSet(
  new URL('https://api-crpay.deskhotel.com.br/.well-known/jwks.json')
);

const { payload } = await jwtVerify(token, jwks, {
  issuer: 'https://api-crpay.deskhotel.com.br',
  audience: 'https://api-crpay.deskhotel.com.br',
  algorithms: ['ES256']
});

Requisitos da implementação:

Ambientes

Determinados pelo prefixo do client_id, não por URL.

Prefixo Ambiente
test_ Sandbox das adquirentes
live_ Produção

A separação é aplicada no servidor. Credencial test_ não acessa configuração live_.

Rotação do client_secret

O client_id é preservado. O segredo anterior é invalidado no ato. Tokens emitidos com ele permanecem válidos até expirarem, no máximo 900 segundos.

Sequência sem indisponibilidade: solicitar a rotação, atualizar o segredo na aplicação, reiniciar.

Limites

POST /oauth/token: 10 requisições por minuto, por client_id. Excedido, retorna 429 com header Retry-After.

Reutilize o token em memória durante a validade. Uma requisição de token por chamada de API excede o limite.

Resposta a credencial inválida

client_id inexistente e client_secret incorreto retornam resposta idêntica, em tempo equivalente:

{ "error": "invalid_client", "error_description": "Credenciais invalidas." }

Armazenamento das credenciais