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

# Redemption

> From request to USDC in the company's wallet, with a complete TypeScript example

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

A redemption returns USDC to a linked wallet owned by the company. After signing by the custodian, the balance arrives within seconds.

## States

| Status | Meaning |
| - | - |
| `pendente` | Created, awaiting approval |
| `aprovado` | Approved, transactions being prepared |
| `aguardando_assinatura` | Unsigned transactions available for the custodian |
| `concluido` | USDC confirmed on-chain in the destination wallet |
| `falhou` | The transaction failed or expired. A new redemption can be created |

## Complete example

Illustrative values. Sending to the custodian depends on each custodian's API and appears here as a function of your own integration.

```typescript TypeScript theme={null}
const BASE = "https://api.t3sa.com/v1"; // proposed URL
const auth = { Authorization: `Bearer ${process.env.TESA_API_KEY}` };

async function tesa(path: string, init: RequestInit = {}) {
  const res = await fetch(`${BASE}${path}`, {
    ...init,
    headers: { ...auth, "Content-Type": "application/json", ...init.headers },
  });
  const body = await res.json();
  if (!res.ok) throw new Error(`${body.erro.codigo}: ${body.erro.mensagem}`);
  return body;
}

// 1. Request (propose scope)
const resgate = await tesa("/resgates", {
  method: "POST",
  headers: { "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({
    valor: "150000.00",
    carteira_destino_id: "cart_3k9d",
    referencia_interna: "folha-2026-09",
  }),
});

// 2. Approve (admin scope, in a restricted environment)
const aprovado = await tesa(`/resgates/${resgate.id}/aprovar`, {
  method: "POST",
  headers: { "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ comentario: "Folha de setembro" }),
});

// 3. Send each unsigned transaction to the custodian
for (const tx of aprovado.transacoes) {
  await enviarAoCustodiante(tx.rede, tx.payload_nao_assinado);
}

// 4. Wait for the resgate.concluido webhook, or poll GET /resgates/{id}
```

## Common errors

| HTTP | Code | What to do |
| - | - | - |
| `422` | `saldo_insuficiente` | The amount exceeds the balance available for redemption. Check `GET /posicoes` |
| `422` | `carteira_nao_vinculada` | The destination is not a linked company wallet |
| `409` | `conflito_idempotencia` | The same `Idempotency-Key` was used with a different body |
| `503` | `servico_indisponivel` | An external dependency is unavailable, such as a CCTP pause. Retry with the same `Idempotency-Key` |

Full list in [Errors and limits](/docs/en/api/erros-e-limites).
