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

# Authentication

> API keys, scopes, rotation, IP allowlist, request signing and idempotency

<Warning>
  Draft: specification in progress. Endpoints and fields may change.
</Warning>

## API keys

Each key belongs to an organization and is created in the dashboard by an administrator. The full key is shown only once, at creation.

| Prefix | Environment |
| - | - |
| `tesa_test_` | Sandbox |
| `tesa_live_` | Production |

The key goes in the `Authorization` header of every request:

```bash theme={null}
curl https://api.t3sa.com/v1/posicoes \
  -H "Authorization: Bearer tesa_live_..."
```

<Warning>
  The API key authenticates the integration with TESA. It does not sign transactions and does not grant access to the wallet keys, which remain with the company or its custodian.
</Warning>

## Scopes

Each key receives one or more scopes. A call outside the key's scope returns `403`.

| Scope | Allows |
| - | - |
| `read` | Reading organization, wallets, positions, policy, proposals, redemptions, records, yield and charges |
| `propose` | Creating rebalancing proposals and redemption requests, which stay pending approval |
| `admin` | Approving or rejecting proposals, changing the allocation policy, linking wallets and managing webhooks |

We recommend separating duties: the ERP integration uses `read` and `propose`, and approval stays with an `admin` key kept in a restricted environment, or in the dashboard only.

## Rotation

* An organization can have more than one active key at a time, which allows rotation with no downtime window.
* The suggested flow is to create the new key, update the integration and revoke the old one.
* Revoked keys stop working immediately. Each key records its creation date, last use and author.

## IP allowlist

Production keys can be restricted to a list of IPs or CIDR blocks. Requests from outside the list return `403` with the code `ip_nao_autorizado`. The proposal is to make the allowlist mandatory for keys with `admin` scope.

## Request signing (HMAC)

In addition to the key, state-changing requests (`POST`, `PUT`) can be signed with an organization HMAC secret, separate from the API key. The proposal is to make signing mandatory for keys with `admin` scope.

| Header | Content |
| - | - |
| `Tesa-Timestamp` | Request time in Unix seconds |
| `Tesa-Signature` | Hex-encoded HMAC-SHA256 of the canonical message |

The canonical message joins, separated by line breaks: the timestamp, the method, the path with query string and the raw request body.

```text theme={null}
1788220800
POST
/v1/propostas/prop_8f2a1c/aprovar
{"comentario":"Aprovado pela tesouraria"}
```

Requests with a timestamp outside a 5-minute window are rejected with `401`, which prevents replay of a captured request.

## Idempotency

Every `POST` request accepts the `Idempotency-Key` header, with a unique value generated by the integration (a UUID, for example).

* Repeating the same key with the same body returns the original response, without creating a second operation.
* Repeating the same key with a different body returns `409` with the code `conflito_idempotencia`.
* Keys are stored for 24 hours.

<Note>
  For redemptions and approvals, `Idempotency-Key` is mandatory. A network failure must not create two redemption requests.
</Note>

## Rate limits

Limits apply per key and are detailed in [Errors and limits](/docs/en/api/erros-e-limites). Every response includes the `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` headers.
