> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Revisando uma transação negada

> Leia uma decisão DENY ou REVIEW do Tracer para encontrar a regra ou o limite por trás dela, recupere o registro armazenado depois e verifique o evento de auditoria durante uma auditoria.

export const GAuditTrail = ({children}) => <Tooltip headline="Trilha de auditoria" tip="Um registro cronológico e imutável de cada ação e transação no sistema, essencial para conformidade regulatória e resolução de disputas." cta="Ver glossário" href="/pt/start-here/glossary">
    {children}
  </Tooltip>;

Uma validação voltou como `DENY` ou `REVIEW` e alguém pergunta o motivo. Este guia leva você da decisão que o Tracer retornou até uma regra nomeada ou um limite de gastos nomeado. A partir daí, você chega ao registro armazenado e ao evento da <GAuditTrail>trilha de auditoria</GAuditTrail> que pode entregar a um auditor meses depois.

**O que muda na sua operação:** a resposta para "por que isso foi bloqueado?" deixa de ser uma busca em log. Cada decisão chega com os identificadores do que a produziu. O mesmo registro responde pelo id anos depois, e você pode conferir seu evento de auditoria contra a cadeia de hash.

<Tip>
  **Para quem é este guia?** Desenvolvedores integrando a chamada de validação, times de suporte e de disputas respondendo perguntas de clientes, e responsáveis por compliance preparando evidências. Os passos 1 a 4 precisam apenas da resposta que você já tem. Os passos 5 a 8 usam os endpoints de consulta.
</Tip>

## Antes de começar

***

* [ ] Tracer em execução e acessível, com uma chave de API. Veja [Primeiros passos](./getting-started.mdx)
* [ ] Uma resposta `DENY` ou `REVIEW` para trabalhar, ou o `validationId` de uma delas
* [ ] Familiaridade com o que regras e limites fazem. Veja o [Motor de regras](./rule-engine.mdx) e [Limites de gastos](./spending-limits.mdx)

Todas as chamadas abaixo enviam a chave de API como `X-API-Key`.

***

## Passo 1: Leia a decisão que o Tracer retornou

***

`POST /v1/validations` responde com a decisão completa. Uma nova requisição responde `201`. Um `requestId` repetido responde `200` com a decisão que o Tracer já havia registrado para essa chave.

```bash theme={null}
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)

curl -X POST http://localhost:4020/v1/validations \
  -H "X-API-Key: your-secure-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "requestId": "7c3f1b8e-5a2d-4c6b-9e1f-0a4d8b2c6e30",
    "transactionType": "CARD",
    "subType": "purchase",
    "amount": "1500.00",
    "asset": "BRL",
    "transactionTimestamp": "'"$TS"'",
    "account": {
      "accountId": "550e8400-e29b-41d4-a716-446655440100",
      "type": "checking",
      "status": "active"
    },
    "merchant": {
      "merchantId": "550e8400-e29b-41d4-a716-446655440103",
      "category": "5411",
      "country": "BR",
      "name": "Acme Store"
    },
    "metadata": {
      "channel": "mobile"
    }
  }'
```

Uma negativa produzida por uma regra se parece com isto:

```json theme={null}
{
  "validationId": "8f14e45f-ea3b-4c6e-9a1c-2b7d5e0a91c4",
  "requestId": "7c3f1b8e-5a2d-4c6b-9e1f-0a4d8b2c6e30",
  "decision": "DENY",
  "matchedRuleIds": [
    "3c8a5b21-9f4d-4e17-8b6a-1d2e3f405162"
  ],
  "evaluatedRuleIds": [
    "3c8a5b21-9f4d-4e17-8b6a-1d2e3f405162",
    "a6b7c8d9-0e1f-4a2b-9c3d-4e5f60718293"
  ],
  "reason": "Rule matched with DENY action",
  "totalRulesLoaded": 2,
  "truncated": false,
  "limitUsageDetails": [],
  "processingTimeMs": 9.4,
  "evaluatedAt": "2026-07-31T14:05:09.481Z"
}
```

| Campo                              | O que ele te diz                                                                            |
| ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `validationId`                     | A chave desta decisão. Tudo o que vem depois neste guia começa a partir dela                |
| `decision`                         | `ALLOW`, `DENY` ou `REVIEW`                                                                 |
| `reason`                           | O que produziu a decisão — veja o [Passo 2](#step-2-tell-a-rule-denial-from-a-limit-denial) |
| `matchedRuleIds`                   | Toda regra que combinou com esta transação, qualquer que seja a ação que ela carregue       |
| `evaluatedRuleIds`                 | As regras que o Tracer avaliou para esta transação                                          |
| `limitUsageDetails`                | Uma entrada por limite de gastos que o Tracer verificou                                     |
| `totalRulesLoaded` / `truncated`   | Quantas regras foram carregadas, e se `MAX_RULES_PER_REQUEST` cortou o conjunto             |
| `processingTimeMs` / `evaluatedAt` | Quanto tempo a avaliação levou, e quando ela rodou                                          |

Para o schema completo de requisição e resposta, veja [Validar uma transação](/pt/reference/products/tracer/validate-transaction).

<Note>
  Armazene o `validationId` junto ao registro da sua própria transação. É a chave que o [Passo 5](#step-5-retrieve-the-record-later) usa, e também é o `resourceId` do evento de auditoria no [Passo 7](#step-7-pull-the-audit-event-behind-the-decision).
</Note>

***

<h2 id="step-2-tell-a-rule-denial-from-a-limit-denial">
  Passo 2: Diferencie uma negativa de regra de uma negativa de limite
</h2>

***

Leia `reason` primeiro. Ele nomeia o que produziu a decisão, e diz qual dos dois próximos passos seguir.

| `reason`                        | O que aconteceu                                                                 | Vá para                                                                                           |
| ------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `Rule matched with DENY action` | Uma regra cuja ação é `DENY` combinou                                           | [Passo 3](#step-3-name-the-rule)                                                                  |
| `limit_exceeded`                | O valor levaria um limite de gastos além do seu teto                            | [Passo 4](#step-4-name-the-spending-limit)                                                        |
| `No matching rules found`       | Nenhuma regra combinou, então o Tracer aplicou `DEFAULT_DECISION_WHEN_NO_MATCH` | Revise essa configuração na página de [variáveis de ambiente](./tracer-environment-variables.mdx) |

`reason` traz o mesmo texto em decisões `REVIEW` (`Rule matched with REVIEW action`), e o Passo 3 lê uma revisão do mesmo jeito que lê uma negativa.

<Note>
  Em uma negativa de regra, `limitUsageDetails` volta vazio porque o Tracer para antes da verificação de limite, não porque nenhum limite se aplica à conta.
</Note>

***

<h2 id="step-3-name-the-rule">
  Passo 3: Nomeie a regra
</h2>

***

`matchedRuleIds` lista toda regra que combinou, qualquer que seja a ação que cada uma carregue. Uma regra `DENY` e uma regra `ALLOW` podem aparecer juntas na mesma negativa. Recupere cada uma e leia sua `action` para encontrar a regra por trás da decisão:

```http theme={null}
GET /v1/rules/3c8a5b21-9f4d-4e17-8b6a-1d2e3f405162
X-API-Key: {api_key}
```

A regra carrega o `name`, `description`, `expression`, `action` e `scopes` que um colega precisa ver para entender por que ela disparou. Veja [Recuperar uma regra](/pt/reference/products/tracer/retrieve-rule).

Compare `matchedRuleIds` com `evaluatedRuleIds` quando a pergunta for a oposta: "por que minha regra *não* disparou?". O Tracer não avaliou uma regra que está ausente de `evaluatedRuleIds`. Comece pelo status e pelo escopo dela, em vez da expressão.

<Tip>
  Uma regra excluída desde a decisão não responde mais em `GET /v1/rules/{id}`. Seu histórico, incluindo quem a excluiu, permanece na trilha de auditoria. Veja [Auditoria e compliance](./audit-compliance.mdx).
</Tip>

***

<h2 id="step-4-name-the-spending-limit">
  Passo 4: Nomeie o limite de gastos
</h2>

***

Em uma negativa `limit_exceeded`, `limitUsageDetails` guarda uma entrada por limite que o Tracer verificou, e as entradas marcadas `"exceeded": true` são as que o valor levaria além do teto:

```json theme={null}
{
  "validationId": "8f14e45f-ea3b-4c6e-9a1c-2b7d5e0a91c4",
  "requestId": "7c3f1b8e-5a2d-4c6b-9e1f-0a4d8b2c6e30",
  "decision": "DENY",
  "matchedRuleIds": [],
  "evaluatedRuleIds": [
    "a6b7c8d9-0e1f-4a2b-9c3d-4e5f60718293"
  ],
  "reason": "limit_exceeded",
  "totalRulesLoaded": 2,
  "truncated": false,
  "limitUsageDetails": [
    {
      "limitId": "b2d4f6a8-1c3e-4507-9b8d-6f0a2c4e6810",
      "limitAmount": "50000",
      "scope": "(segment:2f1c9b7e-40a5-4d18-9c6b-3e7f5a0d1b24,transactionType:CARD)",
      "period": "DAILY",
      "currentUsage": "51500",
      "attemptedAmount": "1500",
      "exceeded": true
    },
    {
      "limitId": "d4f6a8b2-3e5c-4709-8b6d-0a2c4e681012",
      "limitAmount": "400000",
      "scope": "(account:550e8400-e29b-41d4-a716-446655440100)",
      "period": "MONTHLY",
      "currentUsage": "128400",
      "attemptedAmount": "1500",
      "exceeded": false
    }
  ],
  "processingTimeMs": 14.2,
  "evaluatedAt": "2026-07-31T14:05:09.481Z"
}
```

Leia a entrada excedida como a aritmética da negativa: `attemptedAmount` contra `limitAmount`. O campo `currentUsage` reporta o que o período atual e o escopo combinado desse limite conteriam com esta transação incluída. No exemplo acima, uma compra de `1500` levaria um teto diário de `50000` a `51500`.

Um limite `PER_TRANSACTION` não mantém contagem, então sua entrada reporta `currentUsage` como `0`, e `attemptedAmount` contra `limitAmount` é toda a comparação.

`GET /v1/limits/{limitId}` retorna o nome e a configuração atuais do limite. Veja [Recuperar um limite](/pt/reference/products/tracer/retrieve-limit). O registro da decisão guarda o teto, o período e o escopo que se aplicavam quando o Tracer tomou a decisão. Um limite alterado depois disso não muda o que o registro diz.

Para como cada período conta e como o consumo acumula, veja [Limites de gastos](./spending-limits.mdx).

***

<h2 id="step-5-retrieve-the-record-later">
  Passo 5: Recupere o registro depois
</h2>

***

O Tracer armazena toda decisão sob seu `validationId`:

```http theme={null}
GET /v1/validations/8f14e45f-ea3b-4c6e-9a1c-2b7d5e0a91c4
X-API-Key: {api_key}
```

O registro responde com o contexto da transação que o Tracer avaliou (`transactionType`, `amount`, `asset`, `transactionTimestamp`, `account`, e os campos opcionais `segment`, `portfolio`, `merchant` e `metadata`), além dos mesmos `decision`, `reason`, `matchedRuleIds`, `evaluatedRuleIds` e `limitUsageDetails` que a resposta original carregava, e um `createdAt`. Veja [Recuperar uma validação](/pt/reference/products/tracer/retrieve-validation).

Leia este registro em uma disputa. Ele guarda a entrada e o resultado em um único documento. Ele não muda quando regras ou limites mudam depois.

***

## Passo 6: Encontre registros quando você não tem o id

***

`GET /v1/validations` lista decisões armazenadas, da mais recente para a mais antiga, com paginação por cursor:

```http theme={null}
GET /v1/validations?decision=DENY&account_id=550e8400-e29b-41d4-a716-446655440100&start_date=2026-07-01T00:00:00Z&end_date=2026-07-31T23:59:59Z
X-API-Key: {api_key}
```

<Warning>
  **Uma consulta sem datas cobre os últimos 90 dias, não o período completo de retenção.** O Tracer aplica essa janela padrão apenas quando `start_date` e `end_date` estão ambos ausentes. Envie um dos dois, ou os dois, para alcançar um intervalo mais antigo.
</Warning>

Dois filtros respondem às perguntas para as quais este guia existe:

* `matched_rule_id={ruleId}`: toda decisão armazenada com a qual esta regra combinou
* `exceeded_limit_id={limitId}`: toda decisão armazenada que este limite bloqueou

Cada resultado é um resumo: `validationId`, `decision`, `reason`, `amount`, `asset`, `transactionType`, `accountId`, `matchedRuleIds`, `exceededLimitIds`, `processingTimeMs` e `createdAt`. Pegue o `validationId` do que você quer e recupere-o com o Passo 5 para o registro completo. Veja [Listar validações](/pt/reference/products/tracer/list-validations) para todo filtro e os campos de paginação.

***

<h2 id="step-7-pull-the-audit-event-behind-the-decision">
  Passo 7: Extraia o evento de auditoria por trás da decisão
</h2>

***

A trilha de auditoria registra a decisão sob o `validationId` como o `resourceId` do evento:

```http theme={null}
GET /v1/audit-events?resource_type=transaction&resource_id=8f14e45f-ea3b-4c6e-9a1c-2b7d5e0a91c4
X-API-Key: {api_key}
```

```json theme={null}
{
  "auditEvents": [
    {
      "hash": "a3f1e2b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2",
      "previousHash": "b4e2f3a5c6d7e8f9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3",
      "eventId": "1d0a6f52-7b3c-4e8d-9a01-5c2b6e7f8091",
      "eventType": "TRANSACTION_VALIDATED",
      "createdAt": "2026-07-31T14:05:09.492Z",
      "action": "VALIDATE",
      "result": "DENY",
      "resourceId": "8f14e45f-ea3b-4c6e-9a1c-2b7d5e0a91c4",
      "resourceType": "transaction",
      "actor": {
        "actorType": "api_key",
        "id": "tracer-default",
        "name": "",
        "ipAddress": "203.0.113.42"
      },
      "context": {
        "request": {
          "requestId": "7c3f1b8e-5a2d-4c6b-9e1f-0a4d8b2c6e30",
          "transactionType": "CARD",
          "amount": "1500",
          "asset": "BRL"
        },
        "response": {
          "decision": "DENY",
          "reason": "Rule matched with DENY action",
          "matchedRuleIds": [
            "3c8a5b21-9f4d-4e17-8b6a-1d2e3f405162"
          ],
          "evaluatedRuleIds": [
            "3c8a5b21-9f4d-4e17-8b6a-1d2e3f405162",
            "a6b7c8d9-0e1f-4a2b-9c3d-4e5f60718293"
          ],
          "totalRulesLoaded": 2,
          "truncated": false,
          "limitUsageDetails": [],
          "processingTimeMs": 9.4
        }
      }
    }
  ],
  "hasMore": false
}
```

O que o evento de auditoria acrescenta ao registro de validação:

| Campo              | Por que importa em uma revisão                                                                                                                                     |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `actor`            | Quem fez a chamada — a identidade por trás da requisição, e o IP do cliente                                                                                        |
| `result`           | A decisão, indexada para filtragem, então `result=DENY` restringe uma consulta                                                                                     |
| `context.request`  | O instantâneo da requisição registrado com a decisão                                                                                                               |
| `context.response` | A decisão, o motivo e os identificadores de regra como foram retornados                                                                                            |
| `eventId`          | A chave para o [Passo 8](#step-8-verify-the-audit-event-in-an-audit) e para [Recuperar um evento de auditoria](/pt/reference/products/tracer/retrieve-audit-event) |

<Warning>
  A janela padrão de 90 dias se aplica aqui também: `GET /v1/audit-events` sem `start_date` nem `end_date` cobre os últimos 90 dias. Envie o intervalo que você quer quando a decisão for mais antiga que isso.
</Warning>

O mesmo endpoint carrega o ciclo de vida de regras e limites: quem os criou, ativou ou excluiu. Veja [Listar eventos de auditoria](/pt/reference/products/tracer/list-audit-events) para os filtros, e [Auditoria e compliance](./audit-compliance.mdx) para os tipos de evento e os períodos de retenção.

***

<h2 id="step-8-verify-the-audit-event-in-an-audit">
  Passo 8: Verifique o evento de auditoria em uma auditoria
</h2>

***

Passe o `eventId` para o endpoint de verificação:

```http theme={null}
GET /v1/audit-events/1d0a6f52-7b3c-4e8d-9a01-5c2b6e7f8091/verify
X-API-Key: {api_key}
```

```json theme={null}
{
  "isValid": true,
  "totalChecked": 12345,
  "message": "Hash chain integrity verified successfully"
}
```

`isValid: true` estabelece que todo registro do primeiro até o que você nomeou ainda corresponde ao hash armazenado com ele. Cada um também se liga ao hash do registro anterior a ele. Dentro desse intervalo, nenhum registro foi removido, reordenado ou teve a data alterada. `totalChecked` reporta quantos registros a verificação cobriu.

Em uma verificação com falha, `isValid` é `false`, `message` reporta adulteração, e `firstInvalidId` carrega um número de sequência interno para o registro divergente. Esse número não é um id de evento de auditoria, então não é um valor para passar a `GET /v1/audit-events/{id}`.

Veja [Verificar um evento de auditoria](/pt/reference/products/tracer/verify-audit-event).

<Note>
  Entregue os dois juntos: o evento recuperado no Passo 7 é o conteúdo da decisão, e o resultado da verificação é a evidência de que a cadeia que o guarda está íntegra. A chamada de verificação reporta sobre a cadeia. Ela não retorna o registro.
</Note>

***

## Armadilhas comuns

***

<Warning>
  **O que costuma dar errado em uma revisão:**

  * **"Minha consulta do ano passado voltou vazia."** Uma consulta sem `start_date` e sem `end_date` cobre os últimos 90 dias. Envie o intervalo que você quer.
  * **"`matchedRuleIds` tem três entradas e apenas uma negou."** O array guarda toda regra que combinou, qualquer que seja a ação que ela carregue. Recupere cada regra e leia sua `action` (Passo 3).
  * **"`limitUsageDetails` está vazio em uma negativa."** A decisão veio de uma regra, não de um limite. Leia `reason` (Passo 2).
  * **"`currentUsage` está mais alto do que o cliente realmente gastou."** Ele já inclui o valor tentado, então é uma projeção. Em um limite excedido, o contador permanece o mesmo, então o consumo armazenado não inclui esta transação.
  * **"A regra que disparou não existe mais."** Regras excluídas param de responder em `GET /v1/rules/{id}`. Consulte seu ciclo de vida por `GET /v1/audit-events?resource_type=rule&resource_id={ruleId}`.
</Warning>

### Códigos de erro

| Código          | Status | O que mudar                                                                                |
| --------------- | ------ | ------------------------------------------------------------------------------------------ |
| `0065`          | 400    | O id no caminho não é um UUID                                                              |
| `0432`          | 404    | Nenhuma validação armazenada tem esse `validationId`                                       |
| `0381`          | 404    | Nenhum evento de auditoria tem esse `eventId`                                              |
| `0077`          | 400    | Uma data não está em RFC3339 com timezone — envie `2026-07-01T00:00:00Z`, não `2026-07-01` |
| `0083`          | 400    | `end_date` vem antes de `start_date`                                                       |
| `0431`          | 400    | Um filtro em `GET /v1/validations` carrega um valor que o endpoint não aceita              |
| `0080` / `0331` | 400    | `limit` está acima de 1000, ou não é positivo                                              |
| `0334`          | 400    | `cursor` foi enviado junto com `sort_by` ou `sort_order` — o cursor já os carrega          |

A lista completa está na [lista de erros do Tracer](/pt/reference/products/tracer/tracer-error-list).

***

## Referência rápida

***

| Passo                            | Método | Endpoint                       |
| -------------------------------- | ------ | ------------------------------ |
| Validar uma transação            | POST   | `/v1/validations`              |
| Encontrar decisões armazenadas   | GET    | `/v1/validations`              |
| Recuperar uma decisão            | GET    | `/v1/validations/{id}`         |
| Nomear uma regra                 | GET    | `/v1/rules/{id}`               |
| Nomear um limite                 | GET    | `/v1/limits/{id}`              |
| Encontrar eventos de auditoria   | GET    | `/v1/audit-events`             |
| Recuperar um evento de auditoria | GET    | `/v1/audit-events/{id}`        |
| Verificar a cadeia de hash       | GET    | `/v1/audit-events/{id}/verify` |
