Obter taxas de câmbio ao vivo no Power BI é uma daquelas tarefas que parecem prontas muito antes de realmente estarem. Você cola uma URL de API em Obter dados → Web, uma tabela de taxas aparece, sua medida de receita convertida se acende e você publica. Dois dias depois, a atualização do conjunto de dados falha no serviço do Power BI com uma mensagem sobre uma fonte de dados dinâmica — ou ela funciona e converte silenciosamente cada transação histórica pela taxa de hoje.
Este guia cobre o caminho inteiro: uma consulta M do Power Query que devolve uma tabela de taxas limpa, o padrão RelativePath que a mantém atualizável no serviço, uma função de taxas históricas para converter na data da transação, uma medida DAX para uma moeda de relatório dinâmica e a matemática de contagem de requisições que decide se o seu agendamento cabe dentro de um plano de API.
Todas as consultas abaixo foram escritas contra os formatos de resposta documentados da API da Finexly. Se você já leu nosso guia sobre taxas de câmbio ao vivo no Excel, o M aqui vai parecer familiar — mas o Power BI acrescenta uma camada de atualização do lado do serviço que o Excel não tem, e é nessa camada que a maioria desses projetos quebra.
As três formas de levar taxas para o Power BI
| Abordagem | Atualiza no serviço? | Chave de API segura? | Taxas históricas | Ideal para |
|---|---|---|---|---|
| Conector Web, URL colada na caixa de diálogo | Frequentemente não — a URL costuma virar uma fonte de dados dinâmica | ❌ A chave fica na URL | Não | Uma prova de conceito de cinco minutos |
Consulta em branco com Web.Contents + RelativePath | ✅ Sim | ✅ Via cabeçalho | ✅ Sim | Quase todo modelo real |
| Dataflow (ou pipeline do Fabric) alimentando uma tabela de taxas | ✅ Sim, e desacoplado da atualização do relatório | ✅ Via cabeçalho | ✅ Sim | Vários relatórios, muitas linhas |
Método 1: uma tabela de taxas ao vivo com Power Query
Abra Transformar dados → Nova fonte → Consulta em branco → Editor Avançado e cole isto. Retorna uma linha por par de moedas, com carimbo de tempo UTC da coleta.
let
ApiKey = "YOUR_API_KEY",
Base = "USD",
Symbols = "EUR,GBP,JPY,CHF,AUD,CAD,SEK,NZD",
Source = Json.Document(
Web.Contents(
"https://api.finexly.com",
[
RelativePath = "v1/latest",
Query = [ base = Base, symbols = Symbols ],
Headers = [ #"Authorization" = "Bearer " & ApiKey ]
]
)
),
Rates = Record.ToTable( Source[rates] ),
Renamed = Table.RenameColumns( Rates, {{"Name", "Quote"}, {"Value", "Rate"}} ),
AddBase = Table.AddColumn( Renamed, "Base", each Base, type text ),
AddStamp = Table.AddColumn( AddBase, "RetrievedUTC", each DateTimeZone.UtcNow(), type datetimezone ),
Typed = Table.TransformColumnTypes(
AddStamp,
{{"Quote", type text}, {"Rate", type number}}
)
in
TypedO endpoint que ela chama fica assim na linha de comando — vale rodar uma vez para ver o formato que você está interpretando:
curl "https://api.finexly.com/v1/latest?base=USD&symbols=EUR,GBP,JPY" \
-H "Authorization: Bearer YOUR_API_KEY"{
"success": true,
"base": "USD",
"date": "2026-09-01",
"rates": { "EUR": "…", "GBP": "…", "JPY": "…" }
}Por que RelativePath e Query não são opcionais
Esta é a linha mais importante do artigo, então ganha um título próprio.
Se você montar a URL como uma única string concatenada — "https://api.finexly.com/v1/latest?base=" & Base — o Power Query não consegue determinar o destino até a consulta rodar. A Microsoft classifica isso como uma fonte de dados dinâmica, e fontes dinâmicas não são atualizadas no serviço do Power BI, por razões de segurança e privacidade. O relatório atualiza perfeitamente no seu notebook e falha assim que é agendado.
Passar o caminho em RelativePath e os parâmetros em Query é a exceção documentada. O Power BI passa a resolver uma única URL base estática — https://api.finexly.com — para as verificações de credencial e privacidade, enquanto as partes variáveis continuam variáveis. Daí saem três regras:
- A URL base precisa ser uma string literal. Sem parâmetros, sem concatenação, sem nenhum
&. RelativePathdeve ser o caminho fixo do endpoint."v1/latest", não"v1/latest?base=USD".- Nunca concatene dentro de
Query. Passe um registro de pares nome/valor e deixe o Power Query fazer a codificação de URL. Ele também escapa caracteres que quebrariam a requisição.
Configurando as credenciais
Na primeira execução, o Power BI pergunta como autenticar em https://api.finexly.com. Escolha Anônimo. Parece errado, mas está certo: a chave de API viaja no cabeçalho Authorization que você forneceu no código M, e não pelo repositório de credenciais do Power BI. Escolher API Web ou Básica fará o Power BI adicionar o próprio cabeçalho e a requisição será rejeitada.
Defina o nível de privacidade como Público ou Organizacional de forma consistente em todas as fontes. Níveis de privacidade incompatíveis são a segunda causa mais comum de uma atualização que funciona no Desktop e falha no serviço — o Power BI bloqueia a consulta em vez de arriscar vazar dados de uma fonte na requisição de outra.
Uma ressalva honesta: a chave agora fica armazenada como texto puro dentro da consulta. Qualquer pessoa que abrir o .pbix consegue lê-la. Para qualquer coisa compartilhada além da sua própria máquina, promova a chave a um parâmetro do Power Query e mantenha a versão preenchida em um dataflow de propriedade de uma conta de serviço, para que autores de relatórios consumam a tabela de taxas sem nunca ver a credencial.
Método 2: taxas históricas para conversão na data da transação
Uma tabela ao vivo responde "quanto vale EUR/USD agora". Ela não responde "qual foi nossa receita de janeiro em USD", e usá-la para isso é o erro mais caro deste assunto todo — reapresentar os números do trimestre passado porque o modelo os reconverteu a uma taxa nova é exatamente o tipo de coisa que auditores procuram. Se o seu relatório alimenta algo que você terá de defender depois, leia também nosso guia sobre taxas de câmbio e apuração fiscal.
Você precisa de uma tabela de taxas indexada por data. Esta função M encapsula o endpoint de séries temporais e devolve uma linha por data e por moeda:
let
FxHistory = (base as text, symbols as text, startDate as date, endDate as date) as table =>
let
ApiKey = "YOUR_API_KEY",
Source = Json.Document(
Web.Contents(
"https://api.finexly.com",
[
RelativePath = "v1/timeseries",
Query = [
base = base,
symbols = symbols,
start_date = Date.ToText( startDate, [Format = "yyyy-MM-dd", Culture = "en-US"] ),
end_date = Date.ToText( endDate, [Format = "yyyy-MM-dd", Culture = "en-US"] )
],
Headers = [ #"Authorization" = "Bearer " & ApiKey ]
]
)
),
Days = Table.RenameColumns( Record.ToTable( Source[rates] ), {{"Name", "RateDate"}} ),
Expanded = Table.ExpandRecordColumn( Days, "Value", Record.FieldNames( Days{0}[Value] ) ),
Unpivoted = Table.UnpivotOtherColumns( Expanded, {"RateDate"}, "Quote", "Rate" ),
AsDate = Table.TransformColumns(
Unpivoted,
{{"RateDate", each Date.FromText( _, [Format = "yyyy-MM-dd", Culture = "en-US"] ), type date}}
),
AddBase = Table.AddColumn( AsDate, "Base", each base, type text ),
Typed = Table.TransformColumnTypes( AddBase, {{"Quote", type text}, {"Rate", type number}} )
in
Typed
in
FxHistoryDois detalhes aí fazem trabalho de verdade:
Culture = "en-US"emDate.ToTexte emDate.FromText. Sem isso, uma máquina configurada em alemão ou francês envia01.09.2026comostart_datee a API rejeita — ou pior, a atualização de um colega produz uma tabela com formato diferente da sua. A localidade é a variável invisível de todo projeto de Power Query que atravessa mais de um país.Table.UnpivotOtherColumns. A API devolve datas como chaves de registro, com um registro aninhado de moedas. Transformar para o formato longoRateDate / Base / Quote / Rategera uma tabela que se relaciona limpo com uma dimensão de data e não precisa ser remodelada a cada moeda nova.
Invoque uma vez por carga: FxHistory( "USD", "EUR,GBP,JPY", #date(2026,1,1), Date.From( DateTime.LocalNow() ) ).
Como taxas de datas passadas nunca mudam, esta tabela é o caso clássico de atualização incremental: particione por RateDate, atualize os últimos 7 dias, arquive o resto. Seu tempo de atualização para de crescer com o histórico — e sua contagem de requisições também.
Não chame a API uma vez por linha
O padrão que mata esses modelos é invocar uma função de taxa como coluna personalizada na tabela fato. Dez mil transações significam dez mil requisições HTTP por atualização, uma atualização de quarenta minutos e uma conta de cota que chega antes do almoço.
Faça a conta antes de construir. O Power BI Pro permite 8 atualizações agendadas por conjunto de dados por dia; Premium Per User e capacidade Fabric permitem 48. Uma única chamada a /v1/latest cobrindo todas as moedas necessárias, atualizada no máximo do Pro, custa 8 requisições por dia — cerca de 240 por mês, confortavelmente dentro de um plano gratuito de 1.000. O mesmo agendamento com uma função por linha é ilimitado. Mesmo no máximo de 48 atualizações do PPU, uma chamada consolidada fica em torno de 1.440 requisições por mês, o que é um plano pago pequeno em vez de uma catástrofe linha a linha. Nossos planos de preços listam os limiares se você precisar dimensionar isso com precisão.
Quando mais de um relatório precisa das taxas, mova a consulta para um dataflow. O dataflow chama a API no próprio agendamento e materializa o resultado; cada conjunto de dados a jusante lê do armazenamento em vez de bater na API de novo. Cinco relatórios sobre o mesmo dataflow fazem um conjunto de requisições, não cinco.
Convertendo valores: mesclagem no Power Query vs medida DAX
Há dois lugares legítimos para aplicar a conversão, e eles respondem perguntas diferentes.
Opção A: mesclar no Power Query
Se a sua moeda de relatório é fixa — tudo é reportado em USD, ponto — faça a junção no carregamento.
- Carregue a tabela fato no Power Query.
- Mesclar Consultas com a tabela de taxas, casando por código de moeda e data. Segure
Ctrle selecione as colunas na mesma ordem nas duas tabelas. - Expanda apenas a coluna
Ratee defina como Número decimal fixo. - Selecione
AmounteRate, depois Adicionar Coluna → Padrão → Multiplicar. - Desabilite o carregamento da tabela de taxas se nada mais a referenciar.
É rápido, materializa uma vez e não pode ser manipulado por uma segmentação. Esse último ponto é a contrapartida.
Opção B: uma medida DAX com moeda de relatório selecionável
Se os usuários precisam alternar o relatório inteiro entre USD, EUR e GBP, a conversão precisa acontecer em tempo de consulta. Adicione uma tabela desconectada Reporting Currency com uma coluna de códigos ISO, coloque numa segmentação e escreva:
Revenue (Reporting Currency) =
VAR ReportingCurrency = SELECTEDVALUE( 'Reporting Currency'[Code], "USD" )
RETURN
SUMX (
'Sales',
VAR TxCurrency = 'Sales'[CurrencyCode]
VAR TxDate = 'Sales'[OrderDate]
VAR Rate =
CALCULATE (
MAX ( 'FX Rates'[Rate] ),
REMOVEFILTERS ( 'FX Rates' ),
'FX Rates'[Base] = TxCurrency,
'FX Rates'[Quote] = ReportingCurrency,
'FX Rates'[RateDate] = TxDate
)
RETURN 'Sales'[Amount] * Rate
)Três coisas para notar:
- As linhas
VARsão estruturais. CapturarTxCurrencyeTxDateem variáveis antes doCALCULATEas fixa à linha atual doSUMX. Referenciar as colunas diretamente nos argumentos de filtro convida a um bug de transição de contexto que produz totais plausíveis, mas errados. REMOVEFILTERS( 'FX Rates' )impede que qualquer filtro que chegue à tabela de taxas estreite a busca.- Uma taxa ausente retorna
BLANK(), eAmount * BLANK()éBLANK(). É esse o comportamento desejado. Uma linha que silenciosamente cai para o valor não convertido é uma linha que infla seu total pelo tamanho da taxa de câmbio.
A armadilha do relacionamento
Não crie um relacionamento físico da tabela fato para a tabela de taxas apenas pelo código de moeda. O código de moeda não é único em uma tabela indexada por data, então o Power BI propõe um relacionamento muitos-para-muitos — e muitos-para-muitos com filtro bidirecional vai alegremente multiplicar suas linhas e sua receita. Use a mesclagem composta no Power Query, ou mantenha a tabela de taxas desconectada e busque as taxas em DAX como acima.
Cinco erros que produzem números errados sem gerar erro
- URLs concatenadas. Atualiza no Desktop, falha no serviço com "Este conjunto de dados inclui uma fonte de dados dinâmica". Corrigido com
RelativePatheQuery. - Pares invertidos.
base=USD&symbols=EURdevolve USD→EUR. Se a sua tabela fato guarda valores em EUR, você precisa do recíproco. Confira um par conhecido na mão antes de confiar em qualquer total. Nossa referência ISO 4217 ajuda se houver dúvida sobre qual código vai de cada lado. - Taxa de hoje em linhas históricas. O número muda a cada atualização e ninguém percebe até alguém comparar duas exportações do mesmo relatório.
- Datas e decimais em formato regional. Uma vírgula decimal transforma
1,0842em texto,Table.TransformColumnTypesdevolve um erro que o modelo trata como vazio, e as linhas afetadas somem dos seus totais. - Arredondar na etapa errada. Arredonde uma vez, na apresentação, depois da multiplicação. Arredondar a taxa para quatro casas antes de multiplicar um valor de sete dígitos cria uma discrepância visível contra o sistema contábil.
Perguntas frequentes
O Power BI consegue atualizar taxas de câmbio automaticamente?
Sim. Um conjunto de dados publicado pode ser agendado para até 8 atualizações por dia no Power BI Pro e 48 por dia no Premium Per User ou capacidade Fabric. O endpoint XMLA do Premium permite que ferramentas externas disparem atualizações fora desses limites. A consulta de taxas não precisa de nada especial além de ser construída com Web.Contents + RelativePath para que o serviço a aceite.
Como passo uma chave de API com segurança no Power BI?
Coloque-a no registro Headers de Web.Contents como Authorization = "Bearer " & ApiKey e escolha autenticação Anônima quando o Power BI perguntar. Isso mantém a chave fora da URL, fora dos logs de proxy e fora do histórico do navegador. Não criptografa a chave dentro do .pbix — para modelos compartilhados, guarde a chave em um dataflow de propriedade de uma conta de serviço e deixe os relatórios lerem a tabela materializada.
Por que meu conjunto de dados diz "Este conjunto de dados inclui uma fonte de dados dinâmica"?
Porque a URL é montada em código, então o Power BI não consegue verificar o destino antes de a consulta rodar e se recusa a atualizá-la no serviço. Reconstrua a chamada com uma URL base estática mais as opções RelativePath e Query, republique e informe novamente a credencial para a URL base.
Como converto valores usando a taxa de câmbio da data da transação?
Carregue uma tabela de taxas indexada por data a partir de um endpoint de séries temporais e case por moeda e data — via mesclagem composta no Power Query, ou com uma busca CALCULATE dentro de SUMX como mostrado acima. Nunca junte só por moeda; você vai pegar em silêncio a linha de taxa que por acaso ficar em primeiro na ordenação.
Existe uma API de câmbio gratuita que funcione com o Power BI?
Sim. O nível gratuito da API de câmbio gratuita da Finexly inclui 1.000 requisições por mês sem cartão de crédito, o que cobre com folga um conjunto de dados com licença Pro atualizando oito vezes ao dia. Se você está avaliando provedores por limites de atualização, profundidade histórica ou cobertura de moedas, compare APIs de câmbio antes de conectar uma a um modelo que você vai manter por anos.
Comece com a Finexly
Pronto para colocar taxas de câmbio ao vivo nos seus relatórios do Power BI? Pegue sua chave gratuita da API da Finexly — sem cartão de crédito. Comece com 1.000 requisições gratuitas por mês e evolua conforme crescer. Taxas em tempo real e históricas para mais de 170 moedas, a partir de uma única API REST que se comporta igual seja chamada do Power Query, do Python ou de um serviço de pagamentos.
Explore More
Vlado Grigirov
Senior Currency Markets Analyst & Financial Strategist
Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...
View full profile →