Migrating to support multiple currencies

To help you support merchants who sell in multiple currencies, Shopify has updated all of its APIs that expose a price. You should update your apps to make sure that whenever they interact with a price, they are using the correct currency, whether that's the shop currency (used for payouts and reporting) or the presentment currency (used by the customer when they place their order).

Throughout the guide, there are example responses and requests that use the REST Admin API. Where possible, there are also examples that use the GraphQL Admin API.

Is my app affected by the multi-currency feature?

Your app is affected if it uses any properties that represent a price (for example, variant prices, tax lines, shipping lines, and transaction amounts) on the following resources:

  • Refund
  • Transaction
  • Order
  • Product
  • Product Variant
  • Checkout

If your app deals with gift cards, discounts, orders, checkouts, or any other activities that involve interacting with prices, then you might need to migrate your app.

Release schedule

The following table shows the release schedule for the multi-currency feature:

October 24, 2018 All changes to the API are live. All affected developers are notified of the breaking changes to the Transaction and Refund resources. Selling in multiple currencies for Shopify Payments is available to all Partners to be tested on their development stores.
December 17, 2018

Shopify begins allowing select Shopify Plus stores to sell in multiple currencies.

After a merchant enables multiple currencies, your app might be incompatible with their store unless you update your app. You should update your app to support multiple currencies by this date.

Mid January, 2019 Shopify expects to allow all Shopify Plus stores to sell in multiple currencies.
To be determined Shopify expects to allow all stores on all Shopify plans to sell in multiple currencies.

What happens if I don't migrate my app to support multiple currencies?

Breaking changes

The changes to the Refund and Transaction resources are breaking changes because they introduce a requirement for creating those resources. If you don't update your app by December 17, 2018, then the following actions might fail on multi-currency orders:

  • using the Refund resource to calculate and create refunds
  • using the Transaction resource to create refund and capture transactions
  • using the Order resource to cancel and refund an order

Negative user experience

The intent of what many existing properties represent has changed. Some properties are in the shop currency, and others are in the presentment currency. Using the wrong currency can create an inconsistent and negative user experience with your app, and can lead to incorrect reporting.

How can I tell if a store is using multiple currencies?

You can use the enabled_presentment_currencies property on the Shop resource to see the how many currencies a store is using. To learn more, see the changes to the Shop resource.

How do I update my app to support multiple currencies?

Review where your app uses a price or currency value. For each instance, ask yourself two questions:

  • Is this property using the shop currency or the presentment currency?
  • Which currency makes the most sense to use?

Changes of intent: shop currency and presentment currency

To support multiple currencies, Shopify has separated two concepts: shop currency and presentment currency.

Previously, all properties that return a price on Shopify resources were in the shop currency. For example, a line item's price was the same value whether it was retrieved from a checkout, an order, or a transaction. That value was the price that the merchant entered in their Shopify admin, and it's the value that's used for reporting and analytics.

After a merchant enables multiple currencies, the intent of some properties change and they are in the presentment currency. If the customer's local currency is enabled, then it's set as the presentment currency and all prices are displayed in it on the online store and at checkout. At that point, some properties are in shop currency, and some properties are in the presentment currency. For example, if you retrieve a line item's price from the Checkout object, then the value is different than if you retrieve it from the resulting Order object.

For some resources, such as the Order resource, all existing properties remain in the shop currency, and new properties are added to represent values in the customer's presentment currency. For other resources, such as the Checkout resource, the existing properties are in the presentment currency.

Changes to Shopify resources

The multi-currency feature has affected the following resources:

Refund resource

When you use the Refund resource to calculate and create refunds for multi-currency orders, the currency property is required whenever a value is provided for amount. The currency value should match the presentment_currency property on the associated order. If you include the amount property but not the currency property, then creating the refund will fail.

View example

POST https://{shop}.myshopify.com/admin/orders/{order_id}/refunds/calculate.json

{
  "refund": {
    "currency": "JPY",
    "shipping": {
      "amount": 220
    },
    "refund_line_items": [
      {
        "line_item_id": 518995019,
        "quantity": 1,
        "restock_type": "no_restock"
      }
    ]
  }
}

Refund

{
  "refund": {
    "currency": "JPY",
    "shipping": {
      "amount": "220",
      "tax": "0",
      "maximum_refundable": "550"
    },
    "refund_line_items": [
      {
        "quantity": 1,
        "line_item_id": 518995019,
        "price": "4143",
        "subtotal": "3700",
        "total_tax": "443",
        "discounted_price": "4143",
        "discounted_total_price": "4143",
        "total_cart_discount_amount": "0",
        ...
      }
     ],
    "transactions": [
      {
        "amount": "4363",
        "kind": "suggested_refund",
        "maximum_refundable": "4691",
        ...
      }
    ]
  }
}

When you retrieve refunds, the transaction property is in the presentment currency of the parent order, but other existing properties, such as refund_line_items and order_adjustments, are in the shop currency. If you want to return all properties in the shop currency, then you can include the URL parameter ?in_shop_currency=true.

You can use new fields on the refund_line_items and order_adjustments properties to return amounts in shop and presentment currencies.

Refund line item properties

New field Description
subtotal_set The subtotal price for the refund line item in shop and presentment currencies.
total_tax_set The total tax amount applied to the refund line item in shop and presentment currencies.

View example

GET https://{shop}.myshopify.com/admin/orders/{order_id}/refunds/{refund_id}.json

{
  "refund": {
    ...
    "refund_line_items": [
      {
        ...
        "subtotal": 100.52,
        "total_tax": 13.26,
        "subtotal_set": {
          "shop_money": {
            "amount": "100.52",
            "currency_code": "USD"
          },
          "presentment_money": {
            "amount": "11500",
            "currency_code": "JPY"
          }
        },
        "total_tax_set": {
          "shop_money": {
            "amount": "13.26",
            "currency_code": "USD"
          },
          "presentment_money": {
            "amount": "1495",
            "currency_code": "JPY"
          }
        },
        ...
      }
    ],
    ...
  }
}

Order adjustment properties

New field Description
amount_set The amount of the order adjustment in shop and presentment currencies.
tax_amount_set The tax amount applied to the order adjustment in shop and presentment currencies.

View example

GET https://{shop}.myshopify.com/admin/orders/{order_id}/refunds/{refund_id}.json

{
  "refund": [
    {
      ...
      "order_adjustments": [
        {
          ...
          "amount": "-8.99",
          "tax_amount": "0.00",
          "amount_set": {
            "shop_money": {
              "amount": "-8.99",
              "currency_code": "USD"
            },
            "presentment_money": {
              "amount": "-1029",
              "currency_code": "JPY"
            }
          },
          "tax_amount_set": {
            "shop_money": {
              "amount": "0.00",
              "currency_code": "USD"
            },
            "presentment_money": {
              "amount": "0",
              "currency_code": "JPY"
            }
          }
        }
      ]
    }
  ]
}

Transaction resource

When you create capture and refund transactions, the currency property is required whenever a value is provided for amount. The value should match the presentment_currency property on the associated order. If you include the amount property but not the currency property, then creating the transaction will fail.

When you retrieve transactions, all money values on the Transaction resource are in the presentment currency by default. If you want to retrieve money values in the shop currency, then include in_shop_currency=1 as a URL parameter in the request.

View example

POST https://{shop}.myshopify.com/admin/orders/{order_id}/transactions.json

{
  "transaction": {
    "kind": "capture",
    "parent_id": 389404469,
    "amount": "45093",
    "currency": "JPY",
  }
}

Response

{
  "transaction": {
    "kind": "capture",
    "gateway": "bogus",
    "status": "success",
    "amount": "45093",
    "currency": "JPY",
    ...
  }
}

Order resource

Existing properties that return a price on the Order resource, such as total_price, are in the shop’s currency, so they might not match the prices that the customer sees at checkout. You can use several new properties to retrieve prices in the customer’s presentment currency.

Creating orders

You can't create multi-currency orders by using the API. If you include the presentment_currency field when you create an order, then the value needs to match the currency field. If the values aren't the same, then the request fails with a 422 error.

Canceling and refunding orders

If you cancel an order and you include the amount property to issue a refund, then the currency property is required.

View example

POST https://{shop}.myshopify.com/admin/orders/{order_id}/cancel.json

{
  "amount": "10.00",
  "currency": "EUR"
}

Order properties

New field Description
presentment_currency The presentment currency for the order.
subtotal_price_set The subtotal price for the order in shop and presentment currencies.
total_discounts_set The total discounts for the order in shop and presentment currencies.
total_line_items_price_set The total price of the order's line items in shop and presentment currencies.
total_price_set The total price of the order in shop and presentment currencies.
total_tax_set The total tax of the order in shop and presentment currencies.
total_shipping_price_set The total shipping price of the order in shop and presentment currencies.

View example

Line item properties

New field Description
price_set The line item price in shop and presentment currencies.
total_discount_set The total discount applied to the line item in shop and presentment currencies.

View example

Line item discount allocation properties

New field Description
amount_set The discount amount allocated to the line in shop and presentment currencies.

View example

Line item tax line properties

New field Description
price_set The price of the tax line in shop and presentment currencies.

View example

Shipping line properties

New field Description
price_set The price of the shipping line in shop and presentment currencies.
discounted_price_set The discounted price of the shipping line in shop and presentment currencies.

View example

Product and Product Variant resources

For the Product and Product Variant resources, the price property is in the shop currency. This means that it doesn't necessarily return the price that the customer sees at checkout.

For example, suppose that a shop's default currency is USD, and a customer selects JPY as their presentment currency. In that case, variant.price still returns a variant's price in USD, and that value won't match the price in JPY that the customer sees.

You can use the presentment_prices property to retrieve the presentment prices that customers see in each enabled currency.

View example

Use compatible gem versions

If you use the shopify_app gem or the shopify_api gem and you access the Product or ProductVariant resource, then you should update to the latest version of those gems.

If you use those gems but you don't want to upgrade to Rails 5, then include the following versions in your Gemfile:

  • gem 'shopify_app', '7.2.8'
  • gem 'shopify_api', '5.1.0'

Other gem versions won't work with the changes to the Product and Product Variant resources. If you don't update your app, then it will break when the include-presentment-prices header is removed and the resource changes are publicly available in every API response. You should update your app by the end of 2018.

Checkout resource

The currency property on the Checkout resource returns the shop’s currency, and the new presentment_currency property returns the currency that the customer used at checkout. All properties that return a price on the resource are in the presentment currency. For example, in the following response, the payment_due amount is expressed in the presentment currency (JPY) and not in the shop's currency (USD).

View example

GET https://{shop}.myshopify.com/admin/checkouts/{token}.json

{
  "checkout": {
    ...
    "currency": "USD",
    "presentment_currency": "JPY",
    "payment_due": "25127",
    "subtotal_price": "21840",
    ...
  }
}

When you create a checkout, you can include the presentment_currency property to select a presentment currency for the checkout. If you don’t include the property, then the presentment currency and all properties that return a price default to the shop’s currency.

View example

POST https://{shop}.myshopify.com/admin/checkouts.json

{
  "checkout": {
    ...
    "presentment_currency": "CAD"
  }
}

Customer resource

On the Customer resource, the new currency property returns the currency that the customer used when they paid for their last order.

View example

GET https://{store}.myshopify.com/admin/customers/{customer_id}.json

{
  "customer": {
    "id": 621076709432,
    ...
    "currency": "JPY",
    ...
  }
}

Shop resource

On the Shop resource, the new enabled_presentment_currencies property contains the currencies that a merchant has enabled. They're returned as an array of ISO 4217 currency codes.

When the merchant changes the currencies they have enabled in their Shopify Payments settings, the enabled_presentment_currencies array changes and the shop/update webhook is fired.

View example

Keeping prices in sync with current conversion rates

Shopify uses conversion rates from a third-party service to convert prices from the shop currency to presentment currencies. Since those conversion rates change over time, the converted presentment prices also change.

Your app shouldn't cache conversion rates or presentment prices, but instead retrieve them from Shopify every time they're needed. If you do plan on caching values, then you can keep your app's data in sync with Shopify by using the new Currency resource to check whether you should refetch data.

The Currency resource represents the currencies that a merchant has enabled for their shop. For each currency, the resource returns the three-letter currency code (ISO 4217 format) and the time when the conversion rate was last updated.

View example

GET https://{store}.myshopify.com/admin/currencies.json

{
  "currency_settings": [
    {
      "currency": "AUD",
      "rate_updated_at":  "2018-10-10T02:12:22-12:00"
    },
    {
      "currency": "EUR",
      "rate_updated_at": "2018-10-10T02:12:22-12:00"
    },
    ...
  ]
}

Shopify checks the conversion rates every 15 minutes, and rates typically change only a few times a day. Your app can poll the currencies endpoint in 15-minute intervals, and refetch any prices for a currency if its rate has changed.

Testing the multi-currency feature

You can test the multi-currency feature using any development store that you've created from your Partner Dashboard. The feature is available only in a development environment, and it can't be transferred to a store that's on a paid plan.

To test the feature, you need to set up a payment provider in your development store. If you're eligible to set up Shopify Payments and you have a bank account that you can connect to it, then you can use Shopify Payments in test mode to create test orders. Otherwise, you can use Shopify's Bogus Gateway.

Steps:

  1. Log in to a development store, or create a new one.
  2. Set up Shopify Payments or the Bogus Gateway as a payment provider.

  3. In the payment provider settings, enable the currencies that you want to make available on the online store.

  4. If you're using the Product or Product Variant resource, then include the request header 'X-Shopify-Api-Features': 'include-presentment-prices'.

Developing themes that support multiple currencies

Shopify has introduced several tools and resources to help you to develop online store themes that support multiple currencies:

How can I get help?

If you have questions about the multi-currency changes or you have trouble updating your app, then visit the Shopify Community forums to get help from the Shopify community.

Sign up for a Partner account to get started.

Sign up