12

I'm using Stripe to process payments. I have a platform where international Connect accounts can sell items to others through my platform.

My platform is USD. In this specific example, the Connect account is in CAD (Canada Dollar). When someone purchases an item from this CAD Connect Account, Stripe puts the money in my platform account, leaves my app fee there, and then moves the correct amount into the CAD Connect account. It converts this amount to CAD. In the stripe GUI I can find the exchange rate and amount transferred in CAD, as circled in the screenshot below. But I can't find these attributes in the API.

enter image description here

The only object I've seen with an exchange_rate attribute is the balance transaction. However, when I get the balance transaction for the transaction in the screenshot, I get this response object:

Request: https://api.stripe.com/v1/balance_transactions/txn_1IBNiNLLBOhef2QNqIeaNg9o

Response:

{ 
"id": "txn_1IBNiNLLBOhef2QNqIeaNg9o", 
"object": "balance_transaction", 
"amount": -7777, 
"available_on": 1611619200, 
"created": 1611076199, 
"currency": "usd", 
"description": null, 
"exchange_rate": null, 
"fee": 0, 
"fee_details": [], 
"net": -7777, 
"reporting_category": "transfer", 
"source": "tr_1IBNiNLLBOhef2QNcNqv3IlS", 
"status": "pending", 
"type": "transfer" }

The problem here is that the balance transaction object above only shows this transaction in USD: $77.77 USD came out of my platform account.

But it doesn't show the conversion rate or the amount in CAD. When this $77.00 went into the CAD Connect account, as we can see in the GUI screenshot, that $77.77 was converted to $98.02 CAD and the exchange rate was 1.26039 (USD->CAD).

How can I find this CAD amount and exchange rate through the API?

Dashiell Rose Bark-Huss
  • 2,173
  • 3
  • 28
  • 48

4 Answers4

7

The Transfer made to the connected account in this screenshot is in USD. The conversion happens after the Transfer itself. The funds are sent in USD and then in the connected account they get converted to that account's default Currency.

You want to look at the Transfer's destination_payment property which has the py_123 id for the Charge on the connected account. That Charge has a BalanceTransaction object (similar to the Transfer one you shared). That BalanceTransaction would reflect the conversion from USD to CAD and surface the exchange rate used in the exchange_rate property in that case.

koopajah
  • 23,792
  • 9
  • 78
  • 104
  • 2
    That makes a lot of sense. But I tried it and got an error: I went to this endpoint `https://api.stripe.com/v1/transfers/tr_1IBNiNLLBOhef2QNcNqv3IlS?expand[]=destination_payment` to find the balance transaction id. I got: `{"destination_payment": { "balance_transaction": "txn_1IBNiOLKojKNEaYINS8SFq4t"}}`. Then I used the endpoint `https://api.stripe.com/v1/balance_transactions/txn_1IBNiOLKojKNEaYINS8SFq4t` but I got an error :`"No such balance transaction: 'txn_1IBNiOLKojKNEaYINS8SFq4t'"`. Any idea why? – Dashiell Rose Bark-Huss Jan 20 '21 at 02:50
  • 1
    I figured it out. I needed to add the Stripe-Account header in the request with the connect account id. Thank you. – Dashiell Rose Bark-Huss Jan 20 '21 at 03:16
7

In case you need to know the currency rate before the actual transaction happens they provide the currency rates here

HOWEVER, it's only a frontend page and it requires authorization. On top of that, it's updated once every 12 hours. There is no official API that returns currency rates.

There is a small SaaS product that provides stripe currency rates as a REST API. https://striperates.com/

megapixel23
  • 829
  • 1
  • 10
  • 22
  • 3
    Thanks! right now I'm using a free exchange rate api, though it's not ideal. That saas product might be good in the future. I wish stripe just had their updated rates in the API. – Dashiell Rose Bark-Huss Mar 26 '21 at 16:58
4

Here is the way I did : I simulated a payment in a foreign currency to a US based account (so that it is presented in US$), then I retrieved the balance transaction associated, and the exchange_rate argument

async function exchangeFeesToUS(currency) {

  const paymentIntent = await stripeTestUS.paymentIntents.create({
    amount: 10000,
    currency: currency,
    payment_method_types: ['card'],
    customer: "ANY_CUSTOMER_WITH_A_PAYMENT_METHOD",
    payment_method: "ANY_CARD_ASSOCIATED_TO_THIS_CUSTOMER",
    confirm: true
  });

  return await balanceTransaction(paymentIntent).then(balance => {
    return balance.exchange_rate
  })

}

async function balanceTransaction(paymentIntent) {

  const chargeId = paymentIntent.charges.data[0].id;

  const charge = await stripeTestUS.charges.retrieve(
    chargeId
  );

  return await stripeTestUS.balanceTransactions.retrieve(
    charge.balance_transaction
  );

}

Now, if you want to convert to another currency than the US$, just call the aforementioned function twice :

async function exchangeFeesToCUSTOM_CURRENCY(currency) {

  const rate = await exchangeFeesToUS(currency)
  const rateCUSTOM_CURRENCY = await exchangeFeesToUS('your_custom_currency')
  return rate / rateCUSTOM_CURRENCY

}
2

In Java you can do

Stripe.apiKey = "sk_live_...";
Transfer transfer = Transfer.retrieve("tr_...");
RequestOptions requestOptions = RequestOptions.builder().setStripeAccount("acct_...").build();
Charge charge = Charge.retrieve(transfer.getDestinationPayment(), requestOptions);
BalanceTransaction balanceTransaction = BalanceTransaction.retrieve(charge.getBalanceTransaction(), requestOptions);
balanceTransaction.getExchangeRate();
balanceTransaction.getNet();
balanceTransaction.getCurrency();
cnmuc
  • 6,025
  • 2
  • 24
  • 29