Câmbio
Converta reais em dólares e envie para contas no exterior pela API, da cotação ao comprovante.
Em liberação
As rotas de câmbio estão no contrato da API e são liberadas por produto, começando pelo sandbox. Peça o produto fx.exchange ao seu contato na Kodano. A loja precisa estar habilitada para câmbio: o cadastro e a aprovação da loja acontecem fora da API, no portal Kodano.
O caso típico é pagar um fornecedor no exterior: sua aplicação cota o valor, cadastra a conta de destino, cria a operação e mostra ao pagador um Pix; quando o Pix é pago, a Kodano converte e entrega o dólar na conta de destino. Hoje o câmbio é à vista (SPOT), de real para dólar (BRL_TO_USD).
Todas as rotas exigem X-Merchant-Id com credencial de organização, e os POST que criam recursos exigem Idempotency-Key. Valores são inteiros na menor unidade da moeda (centavos de real ou de dólar) com currency; a taxa (rate) é um decimal em string, em reais por dólar.
Taxa e tarifas
A rate já inclui o spread da Kodano, que vem das taxas da sua loja ou, sem taxa própria, da taxa padrão da plataforma; não há linha de spread separada. A tarifa do rail de entrega (COVER_FEE) aparece em fees e já está somada em totalPayin.
Cadastre a conta de destino
POST /v1/fx/payout-accounts com o rail (ACH, WIRE, SWIFT ou SEPA), o titular e os dados bancários. A Kodano valida routing, BIC e IBAN antes de aceitar; dado inválido responde 422 FX.PAYOUT_ACCOUNT_VALIDATION com errors[] por campo.
{
"rail": "ACH",
"displayName": "Fornecedor EUA",
"holder": { "name": "Global Trade LLC", "accountClass": "BUSINESS", "relationship": "VENDOR_OR_SUPPLIER", "businessIndustryNaics": "522320" },
"bank": { "name": "Chase", "routingNumber": "021000021", "accountNumber": "000123456789", "accountType": "CHECKING" },
"address": { "line1": "100 Main St", "city": "New York", "stateProvinceRegion": "NY", "country": "US", "postalCode": "10001" }
}A conta volta mascarada (só os últimos 4 dígitos) e ACTIVE. SWIFT para terceiro volta PENDING_DOCUMENT: envie o documento da operação (fatura, pedido de compra, contrato) em POST /v1/fx/payout-accounts/{id}/documents para ativá-la. A conta é reaproveitada em quantas operações você quiser; DELETE desativa do lado da Kodano.
Simule e cote
POST /v1/fx/quotes/preview mostra a taxa (com o spread da Kodano) e o valor estimado, sem gravar nada. POST /v1/fx/quotes grava a cotação com o rail escolhido e o total a pagar.
{
"product": "SPOT",
"direction": "BRL_TO_USD",
"amount": { "amount": 500000, "currency": "BRL" },
"amountSide": "PAYIN",
"payoutRail": "ACH"
}amountSide: PAYIN fixa o que o pagador paga em reais; PAYOUT fixa o que chega em dólar. A cotação é indicativa e vale até expiresAt: o valor que vale é o da operação.
Crie a operação
POST /v1/fx/operations com a cotação, a conta de destino e o aceite dos termos. A resposta traz os valores vinculantes e o Pix copia e cola.
{
"quoteId": "fxq_0192f4a1c3d24e5f8a9b0c1d2e3f4a5b",
"payoutAccountId": "fxa_0192f4a0b2c14d3e7f8a9b0c1d2e3f4a",
"customerReference": "pedido-8841",
"authorization": { "accepted": true, "termsVersion": "global-spot-2026-10" }
}repricedFromQuote: trueindica que os valores mudaram desde a cotação. Mostrepayinepayoutda operação ao pagador antes de ele pagar.- Gere o QR Code a partir de
paymentInstructions.pixCopyPaste. O Pix vence empaymentInstructions.expiresAt; vencido, a operação viraEXPIREDe você cria outra a partir de uma cotação nova. - Sua aplicação responde por colher o aceite de quem autoriza a transferência.
accepted: falseou termos desatualizados respondem422 FX.AUTHORIZATION_REQUIRED. 202comstatus: UNKNOWNsignifica que a Kodano ainda não confirmou a criação. Consulte a operação; nunca repita oPOSTcom outraIdempotency-Key.
Acompanhe até o fim
GET /v1/fx/operations/{id} devolve o status e a linha do tempo. Os eventos abaixo avisam do desfecho; consulte também por GET (a cada 5 a 10 segundos) se precisar acompanhar a operação em andamento.
| Status | Significado |
|---|---|
AWAITING_PAYMENT | Esperando o pagamento do Pix |
PAYMENT_RECEIVED, CONVERTING, PAYOUT_IN_PROGRESS | Em andamento |
SETTLED | Dólar entregue na conta de destino (final) |
EXPIRED | Pix não pago no prazo (final) |
FAILED | Falha sem dinheiro recebido (final) |
ACTION_REQUIRED | Pix recebido, mas o envio não se completou; a Kodano abre a devolução |
REFUND_PENDING, REFUNDED, REFUND_FAILED | Devolução do valor pago |
GET /v1/fx/operations lista as operações, com filtros por status, direction, período e customerReference. Para falar com o suporte, use o supportReference da operação.
Baixe o comprovante
Em SETTLED e REFUNDED, GET /v1/fx/operations/{id}/receipt devolve a URL assinada do PDF. A URL vale por pouco tempo; peça outra quando precisar. Antes disso a resposta é 409 FX.RECEIPT_NOT_AVAILABLE.
Limites e erros
- Valor fora dos limites da faixa responde
422 FX.AMOUNT_BELOW_MINIMUMouFX.AMOUNT_ABOVE_MAXIMUM. Acima do limite disponível da loja,422 FX.LIMIT_EXCEEDEDtrazremaining. - Loja sem câmbio habilitado responde
422 FX.NOT_ENABLED; loja habilitada mas ainda não apta a operar,409 FX.ACCOUNT_NOT_READY. - Cotação vencida responde
410 FX.QUOTE_EXPIRED: crie outra. - Conta de destino inativa ou de rail diferente do da cotação responde
422 FX.PAYOUT_ACCOUNT_INVALID.
Eventos
Cadastre um endpoint de webhook (Configurar endpoints) com o escopo fx:operations:read e assine os eventos de câmbio. O data.object de cada evento tem o formato do GET /v1/fx/operations/{id}.
| Evento | Quando |
|---|---|
fx.operation.settled | Dólar entregue na conta de destino (SETTLED) |
fx.operation.expired | Pix não pago no prazo (EXPIRED) |
fx.operation.failed | Falha sem dinheiro recebido (FAILED) |
fx.operation.action_required | Pix recebido sem entrega; a Kodano abre a devolução (ACTION_REQUIRED) |
fx.operation.refunded | Valor devolvido ao pagador (REFUNDED) |
Eventos são avisos de desfecho: a entrega pode se repetir e chegar fora de ordem. Deduplique por id e, em caso de dúvida, confirme o estado com o GET da operação, que é a fonte da verdade. Os estados intermediários (PAYMENT_RECEIVED, CONVERTING, PAYOUT_IN_PROGRESS) e a devolução em andamento (REFUND_PENDING) não geram evento; use o GET se precisar deles.