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

# Configurar un límite de gasto

> Limita lo que una cuenta, un portafolio o un segmento puede gastar en un período con Tracer, activa el tope y lee cuánto queda desde la decisión de validación.

export const GAuditTrail = ({children}) => <Tooltip headline="Registro de auditoría" tip="Un registro cronológico e inmutable de cada acción y transacción en el sistema, esencial para el cumplimiento normativo y la resolución de disputas." cta="Ver glosario" href="/es/start-here/glossary">
    {children}
  </Tooltip>;

Una decisión de producto o de riesgo llega como una frase: «no más de R\$ 20,000 por cuenta al mes». Esta guía convierte esa frase en un tope activo y muestra dónde leer cuánto le queda a un cliente.

**Qué cambia en tu operación:** el tope deja de ser una constante compilada en un servicio. Se convierte en una definición almacenada que creas, activas, subes y detienes, y cada decisión que lo toca reporta cuánto consumió.

<Tip>
  **¿Para quién es esta guía?** Equipos de producto y riesgo que definen el tope, y desarrolladores que conectan `POST /v1/validations` al flujo de pago. Los pasos 1 y 2 son decisiones que tomar antes de cualquier llamada. Los pasos 3 a 6 son las llamadas.
</Tip>

## Antes de empezar

***

* [ ] Tracer en ejecución y accesible, con una API key. Consulta [Primeros pasos](./getting-started.mdx)
* [ ] El id de la cuenta, el portafolio o el segmento al que se aplica el tope
* [ ] El código de activo de las transacciones que quieres limitar
* [ ] Familiaridad con los tipos de límite, las ventanas de tiempo y los períodos personalizados. Consulta [Límites de gasto](./spending-limits.mdx)

Todas las llamadas siguientes envían la API key como `X-API-Key` y se ejecutan contra `http://localhost:4020`.

***

## Paso 1: Decide a qué se dirige el tope

***

Un límite lleva una lista de objetos de scope, y cada objeto indica a qué se aplica el límite. Estos campos están disponibles dentro de un objeto:

| Campo             | Aplica el límite a                                                                  |
| ----------------- | ----------------------------------------------------------------------------------- |
| `accountId`       | Transacciones de una cuenta                                                         |
| `portfolioId`     | Transacciones de un portafolio                                                      |
| `segmentId`       | Transacciones de un segmento                                                        |
| `merchantId`      | Transacciones hacia un comercio                                                     |
| `transactionType` | Uno de `CARD`, `WIRE`, `PIX`, `CRYPTO`                                              |
| `subType`         | Un subtipo de transacción, como `purchase`, sin distinguir mayúsculas de minúsculas |

Los campos dentro de un mismo objeto se combinan con AND. Un campo que omitas actúa como comodín. Entre objetos, la lista se combina con OR, así que un límite con dos objetos se aplica cuando cualquiera de los dos coincide.

La decisión que responde a «R\$ 20,000 por cuenta» es **qué id nombras**:

<Tabs>
  <Tab title="Una cuenta, su propio presupuesto">
    ```json theme={null}
    "scopes": [
      { "accountId": "550e8400-e29b-41d4-a716-446655440100" }
    ]
    ```

    El tope se aplica a esa cuenta. Cuenta el gasto de esa cuenta y de ninguna otra. Para un tope por cuenta en toda una cartera de clientes, cada cuenta recibe su propio límite.
  </Tab>

  <Tab title="Un segmento, un presupuesto compartido">
    ```json theme={null}
    "scopes": [
      { "segmentId": "2f1c9b7e-40a5-4d18-9c6b-3e7f5a0d1b24" }
    ]
    ```

    El tope se aplica al segmento en su conjunto. Cada cuenta de ese segmento consume del mismo R\$ 20,000 (los primeros clientes en gastar lo consumen para el resto).
  </Tab>

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

    El tope solo cuenta las transacciones Pix de esa cuenta. Su tráfico de tarjeta y de transferencia pasa sin tocar este límite.
  </Tab>
</Tabs>

<Note>
  Un límite también lleva un `asset`, y Tracer solo verifica un límite contra una transacción cuando ambos coinciden. Tracer no verifica un límite creado en `BRL` contra una transacción en `USD`. Una cartera que liquida en dos monedas necesita un límite para cada una.
</Note>

Un límite debe llevar al menos un objeto de scope, y cada objeto debe establecer al menos un campo. Tracer rechaza una lista vacía o un objeto vacío. Consulta [Qué sale mal](#what-goes-wrong).

***

## Paso 2: Elige el período

***

`limitType` decide tanto el tamaño de la ventana del tope como cuándo empieza un nuevo conteo. Tracer ofrece cinco:

| `limitType`       | El conteo cubre                | Un nuevo conteo empieza                                      |
| ----------------- | ------------------------------ | ------------------------------------------------------------ |
| `DAILY`           | Un día calendario, UTC         | Cada día a las 00:00 UTC                                     |
| `WEEKLY`          | Una semana ISO, UTC            | Cada lunes a las 00:00 UTC                                   |
| `MONTHLY`         | Un mes calendario, UTC         | El día 1 a las 00:00 UTC                                     |
| `CUSTOM`          | Un rango de fechas que defines | Nunca: un solo conteo abarca todo el rango                   |
| `PER_TRANSACTION` | Una sola transacción           | No se mantiene conteo; cada transacción se mide por separado |

«al mes» corresponde a `MONTHLY`.

<Warning>
  **El corte es UTC, no la hora local.** Un cliente en São Paulo que gasta a las 21:30 del 31 de julio está a las 00:30 UTC del 1 de agosto. Ese monto entra en el conteo de agosto, no en el de julio. Cuando un tope usa términos locales, las últimas horas del mes local suelen pertenecer al mes siguiente.
</Warning>

`CUSTOM` toma `customStartDate` y `customEndDate`, y es la forma que sirve para una campaña o una promoción. Esos dos campos pertenecen a `CUSTOM`. Tracer los rechaza en los otros cuatro tipos. Para restringir un tope a ciertas horas del día en cambio, consulta [ventanas de tiempo](./spending-limits.mdx#time-windows).

***

## Paso 3: Crea el límite

***

`POST /v1/limits` almacena la definición. Tracer la crea en `DRAFT` y todavía no la verifica contra transacciones.

```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" }
    ]
  }'
```

Una llamada exitosa responde `201`. El cuerpo lleva el límite almacenado. Dos campos importan ahora:

| Campo     | Qué hacer con él                                                                       |
| --------- | -------------------------------------------------------------------------------------- |
| `limitId` | El id que toma toda llamada posterior en esta guía. Consérvalo                         |
| `status`  | `DRAFT`: el límite todavía no se verifica. El [paso 4](#step-4-activate-it) cambia eso |

<Note>
  **Los nombres son únicos entre límites, y el conjunto de caracteres es reducido.** `name` acepta letras y dígitos ASCII, espacios, y `-`, `_`, `.`, `(`, `)`. Tracer rechaza un acento, o un guion escrito como raya, con `0371`. Tracer rechaza un nombre que ya tiene otro límite activo, con `0442`. Eliminar un límite libera su nombre de nuevo.
</Note>

Para el payload completo y todos los campos opcionales, consulta [Crear un límite](/es/reference/products/tracer/create-limit).

***

<h2 id="step-4-activate-it">
  Paso 4: Actívalo
</h2>

***

Tracer no verifica un límite en `DRAFT`. Activarlo es lo que lo pone en el flujo de pago:

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

La respuesta lleva el límite con `status` en `ACTIVE`. Desde aquí, Tracer verifica contra este límite cada `POST /v1/validations` cuya transacción coincida con el scope y el asset.

<Note>
  **Activar a mitad de mes no importa el historial del mes.** Tracer cuenta una transacción contra un límite en el momento en que decide sobre ella. El gasto que ocurrió mientras el límite estaba en `DRAFT` no entra en el conteo. Un tope activado el día 20 rige lo que pasa desde el día 20 en adelante.
</Note>

Consulta [Activar un límite](/es/reference/products/tracer/activate-limit).

***

## Paso 5: Lee cuánto queda

***

Cada respuesta de `POST /v1/validations` lleva `limitUsageDetails`, con una entrada por cada límite que Tracer verificó:

```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             | Qué reporta                                                                                                  |
| ----------------- | ------------------------------------------------------------------------------------------------------------ |
| `limitAmount`     | El tope que se verificó                                                                                      |
| `currentUsage`    | El consumo proyectado del período actual y el scope coincidente de ese límite si se permite esta transacción |
| `attemptedAmount` | El monto medido contra el tope                                                                               |
| `period`          | El tipo del límite: `MONTHLY` en este caso                                                                   |
| `scope`           | El scope del límite como texto, cada objeto entre paréntesis, varios objetos unidos por `OR`                 |
| `exceeded`        | Si el monto llevaría este límite más allá de su tope                                                         |

En la entrada de arriba, una compra de R\$ 1,500 llevó un mes de 18,500 a exactamente 20,000 y agotó el tope. Tracer deniega la siguiente transacción de esa cuenta hasta agosto.

Cuando una transacción excede un límite, la decisión es `DENY` y `reason` es `limit_exceeded`. Tracer no suma al conteo el monto que habría cruzado el tope. Un límite produce una denegación, no una marca para revisión. Para ir de una denegación así hasta el límite que la causó, consulta [Revisar una transacción denegada](./reviewing-a-denied-transaction.mdx).

### La otra lectura

`GET /v1/limits/{limitId}/usage` responde con un total del límite, no de un período. Suma los contadores de uso registrados contra él, entre los períodos y scopes que ha acumulado. Úsalo para revisar cuánto ha absorbido un límite en total, no para responder cuánto le queda a un cliente este mes.

Tracer elimina un contador 90 días después de que termina su período. En un límite de larga duración, este total cubre solo los períodos que todavía se conservan, no todo el ciclo de vida del límite. Consulta [Seguimiento de uso](./spending-limits.mdx#usage-tracking).

Consulta [Obtener una instantánea de uso de un límite](/es/reference/products/tracer/retrieve-limit-usage).

***

## Paso 6: Cámbialo, páusalo, elimínalo

***

<Steps>
  <Step title="Sube o baja el tope">
    ```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` y `scopes` son editables, igual que los campos de ventana de tiempo y de período personalizado. `limitType` y `asset` no lo son. Tracer rechaza una solicitud que envíe cualquiera de los dos con `0380`, y un período o un asset distintos significan un límite nuevo. Tracer rechaza un cuerpo vacío con `0183`. Consulta [Actualizar un límite](/es/reference/products/tracer/update-limit).

    Cambiar el tope no borra el conteo en curso. Si lo bajas por debajo de lo que el período actual ya consumió, Tracer deniega a la cuenta hasta que empiece el siguiente período.
  </Step>

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

    El límite pasa a `INACTIVE` y Tracer deja de verificarlo. Conserva su definición y su lugar en el <GAuditTrail>registro de auditoría</GAuditTrail>, y `POST /v1/limits/{limitId}/activate` lo devuelve al flujo de pago. Consulta [Desactivar un límite](/es/reference/products/tracer/deactivate-limit).
  </Step>

  <Step title="Devuélvelo a borrador">
    ```bash theme={null}
    curl -X POST http://localhost:4020/v1/limits/{limitId}/draft \
      -H "X-API-Key: your-secure-api-key"
    ```

    Devuelve un límite `INACTIVE` a `DRAFT`. Consulta [Devolver un límite a borrador](/es/reference/products/tracer/draft-limit).
  </Step>

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

    Responde `204`. Primero tienes que desactivar un límite que esté `ACTIVE`. Tracer rechaza la eliminación con `0363`, que es lo que evita que un tope activo desaparezca por accidente. Consulta [Eliminar un límite](/es/reference/products/tracer/delete-limit).
  </Step>
</Steps>

### Encuentra los límites que ya tienes

`GET /v1/limits` los lista, y filtra por los mismos campos de scope que definiste en el paso 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` y `sub_type` filtran todos. Los resultados se paginan por cursor. Consulta [Listar límites](/es/reference/products/tracer/list-limits), y [Obtener un límite](/es/reference/products/tracer/retrieve-limit) para uno por su id.

***

<h2 id="what-goes-wrong">
  Qué sale mal
</h2>

***

<Warning>
  **Lo que suele salir mal al configurar un tope:**

  * **«El cliente gastó de más y nada lo detuvo».** Revisa primero `status`. Tracer no verifica un límite en `DRAFT` o `INACTIVE`. Luego revisa que el `asset` del límite coincida con el de la transacción, y que el scope nombre el id que la transacción realmente llevaba.
  * **«El tope del segmento se agotó al segundo día».** Un límite con scope de segmento es un solo presupuesto para todo el segmento, no uno por cada cuenta dentro de él. Un tope por cuenta significa un límite dirigido a cada cuenta.
  * **«El mes cambió unas horas antes».** Los cortes de período son UTC. El gasto después de las 21:00 en UTC-3 pertenece al siguiente día UTC, y en el último día del mes, al mes siguiente.
  * **«Subí el límite y la cuenta sigue denegada».** Subir el tope no borra el conteo. Confirma que el nuevo `maxAmount` esté por encima de lo que el período ya consumió.
  * **«`GET /v1/limits/{id}/usage` reporta más de lo que el cliente gastó este mes».** Ese endpoint suma los contadores registrados para el límite, entre períodos y scopes. Para el período actual, lee `limitUsageDetails` en la respuesta de la validación.
</Warning>

### Códigos de error

| Código | Estado | Qué cambiar                                                                                                                                                                                    |
| ------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0009` | 400    | Un campo falló la validación: `detail` lo nombra, por ejemplo `scopes must have at least 1 item(s)`, `scope at index 0 must have at least one field set`, o `maxAmount must be greater than 0` |
| `0065` | 400    | El id en la ruta no es un UUID                                                                                                                                                                 |
| `0183` | 400    | El cuerpo del `PATCH` no llevaba ningún campo editable                                                                                                                                         |
| `0362` | 404    | Ningún límite tiene ese id                                                                                                                                                                     |
| `0363` | 422    | La transición no está permitida, por ejemplo eliminar un límite `ACTIVE`                                                                                                                       |
| `0366` | 400    | `asset` son tres letras mayúsculas pero no un código ISO 4217                                                                                                                                  |
| `0371` | 400    | `name` lleva un carácter que el campo no acepta                                                                                                                                                |
| `0380` | 422    | La solicitud intentó cambiar `limitType` o `asset`                                                                                                                                             |
| `0442` | 409    | Otro límite activo ya tiene ese nombre                                                                                                                                                         |

La lista completa está en la [lista de errores de Tracer](/es/reference/products/tracer/tracer-error-list).

***

## Referencia rápida

***

| Paso                               | Método | Endpoint                         |
| ---------------------------------- | ------ | -------------------------------- |
| Crear un límite                    | POST   | `/v1/limits`                     |
| Activarlo                          | POST   | `/v1/limits/{id}/activate`       |
| Leer el consumo con la decisión    | POST   | `/v1/validations`                |
| Leer el total acumulado del límite | GET    | `/v1/limits/{id}/usage`          |
| Cambiar el tope                    | PATCH  | `/v1/limits/{id}`                |
| Dejar de aplicarlo                 | POST   | `/v1/limits/{id}/deactivate`     |
| Devolverlo a borrador              | POST   | `/v1/limits/{id}/draft`          |
| Eliminarlo                         | DELETE | `/v1/limits/{id}`                |
| Encontrar límites                  | GET    | `/v1/limits` · `/v1/limits/{id}` |
