A API Tesouro Direto da brapi.dev entrega lista de títulos, taxas de agora e histórico diário desde 2005. Tudo em três endereços REST (REST é só um jeito de pedir dados na web, devolvendo JSON), com nomes de título que nunca mudam. Sem baixar planilha gigante, sem quebrar a cabeça com nomes diferentes a cada ano.
Em maio de 2026 nós lançamos a API Tesouro Direto da brapi.dev:
/api/v2/treasury. São três endereços que se combinam (você usa um, dois
ou os três conforme precisar) e devolvem as taxas e os preços dos títulos
públicos do governo em JSON. Tem cache no servidor (o resultado fica guardado
por alguns minutos) e cada título tem um nome curto e fixo que você pode
salvar no seu banco de dados.
Esse guia é para você que mexe com renda fixa: gente de fintech, quem faz
calculadora de marcação a mercado (marcação a mercado é o preço pelo qual
você venderia o título hoje), robô de investimento ou planilha de carteira.
Vamos passar pelos três endereços, mostrar os parâmetros e explicar o ponto
que mais confunde: como ler buyRate e sellRate. Cada tipo de título trata
esses campos de um jeito diferente.
Qual endpoint usar?
Legenda: árvore de decisão simples — escolha o endereço da API conforme a pergunta que você quer responder.
Por que uma API Tesouro Direto?
A fonte oficial é o Tesouro Transparente — um site do governo que publica planilhas CSV com o histórico de taxas e preços. É melhor que nada, mas usar essa planilha direto traz três dores crônicas:
- Arquivos pesados. O CSV de taxas tem várias centenas de megabytes e cresce todo dia. Baixar tudo só para saber "qual a taxa do Tesouro Selic hoje" é trabalho a mais.
- Nomes que mudam. O mesmo título aparece com grafias diferentes ao longo dos anos (com ou sem acento, com hífen, em outra ordem). Casar o nome do CSV com o nome no seu app vira faxina manual.
- Sem valor de agora. O CSV traz só o histórico. Para pegar o preço mais recente, você precisa ler a última linha de cada título. Não existe um endereço REST oficial pronto.
A /api/v2/treasury da brapi.dev resolve isso com nomes curtos e fixos
(chamamos de slugs) no formato <nome-do-titulo>-<DDMMAAAA>:
| Slug | Significado |
|---|---|
tesouro-selic-01032031 | Tesouro Selic com vencimento em 01/03/2031 |
tesouro-prefixado-com-juros-semestrais-01012037 | Tesouro Prefixado com Juros Semestrais 01/01/2037 |
tesouro-ipca-com-juros-semestrais-15082060 | Tesouro IPCA+ com Juros Semestrais 15/08/2060 |
O slug nunca muda enquanto o título existir. Pense nele como um RG do título: você pode salvar no banco de dados e dormir tranquilo.
Cobertura e atualização
A base cobre Tesouro Selic, Prefixado, IPCA+, IGP-M histórico, Renda+ e
Educa+ quando aparecem no Tesouro Transparente. Atualizamos uma vez por dia,
em dia útil. O histórico vai até 2005 (depende do que a fonte pública
mostra). As datas vão no formato YYYY-MM-DD, tanto no pedido quanto na
resposta.
Como começar em 3 passos
- Crie sua conta em brapi.dev e pegue o token (uma senha que vai no cabeçalho do seu pedido).
- Faça um teste sem token nos três slugs de exemplo (veja a seção "Sandbox sem token" abaixo).
- Quando quiser todos os títulos, ative o plano Pro e troque o token de teste pelo seu token de verdade.
Os 3 endpoints da API Tesouro Direto
1. GET /api/v2/treasury/list — Lista títulos ofertados
Esse endereço devolve a lista do que o Tesouro está vendendo agora, página por página. Você filtra por indexador (indexador é o índice que corrige o título, tipo a Selic ou o IPCA), por tipo de cupom (com ou sem pagamento semestral) e por busca por palavra. Use esse endereço primeiro para descobrir o que existe.
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/list?indexer=prefixado&limit=3"Resposta (truncada para 2 dos 11 itens reais):
{
"results": [
{
"symbol": "tesouro-prefixado-01012027",
"bondType": "Tesouro Prefixado",
"indexer": "prefixado",
"couponType": "zero",
"maturityDate": "2027-01-01",
"durationDays": 231,
"baseDate": "2026-05-15",
"buyRate": 13.96,
"sellRate": 14.08,
"buyPrice": 921.33,
"sellPrice": 920.24,
"basePrice": 920.24,
"rateInfo": {
"rateType": "nominalAnnualRate",
"rateUnit": "% a.a.",
"description": "Para Tesouro Prefixado, buyRate e sellRate representam a taxa nominal anual contratada."
}
},
{
"symbol": "tesouro-prefixado-com-juros-semestrais-01012027",
"bondType": "Tesouro Prefixado com Juros Semestrais",
"indexer": "prefixado",
"couponType": "semestral",
"maturityDate": "2027-01-01",
"durationDays": 231,
"baseDate": "2026-05-15",
"buyRate": 14.05,
"sellRate": 14.17,
"buyPrice": 1013.85,
"sellPrice": 1012.67,
"basePrice": 1012.67,
"rateInfo": {
"rateType": "nominalAnnualRate",
"rateUnit": "% a.a.",
"description": "Para Tesouro Prefixado, buyRate e sellRate representam a taxa nominal anual contratada."
}
}
],
"pagination": {
"page": 1,
"limit": 3,
"totalItems": 11,
"totalPages": 4,
"hasNextPage": true
},
"requestedAt": "2026-05-17T23:27:44.112Z",
"took": 0
}Parâmetros:
| Parâmetro | Tipo | Default | Descrição |
|---|---|---|---|
indexer | selic / prefixado / ipca / igpm | — | Filtra por indexador |
couponType | zero / semestral | — | Sem cupom periódico ou com juros semestrais |
search | string | — | Busca textual em symbol e bondType |
sortBy | symbol / bondType / maturityDate / buyRate / sellRate / durationDays | symbol | Campo de ordenação |
sortOrder | asc / desc | asc | Ordem |
page | inteiro | 1 | Página |
limit | inteiro (máx. 100) | 20 | Itens por página |
2. GET /api/v2/treasury/indicators — Valor de agora
Esse endereço devolve a fotografia do momento: as taxas e os preços mais recentes dos títulos que você pedir. Você pode pedir até 20 títulos por chamada, separados por vírgula.
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/indicators?symbols=tesouro-selic-01032031,tesouro-prefixado-com-juros-semestrais-01012037,tesouro-ipca-com-juros-semestrais-15082060"Resposta:
{
"results": [
{
"symbol": "tesouro-selic-01032031",
"bondType": "Tesouro Selic",
"indexer": "selic",
"couponType": "zero",
"maturityDate": "2031-03-01",
"durationDays": 1751,
"baseDate": "2026-05-15",
"buyRate": 0.08,
"sellRate": 0.09,
"buyPrice": 18944.78,
"sellPrice": 18925.53,
"basePrice": 18925.53,
"rateInfo": {
"rateType": "spreadOverSelic",
"rateUnit": "% a.a.",
"description": "Para Tesouro Selic, buyRate e sellRate representam o spread em pontos percentuais ao ano sobre a taxa Selic, não a rentabilidade total do título."
}
},
{
"symbol": "tesouro-prefixado-com-juros-semestrais-01012037",
"bondType": "Tesouro Prefixado com Juros Semestrais",
"indexer": "prefixado",
"couponType": "semestral",
"maturityDate": "2037-01-01",
"durationDays": 3884,
"baseDate": "2026-05-15",
"buyRate": 14.36,
"sellRate": 14.48,
"buyPrice": 814.75,
"sellPrice": 809.22,
"basePrice": 809.22,
"rateInfo": {
"rateType": "nominalAnnualRate",
"rateUnit": "% a.a.",
"description": "Para Tesouro Prefixado, buyRate e sellRate representam a taxa nominal anual contratada."
}
},
{
"symbol": "tesouro-ipca-com-juros-semestrais-15082060",
"bondType": "Tesouro IPCA+ com Juros Semestrais",
"indexer": "ipca",
"couponType": "semestral",
"maturityDate": "2060-08-15",
"durationDays": 12511,
"baseDate": "2026-05-15",
"buyRate": 7.22,
"sellRate": 7.34,
"buyPrice": 4086.85,
"sellPrice": 4023.39,
"basePrice": 4023.39,
"rateInfo": {
"rateType": "realAnnualRateOverIpca",
"rateUnit": "% a.a.",
"description": "Para Tesouro IPCA+, buyRate e sellRate representam a taxa real anual acima da inflação medida pelo IPCA."
}
}
],
"requestedAt": "2026-05-17T23:27:46.786Z",
"took": 1
}Parâmetros:
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
symbols | sim | Slugs separados por vírgula, máx. 20 |
3. GET /api/v2/treasury/indicators/history — Histórico diário
Esse endereço devolve uma série dia a dia de taxas (buyRate, sellRate) e
preços (buyPrice, sellPrice, basePrice) para os títulos que você
pedir. Se você não passar startDate ou endDate, ele devolve os últimos
12 meses.
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/indicators/history?symbols=tesouro-selic-01032031&startDate=2026-05-01&endDate=2026-05-15&sortOrder=asc"Resposta (truncada para 3 dos 10 dias úteis retornados):
{
"results": [
{
"symbol": "tesouro-selic-01032031",
"bondType": "Tesouro Selic",
"indexer": "selic",
"couponType": "zero",
"maturityDate": "2031-03-01",
"rateInfo": {
"rateType": "spreadOverSelic",
"rateUnit": "% a.a.",
"description": "Para Tesouro Selic, buyRate e sellRate representam o spread em pontos percentuais ao ano sobre a taxa Selic, não a rentabilidade total do título."
},
"history": [
{
"baseDate": "2026-05-04",
"buyRate": 0.08,
"sellRate": 0.09,
"buyPrice": 18852.7,
"sellPrice": 18833.5,
"basePrice": 18833.5
},
{
"baseDate": "2026-05-13",
"buyRate": 0.08,
"sellRate": 0.09,
"buyPrice": 18924.16,
"sellPrice": 18904.94,
"basePrice": 18904.94
},
{
"baseDate": "2026-05-15",
"buyRate": 0.08,
"sellRate": 0.09,
"buyPrice": 18944.78,
"sellPrice": 18925.53,
"basePrice": 18925.53
}
]
}
],
"requestedAt": "2026-05-17T23:27:47.893Z",
"took": 1
}Parâmetros:
| Parâmetro | Default | Descrição |
|---|---|---|
symbols (obrigatório) | — | Slugs separados por vírgula |
startDate | hoje − 12 meses | YYYY-MM-DD |
endDate | hoje | YYYY-MM-DD |
sortBy | baseDate | baseDate / buyRate / sellRate / buyPrice / sellPrice / basePrice |
sortOrder | desc | asc / desc |
Como interpretar buyRate e sellRate (a pegadinha)
Essa é, de longe, a maior fonte de confusão da API Tesouro Direto. O
nome dos campos é sempre o mesmo, mas o que cada um quer dizer muda
conforme o tipo de título. Por isso a resposta sempre vem com um objeto
chamado rateInfo. Leia ele antes de fazer qualquer conta.
indexer | rateInfo.rateType | Significado |
|---|---|---|
selic | spreadOverSelic | Spread em p.p. ao ano sobre a Selic Meta (ex.: 0.08 = Selic + 0,08 p.p./ano) |
prefixado | nominalAnnualRate | Taxa nominal anual contratada (ex.: 14.05 = 14,05% a.a.) |
ipca | realAnnualRateOverIpca | Taxa real anual acima do IPCA (ex.: 7.22 = IPCA + 7,22% a.a.) |
igpm | realAnnualRateOverIgpm | Taxa real anual acima do IGP-M |
Não some Selic + buyRate sem pensar
No Tesouro Selic, buyRate=0.08 não é o rendimento total do título.
É só o spread (um pequeno extra) sobre a Selic. Para saber quanto rende de
verdade no ano, você precisa juntar com a Selic atual.
Legenda: o número buyRate parece pequeno no Tesouro Selic e grande no
Prefixado, mas eles medem coisas diferentes. Selic é só o spread; Prefixado
é a taxa total; IPCA+ e IGP-M são taxas reais que você soma com a inflação.
Sempre olhe o rateInfo antes de comparar.
Exemplo passo a passo: Tesouro Selic 2031
Em 15/05/2026, o tesouro-selic-01032031 está com buyRate=0.08 (esse é
o spread sobre a Selic, ou seja, o pedacinho a mais que o título paga
acima da Selic). A Selic Meta no mesmo dia está em 14,5% a.a.
(consultada em /api/v2/macro/latest?symbols=selic).
Qual é a rentabilidade efetiva, ou seja, quanto ele rende ao ano de verdade?
selicMeta = 14.5
spread = 0.08
# Aproximação linear (boa o suficiente para spreads pequenos)
aprox = 14.5 + 0.08 = 14.58% a.a.
# Composição correta
composto = ((1 + 14.5/100) × (1 + 0.08/100) - 1) × 100
≈ 14.5916% a.a.No Tesouro Selic o spread geralmente fica entre 0% e 0,30%, então a diferença entre somar reto e compor de verdade é de centésimos. Mas em produtos com spread maior (LCA, debênture com spread sobre CDI de 1,5 a 3 pontos), a composição faz diferença real.
TypeScript: descobrir o tipo de taxa direto no código
type Treasury = {
symbol: string;
indexer: 'selic' | 'prefixado' | 'ipca' | 'igpm';
buyRate: number;
sellRate: number;
rateInfo: {
rateType:
| 'spreadOverSelic'
| 'nominalAnnualRate'
| 'realAnnualRateOverIpca'
| 'realAnnualRateOverIgpm';
rateUnit: string;
description: string;
};
};
function effectiveRate(title: Treasury, selicMeta: number, ipca12m: number): number {
const r = title.buyRate;
switch (title.rateInfo.rateType) {
case 'spreadOverSelic':
// Composição correta: (1 + selic)(1 + spread) - 1
return ((1 + selicMeta / 100) * (1 + r / 100) - 1) * 100;
case 'nominalAnnualRate':
// Já é a taxa final
return r;
case 'realAnnualRateOverIpca':
return ((1 + ipca12m / 100) * (1 + r / 100) - 1) * 100;
case 'realAnnualRateOverIgpm':
// Caller deve passar igpm em vez de ipca12m
return ((1 + ipca12m / 100) * (1 + r / 100) - 1) * 100;
}
}Exemplo de ponta a ponta: rankear por taxa efetiva
Vamos juntar /api/v2/treasury/list com /api/v2/macro/latest para colocar
os Prefixados em ordem pela taxa nominal (a taxa cheia que o título paga)
e o Tesouro Selic em ordem pela taxa efetiva (a taxa final, já somada com a
Selic).
const BASE = 'https://brapi.dev/api/v2/treasury';
const headers = { Authorization: `Bearer ${process.env.BRAPI_TOKEN}` };
async function rankTreasuries() {
const [listRes, macroRes] = await Promise.all([
fetch(`${BASE}/list?limit=100`, { headers }).then((r) => r.json()),
fetch('https://brapi.dev/api/v2/macro/latest?symbols=selic', {
headers,
}).then((r) => r.json()),
]);
const selicMeta = macroRes.results[0]?.latest.value ?? 0;
const ranked = listRes.results.map((t: any) => ({
symbol: t.symbol,
indexer: t.indexer,
maturityDate: t.maturityDate,
rateRaw: t.buyRate,
rateType: t.rateInfo.rateType,
effective:
t.rateInfo.rateType === 'spreadOverSelic'
? ((1 + selicMeta / 100) * (1 + t.buyRate / 100) - 1) * 100
: t.buyRate, // nominal/real são comparáveis em outra dimensão
}));
return ranked.sort((a, b) => b.effective - a.effective);
}import os
import requests
BASE = 'https://brapi.dev/api/v2/treasury'
headers = {'Authorization': f"Bearer {os.environ['BRAPI_TOKEN']}"}
def rank_treasuries():
listing = requests.get(
f'{BASE}/list',
params={'limit': 100},
headers=headers,
).json()
macro = requests.get(
'https://brapi.dev/api/v2/macro/latest',
params={'symbols': 'selic'},
headers=headers,
).json()
selic_meta = macro['results'][0]['latest']['value']
ranked = []
for t in listing['results']:
if t['rateInfo']['rateType'] == 'spreadOverSelic':
effective = ((1 + selic_meta / 100) * (1 + t['buyRate'] / 100) - 1) * 100
else:
effective = t['buyRate']
ranked.append({
'symbol': t['symbol'],
'indexer': t['indexer'],
'maturityDate': t['maturityDate'],
'rateRaw': t['buyRate'],
'rateType': t['rateInfo']['rateType'],
'effective': effective,
})
return sorted(ranked, key=lambda r: r['effective'], reverse=True)Fluxo recomendado de um cliente da API
Na prática, quase todo cliente da API Tesouro Direto segue o mesmo passo a passo: primeiro descobre os títulos, depois pega as taxas de agora e por fim baixa o histórico para fazer gráfico. O diagrama abaixo mostra esse caminho.
Legenda: o cliente faz três chamadas em sequência. Cada uma resolve uma parte do problema: descobrir, ver agora e ver o histórico.
Paginação, busca e ordenação no /list
# Próxima página
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/list?indexer=ipca&page=2&limit=10"
# Busca textual no symbol ou bondType
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/list?search=2031"
# Ordena por vencimento (mais longos primeiro)
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/list?indexer=prefixado&sortBy=maturityDate&sortOrder=desc"
# Só Tesouro IPCA+ sem cupom periódico
curl -H "Authorization: Bearer SEU_TOKEN" \
"https://brapi.dev/api/v2/treasury/list?indexer=ipca&couponType=zero"A resposta sempre traz um campo pagination com totalItems, totalPages
e hasNextPage. Assim você sabe quantas páginas ainda faltam, sem precisar
chutar.
Sandbox sem token
Para você testar sem se cadastrar, três títulos funcionam sem token
(token é a senha que você manda no cabeçalho da requisição, no campo
Authorization: Bearer ...):
tesouro-selic-01032031tesouro-prefixado-com-juros-semestrais-01012037tesouro-ipca-com-juros-semestrais-15082060
# Sem header de autenticação
curl "https://brapi.dev/api/v2/treasury/indicators?symbols=tesouro-selic-01032031,tesouro-prefixado-com-juros-semestrais-01012037,tesouro-ipca-com-juros-semestrais-15082060"
# /list sandbox: passe o slug em ?search=
curl "https://brapi.dev/api/v2/treasury/list?search=tesouro-selic-01032031"Sandbox no /list usa o parâmetro search
O endereço /list libera o teste sem token só quando você passa
?search=<slug-de-teste> igualzinho a um dos três títulos acima. Para
listagens gerais, é preciso usar o token.
Planos e cache
| Endpoint | Auth | Plano mínimo |
|---|---|---|
GET /api/v2/treasury/list | Bearer token (sandbox via ?search=) | Pro |
GET /api/v2/treasury/indicators | Bearer token (sandbox via ?symbols=) | Pro |
GET /api/v2/treasury/indicators/history | Bearer token (sandbox via ?symbols=) | Pro |
| Plano | Acesso |
|---|---|
| Sandbox (sem token) | Apenas os 3 títulos documentados acima |
| Free | Bloqueado |
| Startup | Bloqueado |
| Pro | Acesso completo a todos os títulos e histórico |
Cache no servidor (a resposta fica guardada por esse tempo, então chamadas iguais voltam mais rápido):
/list: 15 minutos/indicators: 5 minutos/indicators/history: 10 minutos
O Tesouro Direto publica as taxas uma vez por dia útil e a brapi sincroniza
diariamente. O cache de 5 minutos no /indicators garante que, assim que
a sincronização rodar, você recebe o valor atualizado sem sobrecarregar o
servidor. Em dashboards executivos, aproveite o cabeçalho Cache-Control
que a API devolve para guardar o resultado no seu próprio lado também.
Erros comuns e como resolver
| Status | Quando acontece | Como resolver |
|---|---|---|
401 MISSING_TOKEN | Você esqueceu de mandar o Authorization: Bearer e o pedido não usa um slug de teste | Adicione o token, ou use um dos 3 slugs de teste |
403 FEATURE_NOT_AVAILABLE | Token válido, mas seu plano não tem canAccessFixedIncome | Faça upgrade para o plano Pro |
400 (ZodError) | Algum parâmetro veio errado: indexer fora da lista, symbols vazio, limit acima de 100 | Olhe a mensagem em error.issues[].message |
200 com results: [] | O título não existe ou parou de ser ofertado | Confira o slug usando /list |
Exemplo da resposta 400 quando você manda ?indexer=wrongvalue:
{
"success": false,
"error": {
"issues": [
{
"received": "wrongvalue",
"code": "invalid_enum_value",
"options": ["selic", "prefixado", "ipca", "igpm"],
"path": ["indexer"],
"message": "Invalid enum value. Expected 'selic' | 'prefixado' | 'ipca' | 'igpm', received 'wrongvalue'"
}
],
"name": "ZodError"
}
}Casos de uso
Comparador de títulos públicos
Use /list?indexer=... com sortBy=buyRate&sortOrder=desc para achar a
maior taxa de cada indexador. Junte com vencimento e couponType para
filtrar por perfil: zero cupom é melhor para quem quer reinvestir tudo;
cupom semestral é bom para quem quer receber dinheiro a cada seis meses.
Marcação a mercado
O endereço /indicators/history serve direto para gráficos de
marcação a mercado.
Você acompanha buyPrice e sellPrice dia a dia e vê o efeito que as
mudanças de taxa têm no valor do seu título.
Carteira de renda fixa com vários títulos
Faça uma só chamada /indicators?symbols= com até 20 slugs e mostre a foto
da carteira inteira de uma vez, sem precisar fazer várias chamadas
separadas.
Análise de curva de juros
Liste todos os Prefixados (/list?indexer=prefixado&limit=100), pegue
(maturityDate, buyRate) de cada um e desenhe a curva. Atualize a cada
5 minutos para respeitar o cache.
Comparativo entre indexadores
Junte /indicators com /api/v2/macro/latest?symbols=selic,ipca12m para
transformar spread e taxa real em taxa efetiva. Aí dá para comparar Selic
vs. IPCA+ vs. Prefixado na mesma unidade. Veja o post
CDB vs. Tesouro Direto: comparativo 2026
para um guia de decisão.
Backtest (teste em dados antigos)
Junte /indicators/history (para o preço diário do título) com nosso
CDI histórico e
compare o desempenho da posição com o benchmark.
Próximos passos com a API Tesouro Direto
Estes são os caminhos para você se aprofundar:
- Documentação completa do
/api/v2/treasury - Listagem — referência do
/list - Indicadores — referência do
/indicators - Histórico — referência do
/indicators/history - API de Macroeconomia: 15 indicadores BCB
- CDI histórico via API
- Tesouro Direto: guia completo 2026
- CDB vs. Tesouro Direto: comparativo 2026
Conclusão
A API Tesouro Direto da brapi.dev existe para te poupar tempo. Em vez
de baixar planilha gigante e brigar com nomes inconsistentes, você faz três
chamadas REST e tem na mão a lista de títulos, o valor de agora e o
histórico diário desde 2005. Os slugs nunca mudam, o JSON é simples e o
campo rateInfo te diz exatamente como ler cada taxa.
Comece pelos três slugs sandbox para testar sua integração sem token. Quando estiver pronto para usar todos os títulos e o histórico completo, gere seu token e ative o plano Pro em brapi.dev. Boa construção!
