> ## 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.

# Configurando um limite de gastos

> Limite o quanto uma conta, um portfólio ou um segmento pode gastar em um período com o Tracer, ative o teto e veja quanto dele resta a partir da decisão de validação.

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 decisão de produto ou de risco chegou como uma frase: "no máximo R\$ 20.000 por conta por mês." Este guia transforma essa frase em um teto ativo e mostra onde ler quanto dele resta para um cliente.

**O que muda na sua operação:** o teto deixa de ser uma constante compilada em um serviço. Ele passa a ser uma definição armazenada que você cria, ativa, aumenta e interrompe, e cada decisão que o toca reporta o que consumiu.

<Tip>
  **Para quem é este guia?** Times de produto e de risco que definem o teto, e desenvolvedores que conectam `POST /v1/validations` ao caminho de pagamento. Os passos 1 e 2 são decisões a tomar antes de qualquer chamada. Os passos 3 a 6 são as chamadas.
</Tip>

## Antes de começar

***

* [ ] Tracer em execução e acessível, com uma chave de API. Veja [Primeiros passos](./getting-started.mdx)
* [ ] O id da conta, do portfólio ou do segmento ao qual o teto se aplica
* [ ] O código do ativo das transações que você quer limitar
* [ ] Familiaridade com tipos de limite, janelas de tempo e períodos personalizados. Veja [Limites de gastos](./spending-limits.mdx)

Todas as chamadas abaixo enviam a chave de API como `X-API-Key` e rodam contra `http://localhost:4020`.

***

## Passo 1: Decida a quem o teto se dirige

***

Um limite carrega uma lista de objetos de escopo, e cada objeto nomeia a que o limite se aplica. Estes campos estão disponíveis dentro de um objeto:

| Campo             | Aplica o limite a                                                                                |
| ----------------- | ------------------------------------------------------------------------------------------------ |
| `accountId`       | Transações em uma conta                                                                          |
| `portfolioId`     | Transações em um portfólio                                                                       |
| `segmentId`       | Transações em um segmento                                                                        |
| `merchantId`      | Transações para um comerciante                                                                   |
| `transactionType` | Um entre `CARD`, `WIRE`, `PIX`, `CRYPTO`                                                         |
| `subType`         | Um subtipo de transação, como `purchase`, correspondido sem diferenciar maiúsculas de minúsculas |

Campos dentro de um mesmo objeto se combinam com AND. Um campo que você omite funciona como curinga. Entre objetos, a lista se combina com OR, então um limite com dois objetos se aplica quando qualquer um deles corresponde.

A escolha que decide a resposta para "R\$ 20.000 por conta" é **qual id você nomeia**:

<Tabs>
  <Tab title="Uma conta, seu próprio orçamento">
    ```json theme={null}
    "scopes": [
      { "accountId": "550e8400-e29b-41d4-a716-446655440100" }
    ]
    ```

    O teto se aplica a essa conta. Ele conta os gastos dessa conta e de nenhuma outra. Para um teto por conta em uma carteira de clientes, cada conta recebe seu próprio limite.
  </Tab>

  <Tab title="Um segmento, um orçamento compartilhado">
    ```json theme={null}
    "scopes": [
      { "segmentId": "2f1c9b7e-40a5-4d18-9c6b-3e7f5a0d1b24" }
    ]
    ```

    O teto se aplica ao segmento como um todo. Toda conta desse segmento consome o mesmo R\$ 20.000 (os primeiros clientes a gastar o consomem para os demais).
  </Tab>

  <Tab title="Restrito a um trilho">
    ```json theme={null}
    "scopes": [
      {
        "accountId": "550e8400-e29b-41d4-a716-446655440100",
        "transactionType": "PIX"
      }
    ]
    ```

    O teto conta apenas as transações Pix dessa conta. Seu tráfego de cartão e de transferência passa sem tocar esse limite.
  </Tab>
</Tabs>

<Note>
  Um limite também carrega um `asset`, e o Tracer apenas confere um limite contra uma transação quando os dois correspondem. O Tracer não confere um limite criado em `BRL` contra uma transação em `USD`. Uma carteira que liquida em duas moedas precisa de um limite para cada uma.
</Note>

Um limite deve carregar pelo menos um objeto de escopo, e cada objeto deve definir pelo menos um campo. O Tracer rejeita uma lista vazia ou um objeto vazio. Veja [O que dá errado](#what-goes-wrong).

***

## Passo 2: Escolha o período

***

`limitType` decide tanto o tamanho da janela do teto quanto quando uma nova contagem começa. O Tracer oferece cinco:

| `limitType`       | A contagem cobre                      | Uma nova contagem começa                                              |
| ----------------- | ------------------------------------- | --------------------------------------------------------------------- |
| `DAILY`           | Um dia civil, UTC                     | Todo dia às 00:00 UTC                                                 |
| `WEEKLY`          | Uma semana ISO, UTC                   | Toda segunda-feira às 00:00 UTC                                       |
| `MONTHLY`         | Um mês civil, UTC                     | No dia 1º às 00:00 UTC                                                |
| `CUSTOM`          | Um intervalo de datas que você define | Nunca: uma única contagem cobre todo o intervalo                      |
| `PER_TRANSACTION` | Uma única transação                   | Nenhuma contagem é mantida; cada transação é medida por conta própria |

"por mês" é `MONTHLY`.

<Warning>
  **A fronteira é UTC, não o horário local.** Um cliente em São Paulo gastando às 21:30 do dia 31 de julho está às 00:30 UTC do dia 1º de agosto. Esse valor entra na contagem de agosto, não na de julho. Quando um teto usa termos locais, espere que as últimas horas do mês local pertençam ao mês seguinte.
</Warning>

`CUSTOM` recebe `customStartDate` e `customEndDate` e é o formato para uma campanha ou uma promoção. Esses dois campos pertencem a `CUSTOM`. O Tracer os rejeita nos outros quatro tipos. Para restringir um teto a certas horas do dia, veja [janelas de tempo](./spending-limits.mdx#time-windows).

***

## Passo 3: Crie o limite

***

`POST /v1/limits` armazena a definição. O Tracer a cria em `DRAFT` e ainda não a confere contra transações.

```bash theme={null}
curl -X POST http://localhost:4020/v1/limits \
  -H "X-API-Key: your-secure-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Monthly Account Spending Cap",
    "description": "Caps total monthly outflow for one account",
    "limitType": "MONTHLY",
    "maxAmount": "20000.00",
    "asset": "BRL",
    "scopes": [
      { "accountId": "550e8400-e29b-41d4-a716-446655440100" }
    ]
  }'
```

Uma chamada bem-sucedida responde `201`. O corpo carrega o limite armazenado. Dois campos importam agora:

| Campo     | O que fazer com ele                                                                          |
| --------- | -------------------------------------------------------------------------------------------- |
| `limitId` | O id que toda chamada posterior deste guia usa. Guarde-o                                     |
| `status`  | `DRAFT`: o limite ainda não está sendo conferido. O [Passo 4](#step-4-activate-it) muda isso |

<Note>
  **Os nomes são únicos entre limites, e o conjunto de caracteres é restrito.** `name` aceita letras ASCII e dígitos, espaços, e `-`, `_`, `.`, `(`, `)`. O Tracer rejeita um acento, ou um traço digitado como travessão, com `0371`. O Tracer rejeita um nome que outro limite ativo já possui, com `0442`. Excluir um limite libera o nome novamente.
</Note>

Para o payload completo e todos os campos opcionais, veja [Criar um limite](/pt/reference/products/tracer/create-limit).

***

<h2 id="step-4-activate-it">
  Passo 4: Ative-o
</h2>

***

O Tracer não confere um limite em `DRAFT`. A ativação é o que o coloca no caminho:

```bash theme={null}
curl -X POST http://localhost:4020/v1/limits/{limitId}/activate \
  -H "X-API-Key: your-secure-api-key"
```

A resposta carrega o limite com `status` definido como `ACTIVE`. A partir daqui, o Tracer confere contra este limite toda `POST /v1/validations` cuja transação corresponda ao escopo e ao ativo.

<Note>
  **Ativar no meio do mês não importa o histórico do mês.** O Tracer conta uma transação contra um limite no momento em que decide sobre ela. Gastos que aconteceram enquanto o limite estava em `DRAFT` não entram na contagem. Um teto ativado no dia 20 rege o que acontece a partir do dia 20.
</Note>

Veja [Ativar um limite](/pt/reference/products/tracer/activate-limit).

***

## Passo 5: Veja quanto resta

***

Toda resposta de `POST /v1/validations` carrega `limitUsageDetails`, com uma entrada para cada limite que o Tracer conferiu:

```json theme={null}
{
  "limitId": "b2d4f6a8-1c3e-4507-9b8d-6f0a2c4e6810",
  "limitAmount": "20000",
  "scope": "(account:550e8400-e29b-41d4-a716-446655440100)",
  "period": "MONTHLY",
  "currentUsage": "20000",
  "attemptedAmount": "1500",
  "exceeded": false
}
```

| Campo             | O que reporta                                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------------------------- |
| `limitAmount`     | O teto que foi conferido                                                                                   |
| `currentUsage`    | Consumo projetado do período atual e do escopo correspondido desse limite, se esta transação for permitida |
| `attemptedAmount` | O valor medido contra o teto                                                                               |
| `period`          | O tipo do limite: `MONTHLY` aqui                                                                           |
| `scope`           | O escopo do limite como texto, cada objeto entre parênteses, vários objetos unidos por `OR`                |
| `exceeded`        | Se o valor levaria este teto a ultrapassar seu limite                                                      |

No exemplo acima, uma compra de R\$ 1.500 levou um mês que estava em 18.500 a exatamente 20.000 e esgotou o teto. O Tracer nega a próxima transação nessa conta até agosto.

Quando uma transação excede um limite, a decisão é `DENY` e `reason` é `limit_exceeded`. O Tracer não soma à contagem o valor que teria cruzado o teto. Um limite produz uma negação, não um sinalizador para revisão. Para ir de uma negação dessas de volta ao limite que a causou, veja [Revisando uma transação negada](./reviewing-a-denied-transaction.mdx).

### A outra leitura

`GET /v1/limits/{limitId}/usage` responde com um total do limite, não de um período. Ele soma os contadores de uso registrados contra ele, entre os períodos e escopos que acumulou. Use-o para revisar quanto um limite absorveu no total, não para responder quanto resta a um cliente este mês.

O Tracer exclui um contador 90 dias após o fim do seu período. Em um limite de longa duração, esse total cobre apenas os períodos ainda retidos, não o ciclo de vida completo do limite. Veja [Rastreamento de uso](./spending-limits.mdx#usage-tracking).

Veja [Obter um snapshot de uso de um limite](/pt/reference/products/tracer/retrieve-limit-usage).

***

## Passo 6: Altere, pause ou remova

***

<Steps>
  <Step title="Aumente ou diminua o teto">
    ```bash theme={null}
    curl -X PATCH http://localhost:4020/v1/limits/{limitId} \
      -H "X-API-Key: your-secure-api-key" \
      -H "Content-Type: application/json" \
      -d '{ "maxAmount": "30000.00" }'
    ```

    `name`, `description`, `maxAmount` e `scopes` são editáveis, assim como os campos de janela de tempo e de período personalizado. `limitType` e `asset` não são. O Tracer rejeita uma requisição que envie qualquer um dos dois com `0380`, e um período ou ativo diferente significa um novo limite. O Tracer rejeita um corpo vazio com `0183`. Veja [Atualizar um limite](/pt/reference/products/tracer/update-limit).

    Alterar o teto não limpa a contagem em andamento. Diminua-o abaixo do que o período atual já consumiu, e o Tracer nega a conta até o próximo período começar.
  </Step>

  <Step title="Pare de aplicá-lo">
    ```bash theme={null}
    curl -X POST http://localhost:4020/v1/limits/{limitId}/deactivate \
      -H "X-API-Key: your-secure-api-key"
    ```

    O limite passa para `INACTIVE` e o Tracer para de conferi-lo. Ele mantém sua definição e seu lugar na <GAuditTrail>trilha de auditoria</GAuditTrail>, e `POST /v1/limits/{limitId}/activate` o coloca de volta no caminho. Veja [Desativar um limite](/pt/reference/products/tracer/deactivate-limit).
  </Step>

  <Step title="Volte-o para rascunho">
    ```bash theme={null}
    curl -X POST http://localhost:4020/v1/limits/{limitId}/draft \
      -H "X-API-Key: your-secure-api-key"
    ```

    Move um limite `INACTIVE` de volta para `DRAFT`. Veja [Retornar um limite ao rascunho](/pt/reference/products/tracer/draft-limit).
  </Step>

  <Step title="Remova-o">
    ```bash theme={null}
    curl -X DELETE http://localhost:4020/v1/limits/{limitId} \
      -H "X-API-Key: your-secure-api-key"
    ```

    Responde `204`. Você precisa desativar antes um limite que está `ACTIVE` no momento. O Tracer rejeita a exclusão com `0363`, que é o que evita que um teto ativo desapareça por acidente. Veja [Excluir um limite](/pt/reference/products/tracer/delete-limit).
  </Step>
</Steps>

### Encontre os limites que você já tem

`GET /v1/limits` os lista, e filtra pelos mesmos campos de escopo que você definiu no Passo 1:

```http theme={null}
GET /v1/limits?status=ACTIVE&account_id=550e8400-e29b-41d4-a716-446655440100&limit_type=MONTHLY
X-API-Key: {api_key}
```

`name`, `status`, `limit_type`, `account_id`, `segment_id`, `portfolio_id`, `merchant_id`, `transaction_type` e `sub_type` filtram. Os resultados são paginados por cursor. Veja [Listar limites](/pt/reference/products/tracer/list-limits), e [Obter um limite](/pt/reference/products/tracer/retrieve-limit) para um por id.

***

<h2 id="what-goes-wrong">
  O que dá errado
</h2>

***

<Warning>
  **O que costuma dar errado ao configurar um teto:**

  * **"O cliente gastou mais do que devia e nada o impediu."** Confira `status` primeiro. O Tracer não confere um limite em `DRAFT` ou `INACTIVE`. Depois, confira se o `asset` do limite corresponde ao da transação, e se o escopo nomeia o id que a transação realmente carregou.
  * **"O teto do segmento acabou no segundo dia."** Um limite com escopo de segmento é um único orçamento para o segmento inteiro, não um por conta dentro dele. Um teto por conta significa um limite endereçado a cada conta.
  * **"O mês virou algumas horas mais cedo."** As fronteiras de período são UTC. Gastos após as 21:00 em UTC-3 pertencem ao próximo dia UTC, e no último dia do mês, ao mês seguinte.
  * **"Aumentei o limite e a conta continua sendo negada."** Aumentar o teto não limpa a contagem. Confirme que o novo `maxAmount` está acima do que o período já consumiu.
  * **"`GET /v1/limits/{id}/usage` reporta mais do que o cliente gastou este mês."** Esse endpoint totaliza os contadores registrados para o limite, entre períodos e escopos. Para o período atual, leia `limitUsageDetails` na resposta de validação.
</Warning>

### Códigos de erro

| Código | Status | O que mudar                                                                                                                                                                                    |
| ------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0009` | 400    | Um campo falhou na validação: `detail` o nomeia, por exemplo `scopes must have at least 1 item(s)`, `scope at index 0 must have at least one field set`, ou `maxAmount must be greater than 0` |
| `0065` | 400    | O id no caminho não é um UUID                                                                                                                                                                  |
| `0183` | 400    | O corpo do `PATCH` não carregou nenhum campo editável                                                                                                                                          |
| `0362` | 404    | Nenhum limite tem esse id                                                                                                                                                                      |
| `0363` | 422    | A transição não é permitida: excluir um limite `ACTIVE`, por exemplo                                                                                                                           |
| `0366` | 400    | `asset` tem três letras maiúsculas mas não é um código ISO 4217                                                                                                                                |
| `0371` | 400    | `name` carrega um caractere que o campo não aceita                                                                                                                                             |
| `0380` | 422    | A requisição tentou mudar `limitType` ou `asset`                                                                                                                                               |
| `0442` | 409    | Outro limite ativo já possui esse nome                                                                                                                                                         |

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

***

## Referência rápida

***

| Passo                           | Método | Endpoint                         |
| ------------------------------- | ------ | -------------------------------- |
| Criar um limite                 | POST   | `/v1/limits`                     |
| Ativá-lo                        | POST   | `/v1/limits/{id}/activate`       |
| Ler o consumo com a decisão     | POST   | `/v1/validations`                |
| Ler o total acumulado do limite | GET    | `/v1/limits/{id}/usage`          |
| Alterar o teto                  | PATCH  | `/v1/limits/{id}`                |
| Parar de aplicá-lo              | POST   | `/v1/limits/{id}/deactivate`     |
| Voltá-lo para rascunho          | POST   | `/v1/limits/{id}/draft`          |
| Removê-lo                       | DELETE | `/v1/limits/{id}`                |
| Encontrar limites               | GET    | `/v1/limits` · `/v1/limits/{id}` |
