Data Warehouse Knowledge Base
Breadcrumbs

API Authentication

FEWS NET staff and partners who have access to the FEWS NET Data Warehouse (FDW) can use authentication to retrieve data they have permissions for from the API.

The FDW REST API supports authentication using a range of methods, including token and session authentication.

  • For programmatic access: Token authentication is recommended. Token authentication involves sending a POST request with your username and password to the /api-token-auth/ endpoint. Once your credentials are validated, the server gives a response such as {"token": "abcdefgh..."}. This response is stored and can be presented in subsequent requests by including an HTTP header in the form Authorization: JWT <token> . The token expiration time is 12 hours. 

    • If you are using applications such as Excel where you cannot set a custom header, include a query parameter in the URL instead, such as ?jwt=<token>.  Including the token in the URL is not recommended for general use due to possible security risks, such as the potential to share a link that contains your token. 

  • When using a browser: After logging in to FDW, your browser will send a session cookie automatically to authenticate requests to the API. 

The data returned from a URL is determined based on the logged in user, meaning the same URL can return different data for different users.

If you do not authenticate or lack permission to the data in FDW:

  • You may receive the error “no data found” when you query data that has restricted permissions.

  • Not all expected data may be included in the response.

Example authentication code

The examples below focus on token authentication in Google Apps Script, R, and Python.

Google Apps Script token authentication

JavaScript
function getFEWSData() {
  // Request an access jwt token from the auth server
  let tokenUrl = 'https://fdw.fews.net/api-token-auth/'
  
  // Populate the form data ready for the POST request.
  let formData = {
    'username' : '<FDW_USERNAME>',
    'password' : '<PASSWORD>'
    };
  
  // These options tell the Fetch App that we want to make a POST rather than a GET request and specifies the form data
  let options = {
    'method' : 'post',
    'payload' : formData
  };

  // Request and parse the token
  let tokenResp = UrlFetchApp.fetch(tokenUrl, options);
  let token = JSON.parse(tokenResp)["token"];
  
  // The jwt token can be added to the URL as a query parameter as &jwt=. This then handles all of the required authorization for the request.
  let url = 'https://fdw.fews.net/api/marketpricefacts/?format=json&country_code=ML&fields=simple&jwt=' + token;

  let response = UrlFetchApp.fetch(url);
  let json = response.getContentText();
  let data = JSON.parse(json);
  }) 
}

R token authentication

R
library(magrittr)
library(httr2)

# For a POST request the authentication must be passed as form data
resp <- request("https://fdw.fews.net/api-token-auth/") %>%
  req_method(method ="POST") %>%
  req_body_json(list(username = "FDW_USERNAME", password = "PASSWORD")) %>%
  req_error(is_error =function(resp) FALSE) %>%
  req_perform()
json_resp <- resp %>% resp_body_json()
token <- json_resp$token
url_with_token = paste("https://fdw.fews.net/api/marketpricefacts/?format=csv&cpcv2=R0112&country_code=KE&fields=simple&jwt=", token, sep="")
request(url_with_token) %>%
  req_method(method ="GET") %>%
  req_error(is_error =function(resp) FALSE) %>%
  req_perform() %>% 
  resp_body_json()
View(json_resp)

Python token authentication

Python
import requests

# Get an access token using a username and password
credentials = {"username": "FDW_USERNAME", "password": "PASSWORD"}
response = requests.post("https://fdw.fews.net/api-token-auth/", data=credentials)
response.raise_for_status()
token = response.json()["token"]

# Set the authorization header to send with every request
headers =  {"Authorization": "JWT " + token}

# Make further requests using the authorization header
response = requests.get("https://fdw.fews.net/api/marketpricefacts/?format=json&dataseries=673", headers=headers)
response.raise_for_status()
response.json()