Inyo

Autenticação

A API de KYC usa o grant client-credentials do OAuth 2.0 (RFC 6749 §4.4). Seu backend troca um client_id e um client_secret por um token Bearer de curta duração e, em seguida, apresenta esse token em cada chamada /v1/*.

As credenciais são exclusivamente server-side. Nunca envie um client_secret — ou um token de acesso — para um navegador ou aplicativo móvel. Seus clientes interagem com o widget, nunca com a API.


Solicitar um Token

Endpoint: POST /oauth/token
Content-Type: application/x-www-form-urlencoded

curl --request POST \
  --url https://{FQDN}/oauth/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data client_id=$KYC_CLIENT_ID \
  --data client_secret=$KYC_CLIENT_SECRET

As credenciais também podem ser enviadas como autenticação HTTP Basic (client_secret_basic) em vez de no corpo:

curl --request POST \
  --url https://{FQDN}/oauth/token \
  --user "$KYC_CLIENT_ID:$KYC_CLIENT_SECRET" \
  --data grant_type=client_credentials

Resposta:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "sessions verifications"
}

grant_type deve ser client_credentials — é o único grant que este endpoint aceita.


Scopes

Cada endpoint exige um scope específico. Os tokens são emitidos com os scopes concedidos ao seu client; solicite um conjunto mais restrito com o parâmetro opcional scope quando um componente do seu sistema precisar de apenas um deles.

ScopeConcede acesso a
sessionsPOST /v1/sessions, GET /v1/sessions/{sessionId}
verificationsPOST /v1/verifications, GET /v1/verifications/{verificationId}

Cada porta lê no seu próprio caminho, e só as suas próprias linhas. Um token sessions lê sessões de widget; um token verifications lê as verificações que criou. Nenhum alcança os registros do outro, então um componente do seu sistema que só envia verificações server-to-server não precisa de nada além de verifications.

--data scope=sessions

Solicitar um scope desconhecido é rejeitado, em vez de ignorado silenciosamente. Um token que não possui o scope exigido por um endpoint retorna 403, e não 401 — o token é válido, apenas não está autorizado para aquela chamada.


Usando o Token

Apresente o token como uma credencial Bearer:

curl --request POST \
  --url https://{FQDN}/v1/sessions \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{"userRef": "user-123"}'

Tempo de Vida e Renovação do Token

Os tokens são JWTs assinados com RS256 e expiram — expires_in informa quando, em segundos. Armazene o token em cache e renove-o antes da expiração; não solicite um novo token a cada chamada de API e não faça hardcode de um token em lugar nenhum.

Um client robusto:

  1. Armazena o token em memória junto com seu timestamp de expiração.
  2. Renova quando o tempo de vida restante cai abaixo de uma pequena margem (30-60 segundos).
  3. Tenta novamente uma vez ao receber 401, caso o token tenha expirado entre a verificação e a chamada.
  4. Trata um 503 como falha transitória de infraestrutura, e não de autenticação — aplica backoff e tenta novamente com o mesmo token.

Respostas de Erro

Os erros do endpoint de token seguem a RFC 6749 §5.2 — um código error com um error_description legível por humanos:

StatuserrorCausa
400unsupported_grant_typegrant_type estava ausente ou não era client_credentials
400invalid_scopeO scope solicitado contém um valor desconhecido
401invalid_clientCredenciais de client ausentes, desconhecidas ou incorretas. A resposta traz um challenge WWW-Authenticate: Basic
{
  "error": "invalid_client",
  "error_description": "Missing client credentials"
}

Toda recusa em uma chamada /v1/* — não apenas de autenticação — responde com o mesmo documento RFC 9457 application/problem+json. Ramifique pelo errorCode; errors[] nomeia os campos aos quais uma falha de validação se aplica, e traz uma entrada sem field para uma recusa que não é sobre um campo.

{
  "type": "docs#/components/schemas/ProblemDetails",
  "title": "Unauthorized",
  "status": 401,
  "errorCode": "unauthorized",
  "errors": [
    { "message": "Missing Bearer token (obtain one at POST /oauth/token)", "type": "unauthorized" }
  ],
  "correlationId": "c0d60e879b6d412488ffe83d5213aa8b",
  "instance": "/v1/sessions/nope"
}

Cite o correlationId ao contatar o suporte — ele identifica a requisição exata nos nossos logs. O endpoint de token é a única exceção: POST /oauth/token segue a RFC 6749 conforme mostrado acima.

Erros em chamadas /v1/*:

StatusCausaComo corrigir
401Sem o header Authorization: BearerEnvie o header; obtenha um token em POST /oauth/token
401Token expiradoRenove o token e tente novamente
401Token inválido ou não verificávelConfirme que está usando o token exatamente como recebido e no ambiente correspondente
403O token é válido, mas não possui o scope do endpointSolicite um token com o scope necessário
503Não foi possível contatar o provedor de identidade para verificar a assinatura do tokenTente novamente com backoff — seu token continua válido

A resposta 403 inclui WWW-Authenticate: Bearer error="insufficient_scope" indicando o scope que era exigido.

Um 503 é transitório e não é uma falha de autenticação. Suas credenciais e o token em cache não são afetados — a Inyo não conseguiu contatar o provedor de identidade para verificar a assinatura do token. Tente novamente com backoff exponencial e mantenha o token que já possui: reautenticar não resolve, e uma chamada a POST /oauth/token durante a mesma indisponibilidade provavelmente também falhará.

{
  "errorCode": "service_unavailable",
  "errors": [
    { "message": "Identity provider unreachable — cannot verify access tokens", "type": "service_unavailable" }
  ]
}

Isolamento de Ambientes

O sandbox e a produção emitem credenciais separadas, e cada token é válido apenas no ambiente que o emitiu. As sessões são estritamente restritas ao tenant que as criou: um token nunca pode ler a sessão de outro tenant, e uma requisição para uma delas retorna 404.


Rotação do Seu Secret

Os client secrets são rotacionados pela Inyo mediante solicitação — entre em contato com seu representante Inyo em vez de tentar a rotação pela API. Rotacione imediatamente se um secret possa ter sido exposto.


Próximos Passos