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

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 passa de uma constante compilada em um serviço para uma definição armazenada que você cria, ativa, aumenta e interrompe. Cada decisão que o toca reporta o que consumiu.

> [!TIP]
>
> **Este guia é para** 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.

## Antes de começar

***

* [ ] Tracer em execução e acessível, com uma chave de API. Veja [Primeiros passos](https://docs.lerian.studio/pt/products/tracer/getting-started.md)
* [ ] 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](https://docs.lerian.studio/pt/products/tracer/spending-limits.md)

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 |
| `scheme` | Um esquema de pagamento, como `CARD` ou `PIX`. `transactionType` é o nome obsoleto desse campo |
| `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.

O id que você nomeia decide a resposta para "R\$ 20.000 por conta":

> [tab] 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] 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] Restrito a um trilho
>
> ```json theme={null}
> "scopes": [
>   {
>     "accountId": "550e8400-e29b-41d4-a716-446655440100",
>     "scheme": "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.

> [!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.

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, UTC | Todo dia no horário de reinício (00:00 UTC por padrão) |
| `WEEKLY` | Uma semana, UTC | Toda segunda-feira no horário de reinício (00:00 UTC por padrão) |
| `MONTHLY` | Um mês, UTC | No dia 1º no horário de reinício (00:00 UTC por padrão) |
| `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. Sem `resetTime`, esse valor entra na contagem de agosto, não na de julho.

Para mover a fronteira, defina `resetTime` em `HH:MM` UTC ao criar um limite `DAILY`, `WEEKLY` ou `MONTHLY`. Por exemplo, `"03:00"` começa cada período à meia-noite em São Paulo (UTC-3). Você não pode alterar `resetTime` após a criação. Veja [Horário de reinício](https://docs.lerian.studio/pt/products/tracer/spending-limits.md#reset-time).

`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](https://docs.lerian.studio/pt/products/tracer/spending-limits.md#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`, então o Tracer ainda não confere o limite. 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.

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

***

## Passo 4: Ative-o

***

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

Veja [Ativar um limite](https://docs.lerian.studio/pt/reference/products/tracer/activate-limit.md).

***

## 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, incluindo a capacidade retida por reservas não confirmadas do ledger do Midaz. `0` para um limite `PER_TRANSACTION` |
| `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](https://docs.lerian.studio/pt/products/tracer/reviewing-a-denied-transaction.md).

### A outra leitura

`GET /v1/limits/{limitId}/usage` responde pelo período atual do limite. Ele reporta o escopo que mais consumiu e conta a capacidade retida por reservas não confirmadas do ledger do Midaz. Use-o para ver quanto do teto o período atual já consumiu.

Veja [Obter um snapshot de uso de um limite](https://docs.lerian.studio/pt/reference/products/tracer/retrieve-limit-usage.md).

***

## Passo 6: Altere, pause ou remova

***

**1. 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`, `asset` e `resetTime` não são. O Tracer rejeita uma requisição que envie qualquer um deles com `0380`, e um período, ativo ou horário de reinício diferente significa um novo limite. O Tracer rejeita um corpo vazio com `0183`. Veja [Atualizar um limite](https://docs.lerian.studio/pt/reference/products/tracer/update-limit.md).

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.

**2. 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 trilha de auditoria (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.), e `POST /v1/limits/{limitId}/activate` o coloca de volta no caminho. Veja [Desativar um limite](https://docs.lerian.studio/pt/reference/products/tracer/deactivate-limit.md).

**3. 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](https://docs.lerian.studio/pt/reference/products/tracer/draft-limit.md).

**4. 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](https://docs.lerian.studio/pt/reference/products/tracer/delete-limit.md).

### 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`, `scheme` e `sub_type` filtram. Os resultados são paginados por cursor. Veja [Listar limites](https://docs.lerian.studio/pt/reference/products/tracer/list-limits.md), e [Obter um limite](https://docs.lerian.studio/pt/reference/products/tracer/retrieve-limit.md) para um por id.

***

## O que dá errado

***

> [!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."** Sem `resetTime`, os períodos começam às 00:00 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. Crie o limite com um `resetTime` para mover a fronteira.
> * **"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.

### 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 or equal to 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 um caractere que não é uma letra |
| `0371` | 400 | `name` carrega um caractere que o campo não aceita |
| `0380` | 422 | A requisição tentou mudar `limitType`, `asset` ou `resetTime` |
| `0440` | 400 | `resetTime` não está no formato `HH:MM` |
| `0442` | 409 | Outro limite ativo já possui esse nome |
| `0537` | 400 | `resetTime` foi definido em um limite `CUSTOM` ou `PER_TRANSACTION` |
| `0538` | 400 | `resetTime` cai dentro da janela de tempo do limite |

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

***

## 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 consumo do período atual | 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}` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.