Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing API Access Key #45

Open
cosmosByCarlSagan opened this issue Sep 28, 2023 · 13 comments
Open

Missing API Access Key #45

cosmosByCarlSagan opened this issue Sep 28, 2023 · 13 comments

Comments

@cosmosByCarlSagan
Copy link

cosmosByCarlSagan commented Sep 28, 2023

Looks like the API of https://exchangerate.host/ now requires an API Access Key. If you try to access
https://api./timeseries?start_date=2010-01-01&end_date=2010-12-31&base=AUD&symbols=USD
you will get the following response:
{ "success": false, "error": { "code": 101, "type": "missing_access_key", "info": "You have not supplied an API Access Key. [Required format: access_key=YOUR_ACCESS_KEY]" } }

This results in the following R error when you run historical_exchange_rates() function:
historical_exchange_rates(from = "AUD", to = "USD", start_date = "2010-01-01", end_date = "2020-06-30")

Error in pmap():
i In index: 1.
Caused by error in stack.default():
! at least one vector element is required
Run rlang::last_error() to see where the error occurred.

The pricing page says that it allows only 1K free requests a month. Do you think that this API can be replaced with another free one, so the priceR package can still be used?

@stevecondylios
Copy link
Owner

Thanks for letting me know.

Looks like there's been a major change to the exchangerate.host API (the API priceR uses to get exchange rates). It now requires a key, which is free for 1000 requests per calendar month. (I'm making some guesses here based on the dates on the dashboard):

image

In the short term, I'm investigating the the extent of the damage. I hope it's possible to set the key in the R session and make everything work without any further code changes, but to see if that can be done I will first examine each endpoint (to ensure they still exist). If it's straight forward, will hopefully have changes pushed to github in a few hours.

In the long term, it would be worthwhile investigating free and unrestricted alternatives. At the time I wrote priceR's original forex functionality, it was somewhat opportunistic, since exchangerate.host was the only free and unrestricted API I knew (all other major exchange rate APIs required keys and some required payment details), so it's been great while it lasted.

I'll keep everyone updated here whatever the outcome.

@roberto-formulatrix
Copy link

roberto-formulatrix commented Sep 28, 2023

Yes, I was able to follow the code all the way to here
https://api.exchangerate.host/timeseries?start_date=2010-01-01&end_date=2010-12-31&base=USD&symbols=GBP
and you end up with this response.
{
"success": false,
"error": {
"code": 101,
"type": "missing_access_key",
"info": "You have not supplied an API Access Key. [Required format: access_key=YOUR_ACCESS_KEY]"
}
}

Technically it's an easy fix, but it sounds like a code change will be needed no matter what :(

You can't blame them for trying to monetize here. I'm a low volume user (under 100 times a month) so would be happy to just pass that info myself!

Having said that - I tried to get an api_key but ended up with this... seems like they're working out stuff on their side:

curl "https://api.exchangerate.host/timeseries?start_date=2010-01-01&end_date=2010-12-31&base=USD&symbols=GBP&access_key=84c66myprivatekey"
{"success":false,"error":{"code":103,"type":"invalid_api_function","info":"This API Function does not exist."}}

@stevecondylios
Copy link
Owner

Having read the new API documentation it looks like most of current priceR functionality will be possible with the new API, but since the endpoints, their responses and some of their parameters have changed, it will take some time to integrate these into the priceR library and ensure they produce comparable outputs to the previous API. Unfortunately it's not as simple as setting a key in the R session and inserting the key in the request URLs. Instead, priceR will need to refactored to parse the differently formatted API responses.

From a scan of the new API, it does appear some endpoints now require a paid plan to retrieve rates with a particular base currency (other than USD), if that's the case priceR should still be able to get rates for all other currencies, but may require cross rate triangulation, which will be a bit more work.

In summary unfortunately these API changes are sudden and it will take some time to work out how to get all the previous priceR functionality back using the new API and ensure it is tested and works correctly.

For now, some endpoints that may help - replace abcd1234 in the URLs below with your access key, and note the URLs use http (as opposed to https):

Live rates: http://api.exchangerate.host/live?access_key=abcd1234

Historical rates. Example from jan to may 2015. This endpoint looks powerful as it gives every currency pairing with USD, making it possible to triangulate exchange rates for all ~160 currencies for up to 365 days with a single API call (again, replace abcd1234 with your key):

http://api.exchangerate.host/timeframe?start_date=2015-01-01&end_date=2015-05-01&access_key=abcd1234

Or from R:

library(jsonlite)
fromJSON("http://api.exchangerate.host/timeframe?start_date=2015-01-01&end_date=2015-05-01&access_key=abcd1234")

There are a more endpoints to explore in the 'Available Endpoints' section of the API docs.

Sorry this isn't a more immediate fix. Hopefully we can get most/all of priceR's forex functionality back in time.

@roberto-formulatrix
Copy link

roberto-formulatrix commented Sep 28, 2023

Thanks for looking into that... keep us posted as you fix this.

@stevecondylios
Copy link
Owner

Having a closer look into the new exchangerate.host API, it appears there are even more changes than first thought.

For example, suppose we get the USD/AUD exchange rate for June 2010

library(jsonlite)
library(tidyverse)

df <- fromJSON("http://api.exchangerate.host/timeframe?start_date=2010-06-01&end_date=2010-06-30&currencies=AUD,USD&access_key=9f7337ae140cc2ad5704fb042125fe29")

(replace access_key=9f7337ae140cc2ad5704fb042125fe29 with yours if mine runs out)

and look at the first 6 days' data:

df[[8]] %>% head
# df[[8]] %>% head
# $`2010-06-01`
# $`2010-06-01`$USDAUD
# [1] 1.197421
# 
# 
# $`2010-06-02`
# $`2010-06-02`$USDAUD
# [1] 1.19466
# 
# 
# $`2010-06-03`
# $`2010-06-03`$USDAUD
# [1] 1.184667
# 
# 
# $`2010-06-04`
# $`2010-06-04`$USDAUD
# [1] 1.204761
# 
# 
# $`2010-06-05`
# list()
# 
# $`2010-06-06`
# list()

The first 4 days' exchange rates are provided, but the last two days don't have values. Presumably it's giving data for weekdays but not weekends. Since the previous API gave daily results (including weekends), missing weekends would fundamentally change the way the historical_exchange_rates() function works (since when using that function, one could expect weekends to be included).

Maybe exchangerate.host API will change in the future and include weekends, but my thinking for the time being is to create a few function that has NA for missing days (e.g. weekends).

@JasonSoesman
Copy link

Hi Steve,

Thanks for all your work!
What a same, all these changes from their side. Got some processes running with PriceR that make my life a whole lot easier.
About those missing weekends, isn't it an idea to take the Friday rate for weekend days for instance?
But I'm a noob when it come down to this stuff... I guess I should code myself that when I receive an NA I should take the rate from the first day available.

@stevecondylios
Copy link
Owner

stevecondylios commented Sep 29, 2023

I've written some new, experimental functionality that can be used with the new exchangerate.host API.

So far, only the historical_exchnage_rates() function has been updated.

This code is untested, Please be on the lookout for any:

  • bugs or anomalies
  • possible miscalculations
    • Due to way the new API works returns currency values, it's necessary to calculate rates in 3 different ways, depending on whether
      1. the 'from' currency is USD
      2. the 'to' currency is 'USD
      3. neither currency is USD

There is a known problem with missing date (looks like it's on weekends) for some currencies and date ranges. As far as I've seen so far it affects only data from about 10+ years ago.

To use this experimental functionality:

  • install with remotes::install_github("stevecondylios/priceR@de72f799498b905813760a30bc545082eb1d8135")
  • Set your API key in the R session like so Sys.setenv("EXCHANGERATEHOST_ACCESS_KEY"="7e5e3140140bd8e4f4650cc41fc772c0")
  • historical_exchnage_rates() should work as before

@stevecondylios
Copy link
Owner

This experimental functionality is now on CRAN, and everything should work as it did prior to changes, just requiring that a key be set in the R session first.

Install priceR from CRAN

install.packages("priceR")

library(tidyverse) 
library(priceR)

# use sessionInfo() to ensure version 1.0.0 installed, if not, try this instead
# devtools::install_version("priceR", version="1.0.0", repos="https://cloud.r-project.org/")

Set API key

Make an API key here: https://exchangerate.host/

Paste it into this code and run once to set it in your R session:

Sys.setenv("EXCHANGERATEHOST_ACCESS_KEY"="your_key_goes_here")

Everything should 'just work' ™️

Examples (same as before):

exchange_rate_latest("USD") %>% 
  head(10)
#    currency one_USD_is_equivalent_to
# 1       AED                  3.67299
# 2       AFN                 77.50220
# 3       ALL                101.25030
# 4       AMD                413.44991
# 5       ANG                  1.80265
# 6       AOA                829.00004
# 7       ARS                350.01992
# 8       AUD                  1.58582
# 9       AWG                  1.80000
# 10      AZN                  1.70231

historical_exchange_rates("AUD", to = "USD",
                          start_date = "2013-01-01", end_date = "2023-06-30") %>% head

#         date one_AUD_equivalent_to_x_USD
# 1 2013-01-01                    1.037464
# 2 2013-01-02                    1.049972
# 3 2013-01-03                    1.047220
# 4 2013-01-04                    1.048371
# 5 2013-01-05                    1.048371
# 6 2013-01-06                    1.049155

@cosmosByCarlSagan
Copy link
Author

Well, it "just works". Thanks for your work!

@JasonSoesman
Copy link

Hi Steve,

Thanks for your work again.
Does the historical_exchange_rates for other that USD and in combination with Time-Frame Queries in combination with the free subscription?
I've rebuild everything on my and a started to log all the historical rates in a data frame, but ran into the problem I need the professional plus subscription from them.

@stevecondylios
Copy link
Owner

@JasonSoesman it will work with the free subscription. Example:

library(priceR)
library(tidyverse)
historical_exchange_rates("AUD", to = "EUR",
                          start_date = "2022-01-01", end_date = "2023-06-30") %>% head

#         date one_AUD_equivalent_to_x_EUR
# 1 2022-01-01                   0.6391881
# 2 2022-01-02                   0.6389321
# 3 2022-01-03                   0.6368972
# 4 2022-01-04                   0.6416999
# 5 2022-01-05                   0.6383105
# 6 2022-01-06                   0.6341034

It's able to do this by using currency cross rates (i.e. computing the rate between currencies A and B based on the USD to A and USD to B rates). The exact logic is here.

@Pasljan
Copy link

Pasljan commented Feb 29, 2024

Dear @stevecondylios , I am a great fan of your package and I was using it quite a while. The big THANK YOU for creating the package.
However recent changes (somewhere mid of Jan 2024) within the https://exchangerate.host/ made my life way more difficult. While they limited to 1k requests (that limit was still quite reasonable considering they wanted to monetize their service) they limited it even further. Now it has only 100 requests. Meaning if I check daily for 5 currencies I am 150% over the limit. Moreover you cannot register an account, even for that 100 requests unless you provide your credit card.
So in their eyes, the pricing looks like below 100 per month with credit card is free above 100 - take 10k package...
I did small research which APIs are still there and here are the free limitations:

  1. https://fixer.io/#pricing_plan - 100
  2. https://exchangeratesapi.io/#pricing_plan - 250
  3. https://currencyapi.com/pricing/ 300
  4. https://openexchangerates.org/signup/free 1000 requests per month.
    What do you think, would it make sense if you modify your package to use the last provider? Actually, of retrieving the historical data for quite a longer period of time with the exchangerate.host, it counts it as multiple requests.

@stevecondylios
Copy link
Owner

I agree, 100 requests per month is just too small to be useful (just generating the readme for this repo takes a few dozen requests). FWIW I emailed exchangerate.host to try to change their mind but it hasn't been successful.

Thanks for researching alternatives. I think moving to openexchangerates.org is a good idea. I have used them in several projects before (via a ruby library) and it's been extremely reliable.

To do it properly, I think exchangerates.host would have to be removed and replaced entirely (i.e. across all functions that use it). I don't have the time to commit to this right now, but if someone wants to have a go and make a PR they're welcome to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants