Guia de Migração da API Mais Retorno

Atualizado em fevereiro de 2026

Autenticação: Token → API Key

O fluxo OAuth (POST /auth com email/senha → access_token JWT) foi substituído por uma api_key estática, gerada em maisretorno.com/app/meu-perfil/api. A chave (formato mr_xxx_xxxxxxxx...) é vinculada a uma subscription ativa de algum plano (Free / Basic / Starter / Growth / Enterprise) e é exibida em texto plano apenas uma vez.

Como gerar sua api_key (vídeo ~30s)

Antes
Authorization: Bearer <access_token JWT, 60min>
Depois
X-Api-Key: <api_key estática>

Resumo das mudanças

AspectoAntesDepois
Como obterPOST /auth com email + senhaGerar em maisretorno.com/app/meu-perfil/api
Pré-requisitoConta cadastradaSubscription ativa de algum plano
Validade60 minutos (JWT expira)Estática, sem expiração
Header principalAuthorization: Bearer <access_token>X-Api-Key: <api_key> (server-side)
Header alternativoAuthorization: Bearer <api_key> (única opção via browser, por CORS)
RenovaçãoRefazer POST /auth ao receber 401Não há; gere uma nova no portal se invalidar (a anterior é revogada)
Onde guardarCache curto em memória / RedisVariável de ambiente / gerenciador de segredos
Limite de usoNão havia quota explícita por chaveCota mensal por plano (500 / 1.5k / 5k / 15k / Enterprise) — 429 quando esgota

Código — Antes

import requests

# 1. Obter access_token via POST /auth (válido por 60min)
auth_response = requests.post(
    "https://data.maisretorno.com/auth",
    data={
        "grant_type": "password",
        "username": "seu-email@exemplo.com",
        "password": "sua-senha",
        "client_id": "mrdata",
    },
)
token = auth_response.json()["access_token"]

# 2. Usar token nas requisições
response = requests.get(
    "https://data.maisretorno.com/mr-data/v4/api/asset-info/petr4:b3",
    headers={"Authorization": f"Bearer {token}"},
)
print(response.json())
// 1. Obter access_token via POST /auth (válido por 60min)
const authRes = await fetch("https://data.maisretorno.com/auth", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: new URLSearchParams({
    grant_type: "password",
    username: "seu-email@exemplo.com",
    password: "sua-senha",
    client_id: "mrdata",
  }),
});
const { access_token: token } = await authRes.json();

// 2. Usar token nas requisições
const response = await fetch(
  "https://data.maisretorno.com/mr-data/v4/api/asset-info/petr4:b3",
  { headers: { Authorization: `Bearer ${token}` } }
);
console.log(await response.json());

Código — Depois

import requests

# 1. Gere a api_key uma única vez no portal e guarde com segurança
#    (formato: mr_xxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxx)
api_key = "SUA_API_KEY"

# 2. Use direto nas requisições — sem POST /auth, sem expiração de 60min
#    Server-side: prefira X-Api-Key (recomendado pelo spec)
response = requests.get(
    "https://data.maisretorno.com/mr-data/v4/api/asset-info/petr4:b3",
    headers={"X-Api-Key": api_key},
)
print(response.json())
// 1. Gere a api_key uma única vez no portal e guarde com segurança
//    (formato: mr_xxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxx)
const apiKey = "SUA_API_KEY";

// 2. Use direto nas requisições — sem POST /auth, sem expiração de 60min
//    Server-side: prefira X-Api-Key (recomendado pelo spec)
const response = await fetch(
  "https://data.maisretorno.com/mr-data/v4/api/asset-info/petr4:b3",
  { headers: { "X-Api-Key": apiKey } }
);
console.log(await response.json());
Migração rápida: remova a chamada inicial ao POST /auth, troque o header Authorization: Bearer <token> por X-Api-Key: <api_key> e exclua toda a lógica de retry/renovação por expiração. Se o cliente roda em browser, mantenha Authorization: Bearer <api_key> (CORS só libera esse header).

Breaking Changes

Mudanças que quebram parsing/paths

Campos reorganizados

API Antiga
GET /market-data/v4/search/{term}
API Nova
GET /mr-data/v4/api/search/{query}

Parâmetros de Input

ParâmetroAPI AntigaAPI NovaMudança
term / querypath, string (term)path, string (query)Renomeado
include_tesouro_tituloquery, bool, default true--Removido
has_quotes--query, bool, optionalNovo

Campos do Response (array de objetos)

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
identifierstringidentifierstringSem mudança
namestringnicenamestringRenomeado
asset_typestringtypestringRenomeado
has_quotesbooleanhas_quotesbooleanSem mudança
slugstring|null----Removido

2. Stats

API Antiga
GET /market-data/v4/{identifier}/stats
API Nova
GET /mr-data/v4/api/stats/{identifier}

Parâmetros de Input

ParâmetroAPI AntigaAPI NovaMudança
identifierpath, stringpath, stringSem mudança
start_datequery, string (YYYY-MM-DD), optquery, string (YYYY-MM-DD), optSem mudança
end_datequery, string (YYYY-MM-DD), optquery, string (YYYY-MM-DD), optSem mudança
adjustedquery, bool, default true--Removido
format_decimalquery, bool, default falsequery, bool, default falseSem mudança
details--query, bool, default falseNovo

Campos do Response

Campo AntigoTipoCampo NovoTipoMudança
statsobjectstatsobjectSem mudança
Timeframes: last_3_months, last_6_months, last_12_months, last_24_months, last_36_months, last_48_months, last_60_months, ytd, mtd, begin — cada um com: profitability, sharpe_ratio, volatility
----trading_currencystringNovo

3. Quotes (Historical Quotes)

API Antiga
GET /market-data/v4/{identifier}/historical-quotes
API Nova
GET /mr-data/v4/api/quotes/{identifier}
Atenção: A rota mudou de historical-quotes para quotes.

Parâmetros de Input

ParâmetroAPI AntigaAPI NovaMudança
identifierpath, stringpath, stringSem mudança
start_datequery, string (YYYY-MM-DD), optquery, string (YYYY-MM-DD), optSem mudança
end_datequery, string (YYYY-MM-DD), optquery, string (YYYY-MM-DD), optSem mudança
adjustedquery, bool, default truequery, bool, default trueSem mudança
link_old_historic--query, bool, default falseNovo
Fundos divididos em classe e subclasse (link_old_historic): com a Resolução CVM 175, fundos que já existiam foram divididos em classe e subclasses; a série de cotas da subclasse começa na data em que ela foi criada e o histórico anterior ficou guardado na classe. Sem o parâmetro, um fundo de 2015 dividido em 2024 devolve cotas só a partir de 2024. Com link_old_historic=true, quando a subclasse pedida é a continuação direta da série da classe (a primeira cota dela vem até 5 dias depois da última cota da classe), as cotas da classe entram antes das cotas da subclasse — na sobreposição vale a da subclasse — e a série passa a começar na data mais antiga das duas. É a série que o site da Mais Retorno exibe e a questats e drawdown já usam sempre. Subclasse que não continua a série da classe (uma série nova de FIDC, por exemplo) devolve o mesmo com ou sem o parâmetro. Só tem efeito em fundos (:fi).

Atenção ao pedir pelo identificador da classe (CNPJ sem o sufixo de subclasse): comtrue a API escolhe uma subclasse por regra técnica — se a classe não tem cotas, a de histórico mais antigo; se tem, pode trocar pela que cobre o mesmo período com dados mais recentes e emenda no fim a que continua a série. Essa escolha não é a "subclasse principal", cadastro que não existe em nenhuma fonte oficial; num FIDC, por exemplo, pode cair na cota subordinada. Peça sempre o identificador da subclasse que o investidor detém — o endpoint fund-structure lista todas as subclasses de um fundo.
Qual série pedir: adjusted=true (default) devolve a série ajustada, que reinveste proventos, amortização e juros — é a base correta para calcular rentabilidade, mas é recalculada para trás a cada novo provento, então o valor de uma data passada muda com o tempo.adjusted=false devolve o preço efetivamente negociado no dia (o PU, no caso de renda fixa) — é o que preserva o valor observado na data e a base correta para registrar uma transação ou manter marcação a mercado histórica. PETR4 em 01/06/2015 fechou a R$ 12,37 negociado; na série ajustada a mesma data valia R$ 3,13 medida em 18/08/2026 e R$ 3,04 em 31/08/2026 — o provento pago no meio reescreveu o histórico inteiro. O parâmetro atua em ações (:b3, :us, :lse), debêntures, tesouro direto, títulos públicos, securitizados e UCITS; fundos, índices, cripto e futuros têm série única e o parâmetro é ignorado.

Campos do Response

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
nicenamestringnicenamestringSem mudança
slugstring|null----Removido
----currencystringNovo
quotes[].dinteger (epoch ms)quotes[].dstring (YYYY-MM-DD)Tipo mudou Breaking

4. Asset Info (Header)

API Antiga
GET /market-data/v4/{identifier}
API Nova
GET /mr-data/v4/api/asset-info/{identifier}
Mudança estrutural: A API antiga retorna campos específicos do tipo de ativo aninhados sob uma chave com o nome do mercado (ex: fi, b3, deb). A API nova retorna tudo flat no root level com DTOs específicos por tipo de ativo.

Campos Comuns (todos os tipos)

Campo AntigoTipoCampo NovoTipoMudança
identifierstringidentifierstringSem mudança
nicenamestringnicenamestringSem mudança
asset_type_mrstringtypestringRenomeado
first_quote_datestringfirst_quotestringRenomeado *
last_quote_datestringlast_quotestringRenomeado *
last_updatestringlast_updatestringSem mudança
has_quotesbooleanhas_quotesbooleanSem mudança
* Exceção IDX: Para Índices, os campos mantêm o nome antigo first_quote_date / last_quote_date.
Nota: Na nova API, last_update e has_quotes estão presentes em B3, DEB, IDX, TD, TP e Crypto, mas não em FI e RFS.
Fundos — link_old_historic (novo, query, bool, default false): comtrue, first_quote e last_quote passam a ser o início e o fim da série quequotes devolve com o mesmo parâmetro (histórico da classe emendado antes da subclasse que a continua e, no identificador da classe, a subclasse que a API escolhe — devolvida no campolinked_identifier). Use para validar o período antes de pedir as cotas — as duas rotas precisam concordar. Só tem efeito em :fi.

Asset Info por Tipo de Ativo

Fundos (FI)

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
fi (wrapper)object----Removido campos no root
fi.cnpjintegercnpjstringRoot Tipo mudou
fi.namestringnamestringRoot
fi.networthnumber----Removido → fund-class-subclass
fi.adminobjectadminobjectRoot
fi.asset_managersarrayasset_managersarrayRoot
----trading_currencystringNovo
----classes_subclassesarrayNovo (RCVM 175)

B3 (Ações, FIIs, ETFs, etc.)

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
b3 (wrapper)object----Removido campos no root
b3.tickerstringtickerstringRoot
b3.company_namestringcompany_namestringRoot
b3.market_capintegermarket_capnumberRoot
b3.trading_currencystringtrading_currencystringRoot
b3.asset_classstringtypestringRenomeado

Índices (IDX)

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
idx (wrapper)object----Removido campos no root
idx.tickerstringtickerstringRoot
idx.trading_currencystringtrading_currencystringRoot
Nota: Para IDX, os campos de data mantêm o nome antigo: first_quote_date e last_quote_date.

Tesouro Direto (TD)

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
td (wrapper)object----Removido campos no root
td.maturity_datestringmaturitystringRoot Renomeado
----trading_currencystringNovo

Títulos Públicos (TP)

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
tp (wrapper)object----Removido campos no root
tp.isinstringisinstringRoot
tp.maturity_datestringmaturity_datestringRoot
----trading_currencystringNovo

Crypto (CC) — Novo na API nova

CampoTipo
nicenamestring
identifierstring
trading_currencystring
typestring
first_quotestring
last_quotestring
Na API antiga, crypto era retornado no search mas não havia um DTO específico para o header.

5. Available Wallets

API Antiga
GET /market-data/v4/wallet/{cnpj}/available-months
API Nova
GET /mr-data/v4/api/available-wallets/{identifier}

Campos do Response

Campo AntigoTipo AntigoCampo NovoTipo NovoMudança
dateinteger (epoch ms)datestring (YYYY-MM-DD)Tipo mudou Breaking
openbooleanopenbooleanSem mudança

6. Wallet Detail

API Antiga
GET /market-data/v4/wallet/{cnpj}/details
API Nova
GET /mr-data/v4/api/wallet-detail/{identifier}

Principais mudanças:

AspectoAPI AntigaAPI Nova
Data de referênciadate (epoch int)reference_month (string "YYYY-MM")
AgrupamentoPor tipo de aplicação (chave dinâmica)Por classes[] (array estruturado)
PercentuaisNão tinhapercentage, class_percentage, value

7. Fund Class/Subclass Novo

API Antiga
Não existia
API Nova
GET /mr-data/v4/api/fund-class-subclass/{identifier}
Endpoint novo: Retorna informações detalhadas de uma classe ou subclasse de fundo (estrutura RCVM 175). Muitos campos que antes estavam em fi.cvm_property do endpoint /{identifier} agora estão neste endpoint dedicado.

Campos do Response (FundClassSubclassDto)

CampoTipoDescrição
identifierstringIdentificador da classe/subclasse
nicenamestringNome amigável do fundo
quotaholdersnumber|nullNúmero de cotistas
networthnumber|nullPatrimônio líquido
first_quotestringData da primeira cotação
last_quotestringData da última cotação
benchmarkstringBenchmark do fundo
long_term_tributationbooleanTributação de longo prazo
pension_fundbooleanSe é fundo de pensão
exclusiveboolean|nullSe é fundo exclusivo
situationstring|nullSituação do fundo
cvm_category Novostring|nullCategoria CVM
anbima_type Novostring|nullTipo ANBIMA
Parâmetro link_old_historic (query, bool, default false): comtrue, first_quote e last_quote passam a ser o início e o fim da série quequotes devolve com o mesmo parâmetro — o histórico da classe emendado antes da subclasse que a continua. A resposta ganha linked_identifier: a série que começa em first_quote(a própria, ou a subclasse que a API escolheu quando o pedido foi pela classe). Use para validar o período antes de pedir as cotas; as duas rotas precisam concordar.