Class to use to make authenticated API requests for Hakai data. Credentials can be provided via the HAKAI_API_TOKEN environment variable or through a credentials file.
Methods
Client$new()
Log into Google to gain credential access to the API
Usage
Client$new(
api_root = "https://portal.hakai.org/api",
login_page = NULL,
credentials_file = NULL
)Arguments
api_rootOptional API base url to fetch data. Defaults to "https://portal.hakai.org/api"
login_pageOptional API login page url to display to user. When NULL (the default) it is derived from the api_root host, so a custom api_root authenticates against the matching server.
credentials_fileOptional path to the credentials cache file. Defaults to a file in the user's data directory as determined by tools::R_user_dir()
Details
Credentials can be provided in two ways: 1. Via the HAKAI_API_TOKEN environment variable (contains query string: "token_type=Bearer&access_token=...") 2. Via a credentials file (default: in user data directory via tools::R_user_dir()) The environment variable takes precedence if both are available.
Client$get()
Send a GET request to the API
Client$get_stations()
Get recent sensor nodes and their locations as an sf object
Arguments
verboseWhen TRUE, print the request and response details (including the resolved url) to aid debugging
Examples
try(client$get_stations())Client$post()
Send a POST request to the API
Arguments
endpoint_urlThe API endpoint url - can be a full URL or a relative path that will be appended to the api_root
rec_datadataframe, list, or other R data structure to send as part of the post request payload
verboseWhen TRUE, print the request and response details (including the resolved url) to aid debugging
Client$put()
Send a PUT request to the API
Arguments
endpoint_urlThe API endpoint url - can be a full URL or a relative path that will be appended to the api_root
rec_datadataframe, list, or other R data structure to send as part of the post request payload
verboseWhen TRUE, print the request and response details (including the resolved url) to aid debugging
Client$patch()
Send a PATCH request to the API
Arguments
endpoint_urlThe API endpoint url - can be a full URL or a relative path that will be appended to the api_root
rec_datadataframe, list, or other R data structure to send as part of the post request payload
verboseWhen TRUE, print the request and response details (including the resolved url) to aid debugging
Client$remove_credentials()
Remove your cached login credentials to logout of the client
Examples
try(
client$remove_credentials()
)Examples
if (FALSE) { # \dontrun{
# Initialize a new client
try(
client <- Client$new()
)
# Or use environment variable for token
Sys.setenv(HAKAI_API_TOKEN = "token_type=Bearer&access_token=TOKEN")
try(
client <- Client$new()
)
# Follow authorization prompts to log in
# Retrieve some data. See <https://hakaiinstitute.github.io/hakai-api/> for options.
try(
projects_2020 <- client$get("/aco/views/projects?project_year=2020&fields=project_name")
)
try(
print(projects_2020)
)
# # A tibble: 20 x 1
# project_name
# <chr>
# 1 Fountain FN
# 2 Haig Glacier
# 3 Fraser River - Chimney Creek West William Canyon
# 4 Cruickshank WS
# ...
} # }
## ------------------------------------------------
## Method `Client$new()`
## ------------------------------------------------
try(
client <- Client$new()
)
#> /home/runner/.local/share/R/hakaiApi/.hakai-api-auth-r
#> Please go here and authorize:
#> https://portal.hakai.org/api-client-login
#>
#> Copy and paste the full credential string from the login page:
#>
#> Invalid credential format, try again.
# Using environment variable
Sys.setenv(HAKAI_API_TOKEN = "token_type=Bearer&access_token=TOKEN")
try(
client <- Client$new()
)
#> Error in if (are_credentials_expired(credentials)) { :
#> argument is of length zero
# Using custom credentials file
try(
client <- Client$new(credentials_file = "/path/to/creds")
)
#> Error in if (are_credentials_expired(credentials)) { :
#> argument is of length zero
## ------------------------------------------------
## Method `Client$get()`
## ------------------------------------------------
try(client$get("/aco/views/projects"))
#> Error in httr2::req_perform(base_request(resolved_url, token), verbosity = private$verbosity(verbose)) :
#> HTTP 401 Unauthorized.
try(client$get("https://portal.hakai.org/api/aco/views/projects"))
#> Error in httr2::req_perform(base_request(resolved_url, token), verbosity = private$verbosity(verbose)) :
#> HTTP 401 Unauthorized.
try(client$get("/aco/views/projects", verbose = TRUE))
#> -> GET /api/aco/views/projects HTTP/2
#> -> Host: portal.hakai.org
#> -> User-Agent: hakai-api-client-r
#> -> Accept: */*
#> -> Accept-Encoding: deflate, gzip, br, zstd
#> -> Authorization: <REDACTED>
#> ->
#> <- HTTP/2 401
#> <- server: nginx
#> <- date: Wed, 14 Oct 2026 21:09:03 GMT
#> <- content-type: application/json; charset=utf-8
#> <- vary: Origin, Accept-Encoding
#> <- content-encoding: br
#> <-
#> << {"message":"Authorization header not set","name":"UnauthorizedError","stack":"UnauthorizedError: Authorization header not set\n at Object.throw (/app/node_modules/koa/lib/context.js:96:11)\n at /app/src/middlewares/auth.js:44:32\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at /app/node_modules/koa-router/lib/router.js:372:16\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at allowedMethods (/app/node_modules/koa-router/lib/router.js:433:12)\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at /app/node_modules/koa-router/lib/router.js:372:16\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at allowedMethods (/app/node_modules/koa-router/lib/router.js:433:12)\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at /app/node_modules/koa-router/lib/router.js:372:16\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at allowedMethods (/app/node_modules/koa-router/lib/router.js:433:12)\n at dispatch (/app/node_modules/koa-compose/index.js:42:32)\n at /app/node_modules/koa-router/lib/router.js:372:16","status":401}
#> Error in httr2::req_perform(base_request(resolved_url, token), verbosity = private$verbosity(verbose)) :
#> HTTP 401 Unauthorized.
## ------------------------------------------------
## Method `Client$get_stations()`
## ------------------------------------------------
try(client$get_stations())
#> Simple feature collection with 25 features and 2 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: -128.1432 ymin: 50.116 xmax: -124.8554 ymax: 51.77083
#> Geodetic CRS: WGS 84
#> # A tibble: 25 × 3
#> station_id sensor_node geometry
#> <chr> <chr> <POINT [°]>
#> 1 Buxton Buxton (-128.0178 51.60491)
#> 2 Calvert Reference Station RefStn (-128.1287 51.65195)
#> 3 East Buxton BuxtonEast (-127.9752 51.58994)
#> 4 Ethel Ethel (-127.5317 51.54844)
#> 5 Hecate Hecate (-128.0228 51.68257)
#> 6 KCBuoy KCBuoy (-127.9663 51.6499)
#> 7 Koeye Koeye (-127.8794 51.77083)
#> 8 Lookout Lookout (-128.1432 51.6475)
#> 9 Orford Buoy OrfordBuoy (-124.9018 50.59661)
#> 10 Orford Camp OrfordCamp (-124.8554 50.59206)
#> # ℹ 15 more rows
## ------------------------------------------------
## Method `Client$remove_credentials()`
## ------------------------------------------------
try(
client$remove_credentials()
)
#> [1] TRUE