---
updatedAt: 2026-10-28T21:18:24.000Z
agentTools:
  projectIndex: https://dev-hub.iorq.com.br/llms.txt
---

# Autenticação

A API IORQ usa OAuth 2.0 client_credentials. Você troca um client_id + client_secret por um Bearer JWT com validade de 1 hora e passa o token no header Authorization de cada chamada operacional. Sem sessões, sem cookies, sem refresh tokens.

`POST /oauth2/token` · OAuth 2.0 · JWT

## 1. Modelo de autenticação

A IORQ adota **OAuth 2.0 client\_credentials** sobre **Amazon Cognito** — o fluxo apropriado para integrações server-to-server. Não há usuário final no caminho, não há autorização explícita por consentimento. As credenciais identificam a aplicação cliente do integrador; as permissões e os fundos acessíveis são resolvidos pela IORQ a partir do `client_id`.

```mermaid
sequenceDiagram
    participant INT as Integrador
    participant AUTH as IORQ Auth (Cognito)
    participant API as IORQ API

    INT->>AUTH: POST /oauth2/token (client_id + client_secret)
    AUTH-->>INT: access_token (JWT, exp=1h)
    loop Por até 1h
        INT->>API: Chamada operacional (Bearer access_token)
        API-->>INT: Resposta
    end
    Note over INT,AUTH: Após expiração, repete o /oauth2/token
```

## 2. Obter um token

### 2.1 `POST /oauth2/token`

`POST /oauth2/token` · `application/x-www-form-urlencoded` · host `auth-hs.iorq.com.br` (sandbox: `auth-dev.iorq.com.br`)

> 📘 **Host de autenticação**
>
> O token é obtido no serviço de autenticação (`https://auth-hs.iorq.com.br/oauth2/token`), **não** no hs-receiver. As chamadas operacionais usam o host `hs-receiver-app-*.iorq.com.br/api`. A API do investidor usa `investor-api.iorq.com.br` (sandbox: `investor-api-dev.iorq.com.br`), sem o prefixo `/api`. O token de todas elas é emitido neste mesmo host.

#### Parâmetros (form-encoded)

| Campo           | Obrigatório | Descrição                                                                                                                                                             |
| --------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `grant_type`    | sim         | Sempre `client_credentials`                                                                                                                                           |
| `client_id`     | sim         | Identificador da aplicação, fornecido pela IORQ                                                                                                                       |
| `client_secret` | sim         | Secret correspondente. Trate como senha — não exponha em logs, repositórios ou frontend                                                                               |
| `scope`         | não         | Opcional. Escopo Cognito do resource server (ex.: `cerberus-m2m/read`). A autorização efetiva por endpoint é feita pela IORQ a partir do `client_id`, não pelo escopo |

Exemplo:

```bash
curl -X POST 'https://auth-hs.iorq.com.br/oauth2/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials' \
  -d 'client_id=YOUR_CLIENT_ID' \
  -d 'client_secret=YOUR_CLIENT_SECRET'
```

Resposta:

```json
{
  "access_token": "eyJraWQiOiJyc2EtMjAyNiIsImFsZyI6IlJTMjU2In0...",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

### 2.2 Usar o token

Inclua o token no header `Authorization` de toda chamada operacional. O prefixo `Bearer` é obrigatório (com espaço). Lembre que as rotas operacionais ficam sob o prefixo `/api`.

```bash
curl 'https://hs-receiver-app-production.iorq.com.br/api/loan/?originator_proposal_code=OP-001' \
  -H 'Authorization: Bearer eyJraWQiOiJyc2EtMjAyNiIs...'
```

### 2.3 O `fund_id`

Quando a IORQ libera seu acesso, você recebe um **e-mail de credenciais** com `client_id`, `client_secret` e a lista de **fundos liberados** — cada um com nome e UUID. Esse UUID é o `fund_id` que você usa em toda a integração.

> 📘 **De onde vem o valor**
>
> Guarde o UUID exibido no e-mail (seção *Fundos liberados*). Sandbox e produção têm `fund_id` diferentes — use sempre o UUID do ambiente em que está integrando.

O mesmo UUID e o mesmo header valem para todos os serviços:

| Serviço                                 | Como informar o fundo                                                                                                                                              |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **API operacional** (`hs-receiver`)     | Header `iorq-fund-id` em toda requisição; em muitas rotas também no corpo ou na query como `fund_id`, e os dois têm de bater                                       |
| **Webhooks** (`webhook-sender-manager`) | Header `iorq-fund-id` em toda rota do serviço, e **só** por ele: não existe `fund_id` no corpo nem na query. O `fund_id` que aparece nas respostas é eco do header |
| **API do investidor**                   | Header `iorq-fund-id` em toda rota de fundo, e só por ele. O UUID é o `id` devolvido por `GET /v1/funds`. `GET /v1/funds` não recebe o header                      |

Exemplo na API operacional:

```bash
curl 'https://hs-receiver-app-production.iorq.com.br/api/loan/?fund_id=374485cf-f6df-467c-b91d-9f14082c6f36&originator_proposal_code=OP-001' \
  -H 'Authorization: Bearer eyJraWQiOiJyc2EtMjAyNiIs...' \
  -H 'iorq-fund-id: 374485cf-f6df-467c-b91d-9f14082c6f36'
```

Exemplo no webhook-sender-manager:

```bash
curl -X POST 'https://webhook-sender-manager-production.iorq.com.br/api/webhook' \
  -H 'Authorization: Bearer eyJraWQiOiJyc2EtMjAyNiIs...' \
  -H 'iorq-fund-id: 374485cf-f6df-467c-b91d-9f14082c6f36' \
  -H 'Content-Type: application/json' \
  -d '{ "message_type": "LOAN_UPDATE", "webhook_url": "https://example.com/hooks", "contract_version": "v2" }'
```

> 📘 **Um único header de fundo**
>
> O mesmo UUID e o mesmo header `iorq-fund-id` valem para os dois serviços. O exemplo acima é só para mostrar o header: o registro completo do webhook, com `contract_version: "v2"` (sem ele o webhook nasce no contrato legado v1) e os demais campos, está em [Configurando webhooks](https://dev-hub.iorq.com.br/docs/configurando-webhooks#2-registrar-a-url).

## 3. Perfis de acesso

O mesmo fluxo `client_credentials`, no mesmo host de autenticação (`auth-hs.iorq.com.br`; sandbox: `auth-dev.iorq.com.br`), serve os dois perfis de integração da IORQ. O claim `scope` do token muda com o perfil (`cerberus-m2m/read` para originador, `cerberus-m2m/investor` para investidor), mas não decide o acesso: as permissões e os fundos de cada credencial são resolvidos pela IORQ a partir do `client_id`, a cada chamada.

| Perfil         | Quem é                                                                        | APIs                                                                                                          | Fundos                                                                 |
| -------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **Originador** | Originador, bancarizador ou plataforma de crédito que cede operações ao fundo | API operacional (`hs-receiver-app-*.iorq.com.br/api`) e Webhooks (`webhook-sender-manager-*.iorq.com.br/api`) | Os fundos em que a credencial opera, listados no e-mail de credenciais |
| **Investidor** | Gestora de um investidor institucional que tem cotas no fundo                 | [API do investidor](https://dev-hub.iorq.com.br/docs/api-do-investidor) (`investor-api.iorq.com.br`), somente leitura                    | Os fundos em que o investidor tem cotas, listados por `GET /v1/funds`  |

* **Uma credencial, um perfil.** A credencial de investidor só tem a permissão de leitura da API do investidor: ela não chama a API operacional nem a de webhooks. A credencial de originador não recebe essa permissão. Quem precisa dos dois perfis recebe duas credenciais.
* **Extração de estoque (WIP), a exceção.** A permissão de pedir o estoque de um fundo (`POST /v1/inventory-exports`, na API do investidor) é separada da de leitura e é concedida por fundo. Ela pode ir também para a credencial de **originador** que é cotista do fundo, sem que essa credencial passe a ler covenants ou indicadores. Ver [Extração de estoque](https://dev-hub.iorq.com.br/docs/extracao-de-estoque).
* **O fundo vai no header.** Nas duas APIs, toda rota de um fundo exige o header `iorq-fund-id` com o UUID do fundo. Na API do investidor, o UUID é o `id` devolvido por `GET /v1/funds`. A permissão é sempre conferida no fundo do header: ter acesso a um fundo não dá acesso a outro.
* **Bloqueio sem perder a credencial.** A IORQ pode suspender uma credencial sem apagá-la. Enquanto suspensa, o token continua sendo emitido, mas a API do investidor responde `401` (`CALLER_NOT_PROVISIONED`); quando a suspensão é retirada, ela volta a funcionar com o mesmo `client_id` e `client_secret`. Uma credencial removida não volta: a IORQ emite uma nova, com outro `client_secret`.

## 4. Ciclo de vida do token

* **Validade:** 1 hora (`expires_in: 3600`). O claim `exp` dentro do JWT é a fonte da verdade — use-o para programar renovação proativa.
* **Renovação:** não há refresh token. Para renovar, basta chamar `POST /oauth2/token` novamente com as mesmas credenciais.
* **Revogação:** não há endpoint público. Em caso de comprometimento, peça ao seu contato na IORQ para revogar o `client_secret` — o token deixa de ser aceito imediatamente.
* **Múltiplos tokens válidos:** permitido. Você pode emitir tokens em paralelo para escalar — não há limite enforced por essa via.

> 📘 **Padrão recomendado**
>
> Mantenha um cache em memória do token e renove proativamente quando faltar menos de 5 minutos para expirar. Isso evita uma rajada de `401` quando o token expira no meio de um lote de cessões.

## 5. Anatomia do JWT

O `access_token` é um JWT (RFC 7519) emitido e assinado (RS256) pelo Amazon Cognito. A chave pública fica no JWKS do user pool Cognito:

```
https://cognito-idp.us-east-1.amazonaws.com/{user_pool_id}/.well-known/jwks.json
```

### Claims relevantes

| Claim               | Significado                                                            |
| ------------------- | ---------------------------------------------------------------------- |
| `sub` / `client_id` | Identificador da aplicação cliente (em tokens M2M, `client_id == sub`) |
| `scope`             | Escopo Cognito do resource server (ex.: `cerberus-m2m/read`)           |
| `token_use`         | `access`                                                               |
| `exp`               | Timestamp UNIX de expiração                                            |
| `iat`               | Timestamp UNIX de emissão                                              |
| `iss`               | Emissor — o URL do user pool Cognito                                   |

> 📘 **Partner e fundos não vêm no token**
>
> O parceiro (`id_partner`) e os fundos/credit vehicles acessíveis **não** são claims do JWT. Eles são resolvidos pela IORQ a cada chamada, a partir do `client_id`, pelo serviço de autorização (Cerberus). Você **não precisa** verificar a assinatura do token — a IORQ valida do lado dela.

## 6. Segurança do `client_secret`

* [ ] Armazene o `client_secret` em cofre de credenciais (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager). Nunca em repositório, build artifact ou variável de ambiente em plain text.
* [ ] Rotacione o secret pelo menos a cada 12 meses. Em caso de qualquer suspeita, rotacione imediatamente — a IORQ emite secrets sob demanda.
* [ ] Não use o secret no frontend. O fluxo client\_credentials é exclusivamente server-side.
* [ ] Restrinja o acesso ao secret aos serviços que efetivamente chamam `/oauth2/token`. Cada serviço que precisa de token deve ter sua própria credencial.

## 7. Erros de autenticação

| HTTP          | Serviço           | Causa                                                                                                                               | Corpo                                                                                 | O que fazer                                                                                            |
| ------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `400`         | Autenticação      | `grant_type` ausente ou diferente de `client_credentials`                                                                           | —                                                                                     | Corrigir o payload da chamada a `/oauth2/token`                                                        |
| `401`         | Autenticação      | `client_id` ou `client_secret` inválido                                                                                             | —                                                                                     | Verificar credenciais; rotacionar se necessário                                                        |
| `401`         | API de cessão     | Token expirado, malformado ou ausente                                                                                               | `{"message": "...", "status": 401}`                                                   | Renovar via `/oauth2/token` e refazer                                                                  |
| `401`         | Webhooks          | Só `Authorization` **ausente**                                                                                                      | `{"message": "Unauthorized"}`                                                         | Incluir o header                                                                                       |
| `403`         | Webhooks          | Token inválido ou expirado, recusado no gateway                                                                                     | `{"message": "Forbidden"}`                                                            | Renovar via `/oauth2/token` e refazer; ver [os formatos de erro](https://dev-hub.iorq.com.br/docs/configurando-webhooks#21-erros) |
| `400`         | API de cessão     | Header `iorq-fund-id` ausente em rota que o exige                                                                                   | `{"detail": "..."}`                                                                   | Incluir o UUID do fundo no header                                                                      |
| `400`         | Webhooks          | Header `iorq-fund-id` ausente ou fora do formato UUID                                                                               | `{"code": "bad_request", "message": "...", "details": null}`                          | Incluir o UUID do fundo no header                                                                      |
| `403`         | API de cessão     | Token válido, mas o `client_id` não tem permissão para o endpoint, ou o fundo está fora dos fundos provisionados                    | `{"detail": "..."}`                                                                   | Revisar permissões/fundos contratados; pedir ao seu contato na IORQ                                    |
| `403`         | Webhooks          | Token válido, mas o `client_id` não tem permissão para o endpoint, ou o fundo está fora dos fundos provisionados                    | `{"code": "forbidden", "message": "...", "details": null}`                            | Revisar permissões/fundos contratados; pedir ao seu contato na IORQ                                    |
| `401`         | API do investidor | Só `Authorization` **ausente**, recusado no gateway                                                                                 | `{"message": "Unauthorized"}`                                                         | Incluir o header                                                                                       |
| `401`         | API do investidor | Credencial desconhecida, suspensa ou removida                                                                                       | `{"message": "...", "status": 401, "error_code": "CALLER_NOT_PROVISIONED"}`           | Falar com o seu contato na IORQ                                                                        |
| `403`         | API do investidor | Token inválido ou expirado, recusado no gateway                                                                                     | `{"message": "Forbidden"}`                                                            | Renovar via `/oauth2/token` e refazer                                                                  |
| `400` e `403` | API do investidor | Header `iorq-fund-id` ausente ou fora do formato UUID (`400`); fundo não vinculado à credencial ou sem permissão de leitura (`403`) | `{"message": "...", "status": ..., "error_code": "..."}`                              | Ver [os erros da API do investidor](https://dev-hub.iorq.com.br/docs/api-do-investidor#4-erros)                                   |
| `422`         | Webhooks          | Corpo ou parâmetro inválido                                                                                                         | `{"code": "validation_error", "message": "...", "details": [{"loc", "msg", "type"}]}` | Corrigir o campo que o `msg` aponta                                                                    |
| `429`         | Autenticação      | Excesso de chamadas a `/oauth2/token`                                                                                               | —                                                                                     | Cachear o token até próximo do `exp` antes de renovar                                                  |

O serviço de webhooks (`webhook-sender-manager`) e a API do investidor ficam atrás de outros gateways e respondem ao token inválido ou expirado com **`403`**, não `401`: um cliente que só renova o token ao ver `401` fica preso no `403` lá. Trate `403` com corpo `{"message": "Forbidden"}` como "renove o token" em todos os serviços. A validação de corpo é `422` com `code: validation_error` e a lista em `details` no serviço de webhooks; na API de cessão os erros de validação de corpo estão em cada fluxo ([Cessão de operações](https://dev-hub.iorq.com.br/docs/cessao-de-operacoes), [Liquidação](https://dev-hub.iorq.com.br/docs/liquidacao)).

## 8. Próximos passos

<Cards columns={2}>
  <Card title="Próximo passo — Configurando webhooks" href="/docs/configurando-webhooks" icon="fa-arrow-right">
    Registre sua URL pública para receber os eventos.
  </Card>
  <Card title="Atalho — Quickstart" href="/docs/quickstart" icon="fa-arrow-right">
    Primeira cessão de ponta a ponta em sandbox.
  </Card>
</Cards>