Skip to main content
Prerequisites
  • A ClientId and ClientSecret provided by the Ginkgo Biosecurity team
  • A machine with the R programming language runtime installed

Authenticate and make API requests

# load pacakges
library(utils)
library(stringr)
library(httr)
library(data.table)

# read in config file, parse parameters and return
# example of config file api_client.env
# AUTH0_DOMAIN=sso.ginkgobiosecurity.com
# AUTH0_CLIENT_ID={use credentials provided}
# AUTH0_CLIENT_SECRET={use credentials provided}
# AUTH0_API_AUDIENCE=https://api.ginkgobiosecurity.com
# API_GATEWAY_URL=https://api.ginkgobiosecurity.com

init_config <- function(full_path_to_config_file = NULL)
{
	if(is.null(full_path_to_config_file) | is.na(full_path_to_config_file) | full_path_to_config_file == "")
	{
  	stop("Please provide config file path")
	}
	if(!file.exists(full_path_to_config_file))
	{
  	stop("Config file does not exist. Please check file path provided.")
	}
	api_client_params <- as.data.table(read.table(full_path_to_config_file, sep = "=", header = FALSE, stringsAsFactors = FALSE, col.names=c('Key','Value')))
	# retrieve config parameters
	auth0_domain <- str_trim(api_client_params[Key == "AUTH0_DOMAIN", Value])
	auth0_client_id <- str_trim(api_client_params[Key == "AUTH0_CLIENT_ID", Value])
	auth0_client_secret <- str_trim(api_client_params[Key == "AUTH0_CLIENT_SECRET", Value])
	auth0_api_audience <- str_trim(api_client_params[Key == "AUTH0_API_AUDIENCE", Value])
	api_gateway_url <- str_trim(api_client_params[Key == "API_GATEWAY_URL", Value])
	authorization_token <- NULL
    
	config_param_list <- list(auth0_domain = auth0_domain, auth0_client_id = auth0_client_id, auth0_client_secret = auth0_client_secret,
                            	auth0_api_audience = auth0_api_audience, api_gateway_url = api_gateway_url, authorization_token = authorization_token)
	return(config_param_list)
}
# authenticate with auth0 service and retrieve authorization token
# valid authorization token is needed to retrieve resources from the api end point
authenticate  <- function(config_params = NULL)
{

	# Get the authorization token from the Auth0 server by
	# POSTing the clientId and clientSecret to the /oauth/token endpoint
	auth0_domain <- config_params$auth0_domain
	auth0_token_url = paste0("https://", auth0_domain,"/oauth/token")
 	auth0_client_id = config_params$auth0_client_id
  	auth0_client_secret = config_params$auth0_client_secret
  	auth0_api_audience = config_params$auth0_api_audience
	auth_headers = "{
  	'content-type': 'application/json',
	}"
	# POST the submission and retrieve response
	response <- POST(auth0_token_url,
                 	encode="form", add_headers(.headers = auth_headers),
                       	body=list(
                         	grant_type = "client_credentials",
                         	client_id = auth0_client_id,
                         	client_secret = auth0_client_secret,
                         	audience = auth0_api_audience              	 
                       	)
            	)
	if(response$status_code > 400)
	{
  	stop("Error retrieving authorization token from the Auth0 service.")
	}
	authorization_token <- content(response)$access_token
	return(authorization_token)
}

# Use the authorization token to access the secured resource
# example: get a listing of events
# query_params_list is a list with name value pairs of query parameters to provide to the api end point
get_resource <- function(config_params = NULL, access_token = NULL, path = NULL, query_params_list = NULL)
{
	api_gateway_url <- config_params$api_gateway_url
	if(stringr::str_starts(path, "/"))
	{
  	path <- substring(path, 2)
	}
	resource_url <- paste0(api_gateway_url, "/",path)  
	headers = c(
  	`Authorization` = paste0("Bearer ", access_token)
	)
	query <- query_params_list
	# Escaped query
	action_path_encoded <- httr::modify_url(resource_url, query = query)
	res <- GET(url = action_path_encoded, add_headers(.headers = headers), httr::timeout(29), VERBOSE = TRUE)
	result_list <- content(res, encoding = "application/json")
	return(result_list)
 
}
# Use the authorization token to access the secured resource
# example: get a listing of all hed events
get_all_records_v1 <- function(config_params = NULL, access_token = NULL, path = NULL, params = list(), page_size = 100, verbose = TRUE) {
  all_records <- list()
  offset <- 0
  
  allowed_paths <- c("hed-outbreaks/event-names",
                     "hed-outbreaks/events/source-names",
                     "hed-outbreaks/outbreaks",
                     "active-outbreaks/outbreak-summaries")
  
  # Remove version prefix like v1/, v2/, etc.
  stripped <- sub("^v[0-9]+/", "", path)
  
  # Check if stripped path is allowed
  if (!(stripped %in% allowed_paths)) {
    stop(sprintf("Path '%s' is not allowed in this function. The end point does not support pagenation since the entire data set is returned when calling get_resource.", path))
  }
  
  
  repeat {
    # Pagination parameters
    pagination_params <- c(params, list(offset = offset, num = page_size))
    
    # Get current page
    response_data <- get_resource(
      config_params = config_params,
      access_token = access_token,
      path = path,
      query_params_list = pagination_params
    )
    
    if (is.null(response_data)) {
      warning(sprintf("Error retrieving data at offset %d", offset))
      return(NULL)
    }
    
    # Check if we got records
    if (length(response_data) == 0) {
      break
    }
    
    # Append records
    all_records <- c(all_records, response_data)
    
    # If fewer records than page_size, we are done
    if (length(response_data) < page_size) {
      break
    }
    
    # Increment offset
    offset <- offset + page_size
    
    if (verbose) {
      message(sprintf("Retrieved %d records at offset %d, total so far: %d",
                      length(response_data), offset - page_size, length(all_records)))
    }
  }
  
  if (verbose) {
    message(sprintf("Total records retrieved: %d", length(all_records)))
  }
  
  return(all_records)
}

# Use the authorization token to access the secured resource
# example: get a listing of all hed events
get_all_records_v2 <- function(config_params = NULL, access_token = NULL, path = NULL, params = list(), page_size = 200, verbose = TRUE) {
  all_records <- list()
  offset <- NULL
  allowed_paths <- c("hed-outbreaks/event-names",
                     "hed-outbreaks/events/source-names",
                     "hed-outbreaks/outbreaks",
                     "active-outbreaks/outbreak-summaries",
 "transit-hub/risk-scores",)
  
  # Remove version prefix like v1/, v2/, etc.
  stripped <- sub("^v[0-9]+/", "", path)
  
  # Check if stripped path is allowed
  if (!(stripped %in% allowed_paths)) {
    stop(sprintf("Path '%s' is not allowed in this function. The end point does not support pagenation since the entire data set is returned when calling get_resource.", path))
  }
  
  
  repeat {
    # Pagination parameters
    pagination_params <- c(params, list(page = offset, num = page_size))
    print(pagination_params)
    # Get current page
    response_data <- get_resource_v2(
      config_params = config_params,
      access_token = access_token,
      path = path,
      query_params_list = pagination_params
    )
    
    if (is.null(response_data)) {
      warning(sprintf("Error retrieving data at offset %d", offset))
      return(NULL)
    }
    
    # Check if we got records
    if (length(response_data$data) == 0) {
      break
    }
    
    # Append records
    all_records <- c(all_records, response_data$data)
    
    if (verbose) {
      message(sprintf("Retrieved %d records with has_more %s, total so far: %d",
                      length(response_data$data), response_data$has_more, length(all_records)))
    }
    
    # If fewer records than page_size, we are done
    if (!response_data$has_more) {
      break
    } else
    {
      offset <- response_data$next_page
    }
  }
  
  if (verbose) {
    message(sprintf("Total records retrieved: %d", length(all_records)))
  }
  
  return(all_records)
}

# sample retrieval flow using the above functions
# step 1: initialize to retrieve config parameters
# step 2: authenticate to retrieve authorization token
# step 3: access the api end point to retrieve 10 outbreak events

# call init_config with path to config file
config_params <- init_config("~/rprojects/scratch/api_client.env")
# retrieve the authentication access token
access_token <- authenticate(config_params = config_params)
# get the relevant resource. in this example we are getting a listing of events
event_list <- get_resource(config_params = config_params, access_token = access_token, path = "v1/events", query_params_list = list(num = 10))

# get all records from select end-points by making repeat get_resource calls
event_list <- get_all_records_v1(config_params = config_params, access_token = access_token, path = "v1/hed-outbreaks/event-names", params = list())  # any additional query parameters

# get all records from select v2 end-points by making repeat get_resource calls
outbreaks <- get_all_records_v2(config_params = config_params, access_token = access_token, path = "v2/hed-outbreaks/outbreaks", params = list(event = "Nipah virus_India_2025"))  # any additional query parameters
# get all records for active outbreaks end point for a specific event.
# events in scope can be first queried from the active outbreaks event names end point 
active_outbreaks <- get_all_records_v2(
  config_params = config_params,
  access_token = access_token,
  path = "v2/active-outbreaks/outbreak-summaries",
  params = list(event = "Zaire ebolavirus_Democratic Republic of the Congo_2025_Kasai")  # any additional query parameters
)
active_outbreaks_ebola_DRC_kasai <- rbindlist(active_outbreaks, fill = TRUE)

# get all records for transit hub for a specific pathogen.
# pathogens in scope can be first queried from the transit hub pathogens end point 
transit_hub <- get_all_records_v2(
  config_params = config_params,
  access_token = access_token,
  path = "v2/transit-hub/risk-scores",
  params = list(pathogen_name = "Zaire ebolavirus")  # any additional query parameters
)
transit_hub_ebola_DRC_kasai <- rbindlist(transit_hub, fill = TRUE)