Integrate the Currency Exchange API
Last updated: Feb 26th, 12:06pm
Set up your Orders API integration to present local currencies to your buyer
Know before you code
- You must be an approved merchant with an FX as a Service contract to use this integration. The contract includes when the FX as a Service rate expires, the rate refresh time, and other important details regarding PayPal FX fees. Contact your account manager to set up this feature on your account.
- Your account must be authorized to interact with the FX as a Service. Contact your account manager to verify you have this scope set on your account.
- Set up your development environment and get your client ID using the information in Get Started. You will use the client ID in the integration process to authenticate your API calls. You'll also need your REST API credentials, which are available in the Developer Dashboard.
- This integration uses the Orders V2 API and the Currency Exchange API.
- You must have the integration set up for both sandbox and live business accounts.
1. Get the exchange rate quote
Use the Quote exchange rates endpoint to get a quote for the exchange rate to present prices in the buyer’s local currency. This rate is honored during payment processing.
Note: The expiration interval for an exchange rate is in the contract. PayPal will not honor the contracted exchange rate if the rate guarantee period has expired before the payment transaction is captured. In this instance, PayPal converts the transaction amount to the merchant's base currency using the prevailing exchange rate.
Sample quote API with mandatory parameters
This code sample passes the currency code of your base currency and quote currency in the request.
- Request
- Response
1curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/pricing/quote-exchange-rates' \2-H 'Content-Type: application/json' \3-H 'Authorization: Bearer ACCESS-TOKEN' \4-d '{5 "quote_items": [6 {7 "base_currency": "USD",8 "quote_currency": "GBP",9 }10 ]11 }'
Sample quote API with optional parameters
- Request
- Response
1curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/pricing/quote-exchange-rates' \2-H 'Content-Type: application/json' \3-H 'Authorization: Bearer ACCESS-TOKEN' \4-d '{5 "quote_items": [6 {7 "base_currency": "USD",8 "quote_currency": "GBP",9 "base_amount": 16.80,10 "markup_percent": 1,11 }12 ]13 }'
Parameters
Parameter | Type | String |
---|---|---|
base_amount | Object | Pass this parameter in the API request to know the specific price of a product in quote currency rather than using the FX conversion rate for product price from the stored conversion rate. |
markup_percent | String | Pass this parameter in the API request to add the markup percentage. The percentage will be added to the given rates in the API response. |
expiry_time | String | The exchange rates after obtaining are valid for settlement only till rate_refresh_time . expiry_time provides the ability to set an extra grace period for rate guarantee even after rate refresh time. This is applicable only if the merchant passes the payee_receivable_fx_rate_id parameter in the order V2 API. If the merchant does not pass the payee_receivable_fx_rate_id parameter or for any non-order V2 integration after rate refresh time, new rates will be applied. Time difference duration between rate refresh time and expiry time (cut-off period) is offered at 3 hours as a standard feature. If merchants want anything different, it will be reviewed on case-by-case basis. |
rate_refresh_time | String | The time at which refreshed exchange rates are available. This time is not dependent on the transaction time, but is at an agreed upon fixed time every day (for example, at 17:00:00 hours) that rates are updated. The time of rate refresh and rate refresh period will be decided during the contract. The API response follows the UTC time zone. |
Step result
A successful request returns the following:
- A return status code of
HTTP 201 Created
. - A JSON response body that contains the
fx_id
. You'll use thefx_id
in your Orders V2 APIcreate_order
call.
Sample create order
- Request
- Response
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders \2-H "Content-Type: application/json" \3-H "Authorization: Bearer ACCESS-TOKEN" \4-d '{5 "intent": "CAPTURE",6 "purchase_units": [7 {8 "amount": {9 "currency_code": "GBP",10 "value": "13.60"11 }12 "payment_instruction": {13 "payee_receivable_fx_rate_id": "MTFFQy05RjBFLTEyOTlDQTgwLTg3MzMtMzk0ODIwRUEwMTc4"14 }15 }16 ]17}'
The create order API response returns the provided payee_receivable_fx_rate_id
in the create order request. If payee_receivable_fx_rate_id
is not passed in the request for any presentment currency, it will always be converted to primary currency of the merchant account.
Sample capture order
- Request
- Response
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T/capture \2-H "Content-Type: application/json" -H "Authorization: Bearer ACCESS-TOKEN" \3-H "PayPal-Request-Id: 7b92603e-77ed-4896-8e78-5dea2050476a"
In the capture API response, the seller_receivable_breakdown
section specifies that the merchant will receive:
- The amount in base currency
- The currency conversion rate which is used to convert the receivable amount from quote currency to base currency
Note: The PayPal transaction fee will be charged in the transaction currency.
If any transactions are completed but not passed by the payee_receivable_fx_rate_id
parameter during the window between rate_refresh_time
and expiry_time
, the refreshed rates will be applied to the conversion by default.
Special case: market-moving event (Force Majeure)
In case of market-moving events, such as natural disasters or political unrest, exchange rates in wholesale currency markets may be extremely volatile and FX as a Service’s rate lock guarantee can no longer be honored.
In response to such events, PayPal will update FX as a Service exchange rates and generate a new FXID outside of the typical rate refresh cycle.
There are 2 different scenarios when an Orders API call happens during a Force Majeure event:
When a Force Majeure event takes place after a quote is generated with FXID, and before the subsequent Orders API call, the latter will respond with
422 UNPROCESSABLE ENTITY
and the error response will include thenew_fx_id
link to use.After the Orders API returns the first error message, any subsequent calls to the Orders API using the previous
fx_id
return200 OK
with thenew_fx_id
aspayee_receivable_fx_rate_id
.
Note: Use this new_fx_id
to refresh prices presented in buyers' local currencies and for subsequent transaction processing until the next time exchange rates are refreshed.
Sample create order during Force Majeure event
- Response
- Request
1{2 "name": "UNPROCESSABLE_ENTITY",3 "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",4 "debug_id": "8872d95df4110",5 "details": [6 {7 "field": "payment_instruction/payee_receivable_fx_rate_id",8 "location": "body",9 "issue": "FX_RATE_CHANGE_DUE_TO_MARKET_EVENT",10 "links": [11 {12 "href": "https://api-m.sandbox.paypal.com/v2/pricing/quote-exchange-rates/MTFFRS1EMDVBLTJDNzFCRUYyLTkzN0MtNDQzQzZDRjY4QjUy",13 "method": "GET",14 "rel": "new_fx_id",15 "encType": "application/json"16 }17 ],18 "description": "The FX rate associated with the specified FX rate ID has been changed due to market events. Please refer to the provided new_fx_id link to retrieve a new FX rate ID and try the request again."19 }20 ],21 "links": [22 {23 "href": "https://developer.paypal.com/docs/api/payments/v2/#error-FX_RATE_CHANGE_DUE_TO_MARKET_EVENT",24 "rel": "information_link",25 "encType": "application/json"26 }27 ]28}
Note: This integration uses the Orders V2 API.
2. Test and go live
Complete end-to-end testing in sandbox to make sure the integration functions as you expect. You can then go live with your integration.