FatSecret Food Database REST API Client with Typescript

Bartosz Klukaczewski
DLabs.AI
Published in
5 min readAug 21, 2018
Photo by Rachel Park on Unsplash

FatSecret Platform

Have you ever wondered, how to provide your product a rich food and meals database? When we decided to have food search functionality in one of our products, Suguard (diabetes diary app, under development in React Native with Firebase and Typescript), we had to do some research what service would suit our needs best. We needed something that is free for most basic functionalities to validate our product with users. After some research, we realised, that FatSecret might be best choice, if we want to use 100% free service (most basic pricing tier) for now. It might not suit all your needs, but we never claim that is is best service of all. Some facts about FatSecret from their homepage:

The #1 food and nutrition database in the world, utilized by more than 10,000 developers, in more than 50 countries contributing in excess of 500 million API calls every month.

Authentication

To use FatSecret API you need to register as a developer here. The API uses authentication based on OAuth Core 1.0 protocol for securely signing all requests. Although documentation at FatSecret’s page looks rich, it takes some time to go through it. Here’s why this tutorial article comes by. Even though the code below is written in Typescript, it can easily be adjusted to Javascript so don’t worry if Typescript is not your thing. We use async functions which is a ES2017 feature, so it might be worthy to read a bit about them.

Full API documentation can be found at Fatsecret Platform API docs.

What you need before start

As mentioned before, you will need Fatsecret Developer account. You will need it to get Access Token also known as REST API Consumer Key and Access Secret sometimes referred as REST API Shared Secret. From the documentation:

Access Token: A value which identifies a user of your application (you use the REST API Profile Management methods to generate these).

Access Secret: A secret we issue with the Access Token which helps us establish that you can perform a request on behalf of the user identified by the Access Token (you use the REST API Profile Management methods to generate these and/or retrieve these for your users).

Lets create a fatsecret.ts file and define some constants for later use:

Both OATH_VERSION and OAUTH_SIGNATURE_METHOD cannot be changed. We could have it hardcoded in our requests, but having it as const at the top of the file will make the code easier to understand and maintain.

To properly sign a request according to FatSecret documentation, we need to add appropriate HTTP query parameters to it. In this tutorial, we will cover only Signed Requests. As long as you don’t need any data specific to the user (like getting user’s weight history directly from FatSecret), you will not need Delegated Requests. More information about these two kinds of request can be found in the documentation.

Signature Base String

We need to generate Signature Base String by concatenating the HTTP method (GET or POST), the request URL and our query params in the following format:

<HTTP Method>&<Request URL>&<Normalized Parameters>

Request URL is simply API_PATH.

Query Params aka Normalized Parameters

Each method (like foods.search or food.get) in FatSecret REST API has it’s own set of supported params, but all of them share common OAuth parameters. Let’s create a helper function to get all of them.

We use constant values defined before. The only thing that might be unclear here is oauth_nonce which is a randomly generated string for a request that has been created from timestamp and random value.

We need to convert plain Javascript object from getOauthParameters to a query string. For that, we will use popular query-string library.

yarn add query-string
yarn add --dev @types/query-string

Second line will add optional Typescript definitions to the library (it is not included in the lib).

Now, lets prepare function to get request signature.

We concatenate HTTP method, API Path (Request URL) and query params (Normalized Parameters) into single string.

encodeURIComponent allows us to encode strings to be proper URIs, without unsafe characters (like ?=/&). You don’t need it install or import it. It is part of Javascript standard built-in objects, available even in Internet Explorer 5.5.

hmcsha1 function comes from external library, which must be added to package.json:

yarn add hmacsha1

and imported in the source code:

import hmacsha1 from 'hmacsha1';

If you don’t want to add external requirement to your project’s package.json, you can define hmacsha1 function in your source code as a one-liner.

API Call wrapper

We are almost there! All we need now is to call the FatSecret API.

methodParams is a object of method specific query parameters. It will be different set of properties for food search and different for other methods.

After computing the signature, we add oauth_signature to queryParams .

As you can see, we used fetch library to interact with the API. You can use any HTTP client you want (axios for example).

Search method

In this tutorial we will cover only one method, foods.search which seems to be entry point for further development. Other methods are very similar and our code can be reused for them.

query is our search expression. If we want to search for hamburgers, it will be hamburger . This one will probably come from input component. maxResults is a number value, which does not need much explanation.

Fetch returns a Promise so we need to await it’s results. At the end, we return response.json() from our function, which is Promise<FatsecretResponse>, that need to be used in our result displaying component. As you can see, we defined FatsecretResponse interface as result of our function. You can make it return Response<any> , but you will not have type checks, which Typescript provides.

export interface FatsecretFood {
food_id: string;
food_name: string;
food_type: FatsecretFoodType;
food_url: string;
brand_name?: string;
food_description: string;
}
export enum FatsecretFoodType {
Brand = 'Brand',
Generic = 'Generic',
}
export interface FatsecretResponse {
foods: {
food: FatsecretFood[];
max_results: number;
total_results: number;
page_number: number;
};
}

Full example

That’s it! You can execute API calls to FatSecret. In case you missed something, here’s a full example with extra method to get single food data (by food ID).

--

--

Bartosz Klukaczewski
DLabs.AI
Writer for

React Native / Frontend Developer with Python background. Interested in UX, fitness and architecture.