NutritionQuest FFQ API

Introduction

The FFQ API is a web API that enables the creation and management of users and sessions, the analysis of session answers, retrieval of results, and importing and exporting batch sessions and results.

Protocol

You can access the FFQ API via standard "REST" style HTTP protocols. Authentication requires an API key that is assigned to your group, sent as an "Authorization" header. Your API key determines the group.

Authentication Header: Use Authorization header (not X-API-Key). The header name is case-insensitive.

Authentication Levels

Access Level Authentication Capabilities
Standard API Access API Key only Create/read/update users and sessions, analyze data, export results
NutritionQuest Admin Access API Key + Admin Password All standard functions plus delete users/sessions and reset group
Demo Mode API Key (demo group) All NutritionQuest admin functions available (delete/reset enabled)
Important: Delete operations (users, sessions) and group reset are restricted to NutritionQuest admin access only. Standard API keys cannot perform destructive operations for data safety.

Structure

The group is associated with one questionnaire, and has zero or more users. Each user has zero or more sessions, which include their answers and the various types of analysis results. Sessions contain various bulk data like JSON answers, JSON results, CSV file spreadsheets, HTML pages, etc, which can be read and optionally written by corresponding API calls.

Session Management Model

  • Allowable Sessions: Each user has a maximum number of sessions they're permitted to create
  • Default Limit: When a user is created, they're assigned the group's default per-user limit
  • Actual Sessions: Created when questionnaire data is submitted
API Structure: Group → Users → Sessions → (Answers, Results, Analysis)

Features

User Management

Create and delete users individually with customizable passwords and session limits

Session Control

Create, delete, analyze, update, and query sessions individually

Template System

Apply HTML templates to partial or full results for interstitial feedback

Batch Operations

Bulk import users and answers, batch export results by ID or session cookies

Configuration

Setting Value
Base Server URL https://www.nutritionquest.com
Authentication NutritionQuest will assign you one or more FFQ API keys for each questionnaire you want to use. Send in Authorization header.

Data Types

Basic Types

Type Description
authorization secret A secret string FFQ API key sent in the HTTP Authorization header, used to authenticate and select the group to operate on. Each group will be assigned its own unique API key by NutritionQuest. If the group is in "demo" mode, all requests have NutritionQuest admin access to delete users and sessions and reset the group.
user cookie A long hex string used in API paths to identify an existing user.
session cookie A long hex string identifying a session. This is what the API uses to identify sessions.
completion date A date string in the format "MMDDYYYY" if a session is complete, or "" if not complete
session timestamp A time and date string in the format "YYYY-MM-DD HH:MM:SS" or "" if undefined

File Types

Type Description
CSV file A text comma separated values spreadsheet file of analysis data, the first row of which contains headers with names for the columns
HTML file A text HTML file with human readable analysis results
ZIP file A binary compressed archive containing other types of files
JSON file A file in JavaScript Object Notation containing JSON objects, JSON arrays, etc

Key JSON Objects

JSON confirmation object

{
    "success": boolean,  // success flag
    "message": string    // error or success message
}

JSON group object

{
    "success": boolean,
    "ffq_name": string,           // name of the group's FFQ
    "title": string,              // title of the group
    "user_count": number,         // number of users in the group
    "session_count": number,      // number of sessions in the group
    "nutrients_per_food": boolean // true if analysis results include nutrients-per-food tables
}

JSON user object

{
    "success": boolean,
    "user_id": string,     // User ID in the group's admin interface, represents the user's unique Respondent ID number
    "user_cookie": string, // User Cookie (unique identifier for API lookups)
    "user_screen_name": string,  // User Screen Name in the group's admin interface, the name that a user logs in with
    "sessions_per_user": number,  // Maximum number of sessions this user is permitted to create
    "session_count_total": number,
    "session_count_complete": number,
    "session_count_incomplete": number,
    "sessions": [
        {
            "session_cookie": string,  // Session Cookie (unique identifier for API lookups)
            "complete": boolean,
            "start": string,     // Date in "YYYY-MM-DD" format
            "finish": string     // Date in "YYYY-MM-DD" format or null
        }
    ]
}
Note on sessions_per_user: This field represents the maximum number of FFQ sessions this user is allowed to create. It defaults to the group's per-user limit when the user is created, but can be adjusted via the API (up to the group's maximum).

JSON user initialization object

{
    "user_id": string,                  // Required: User's unique Respondent ID number (must be unique in group)
    "user_screen_name": string,         // Optional: User Screen Name (the name that a user logs in with), defaults to user_id
    "user_password": string             // Optional: User's password, generates random if not provided
}
Note: The sessions_per_user field cannot be set during user creation. Users are automatically assigned the group's default per-user session limit.

JSON user update object

{
    "user_name": string,                // Optional: New user ID (must be unique in group)
    "user_screen_name": string,         // Optional: New user screen name (the name that a user logs in with)
    "user_password": string,            // Optional: New user password
    "sessions_per_user": number         // Optional: Number of sessions permitted (cannot exceed group's per-user default)
}

JSON session object

{
    "session_cookie": string,  // Session Cookie (unique identifier for API lookups)
    "complete": boolean,       // session complete flag
    "start": string,          // session timestamp start time
    "finish": string          // session timestamp finish time
}

JSON session initialization object

{
    "app_values": {},    // JSON application values object (questionnaire screen progress tracking)
    "answers": {},       // JSON answers object (the user's answers to the FFQ)
    "environment": {}    // JSON environment object (browser information)
}

JSON answers object

{
    // An object representing the user's answers to an FFQ
    // Structure varies by questionnaire
    // Example:
    "answer_1": "1",
    "answer_2": "2", 
    "answer_3": "3"
}

JSON application values object

{
    // An object containing the number of the questionnaire screen the user was last on
    // Used to track user progress through the questionnaire
    // Example:
    "screen": 15
}

JSON environment object

{
    // An object containing information about the browser the user was using
    // Example:
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "browser": "Chrome",
    "platform": "Windows"
}

JSON results object

{
    // An object representing the analysis results
    // Contains nutritional analysis, calculations, and derived values
    // Structure includes fields like:
    "STATIC_ROOT": "https://www.nutritionquest.com",
    "RESPONDENTID": "user_id",
    "FINISHED": boolean,
    "TODAYSDATE": "MMDDYYYY",
    // ... plus many nutrition-specific fields
}

JSON batch import description object

{
    "complete_flag": boolean,    // true if session complete
    "date_completed": string,    // completion date as "MMDDYYYY" if complete, or "" if not
    "user_id": string,           // User's unique Respondent ID number
    "answers": {}                // JSON answers object
}

JSON batch import confirmation object

{
    "successes": [],        // JSON array of success message strings
    "warnings": [],         // JSON array of warning message strings
    "errors": [],           // JSON array of error message strings
    "batch_number": number, // batch number of import, used to export results
    "session_cookies": [],  // JSON array of session cookies processed
    "records": []          // JSON array of JSON batch import record confirmation objects
}

JSON batch import record confirmation object

{
    "success": boolean,
    "user_id": string,           // User's unique Respondent ID number
    "user_created": boolean,     // true if user was created, false if already existed
    "ffq_name": string,
    "session_created": boolean,  // true if session was created, false if already existed
    "complete_flag": boolean,
    "date_completed": string,    // completion date as "MMDDYYYY" if complete, or "" if not
    "user_cookie": string,       // user cookie identifying user (internal identifier)
    "session_cookie": string     // session cookie identifying session
}

JSON batch export description object

{
    "batch_number": number,      // batch number to export (optional)
    "session_cookies": []        // array of session cookies to export (optional)
}

JSON batch export confirmation object

{
    "success": boolean,
    "url": string  // url of ZIP file of exports to download
}

API Methods

Group Management

GET /ffqapi/group

Get group as JSON group object

→ See example

User Management

GET /ffqapi/user

Get list of all users in group

→ See example
POST /ffqapi/user

Create new user in group

Requires user_id
Optional password
Automatically assigns group's default session limit
→ See example
GET /ffqapi/user/{user_cookie}

Get user by user cookie

Includes sessions_per_user
PUT /ffqapi/user/{user_cookie}

Update user by user cookie

Can update user ID
Can update screen name
Can update password
Can adjust session limit
→ See example

Session Management

POST /ffqapi/user/{user_cookie}/session

Create a new session for a user

Checks user hasn't exceeded session limit
Checks group hasn't exceeded total sessions
→ See example
GET /ffqapi/user/{user_cookie}/session/{session_cookie}

Get session by user cookie and session cookie

Session Data Management

GET /ffqapi/user/{user_cookie}/session/{session_cookie}/answers

Get answers from session

PUT /ffqapi/user/{user_cookie}/session/{session_cookie}/answers

Update answers in session

→ See example
GET /ffqapi/user/{user_cookie}/session/{session_cookie}/app_values

Get app values from session

PUT /ffqapi/user/{user_cookie}/session/{session_cookie}/app_values

Update app values in session

GET /ffqapi/user/{user_cookie}/session/{session_cookie}/environment

Get environment from session

PUT /ffqapi/user/{user_cookie}/session/{session_cookie}/environment

Update environment in session

Analysis and Results

GET /ffqapi/user/{user_cookie}/session/{session_cookie}/results

Get JSON results from session

Returns nutritional analysis
Partial results before finish, complete after
→ See example
GET /ffqapi/user/{user_cookie}/session/{session_cookie}/results_html

Get HTML results from session

Human-readable report
Only available after session finished
→ See example
GET /ffqapi/user/{user_cookie}/session/{session_cookie}/nutrients

Get nutrients CSV (if enabled)

Only if group's nutrients_per_food is true
Only available after session finished
GET /ffqapi/user/{user_cookie}/session/{session_cookie}/cases

Get cases CSV

Only available after session finished
GET /ffqapi/user/{user_cookie}/session/{session_cookie}/template/{template_id}

Apply template to results

Returns HTML with template applied
POST /ffqapi/user/{user_cookie}/session/{session_cookie}/analyze

Analyze answers without finishing

Partial analysis
POST /ffqapi/user/{user_cookie}/session/{session_cookie}/finish

Analyze answers and finish session

Completes analysis
→ See example

Batch Operations

POST /ffqapi/import

Batch import users and answers

Creates users & sessions
Auto-analyzes data
→ See example
POST /ffqapi/export

Batch export analysis results as ZIP

By batch number or session cookies
→ See example

Examples

Note: In these examples, xyzzy represents your group's authorization key, and USER_COOKIE and SESSION_COOKIE are placeholders for actual user and session cookies (long hex strings). The curl -s parameter operates in quiet mode (not printing unnecessary output). The jq . command pretty-prints JSON output.
Authentication Update: Use Authorization header, not X-API-Key as shown in older documentation.

Create a New User with Password

curl -s \
     -H "Authorization: xyzzy" \
     -H "Content-Type: application/json" \
     -X POST \
     -d '{"user_id":"123_1", "user_screen_name": "John_Doe", "user_password": "mypassword123"}' \
     https://www.nutritionquest.com/ffqapi/user \
| jq .

Response:

{
  "success": true,
  "user_id": "123_1",
  "user_cookie": "1bb43d659f52ca986b2f360c0bb7025d",
  "user_screen_name": "John_Doe",
  "sessions_per_user": 10,  // Automatically set to group's default
  "session_count_total": 0,
  "session_count_complete": 0,
  "session_count_incomplete": 0,
  "sessions": []
}

Get Group Information

curl -s \
     -H "Authorization: xyzzy" \
     -X GET \
     https://www.nutritionquest.com/ffqapi/group \
| jq .

Response:

{
  "success": true,
  "ffq_name": "Block_2014_FFQ",
  "title": "UniversityX_studyNameY",
  "user_count": 0,
  "session_count": 0,
  "nutrients_per_food": false
}

Create a New Session

curl -s \
     -H "Authorization: xyzzy" \
     -H "Content-Type: application/json" \
     -X POST \
     -d '{}' \
     https://www.nutritionquest.com/ffqapi/user/1bb43d659f52ca986b2f360c0bb7025d/session \
| jq .

Response:

{
  "session_cookie": "cbd42f733e4c8f65f8f98c52a4fea5fd",
  "complete": false,
  "start": "2024-03-03 00:00:00",
  "finish": "0000-01-01 00:00:00"
}
Note: Session creation will fail if the user has reached their sessions_per_user limit or if the group has reached its total session limit.

Get All Users and Sessions

curl -s \
     -H "Authorization: xyzzy" \
     -X GET \
     https://www.nutritionquest.com/ffqapi/user \
| jq .

Response:

{
  "success": true,
  "users": [
    {
      "success": true,
      "user_id": "123_1",
      "user_cookie": "1bb43d659f52ca986b2f360c0bb7025d",
      "user_screen_name": "John_Doe",
      "sessions_per_user": 10,
      "session_count_total": 1,
      "session_count_complete": 0,
      "session_count_incomplete": 1,
      "sessions": [
        {
          "session_cookie": "cbd42f733e4c8f65f8f98c52a4fea5fd",
          "complete": false,
          "start": "2024-03-03 00:00:00",
          "finish": "0000-01-01 00:00:00"
        }
      ]
    }
  ]
}

Update Session Answers

curl -s \
     -H "Authorization: xyzzy" \
     -H "Content-Type: application/json" \
     -X PUT \
     -d '{"answer_1":true,"answer_2":false}' \
     https://www.nutritionquest.com/ffqapi/user/1bb43d659f52ca986b2f360c0bb7025d/session/cbd42f733e4c8f65f8f98c52a4fea5fd/answers \
| jq .

Response:

{
  "success": true,
  "message": "Updated session answers."
}

Finish Session Analysis

curl -s \
     -H "Authorization: xyzzy" \
     -X POST \
     https://www.nutritionquest.com/ffqapi/user/1bb43d659f52ca986b2f360c0bb7025d/session/cbd42f733e4c8f65f8f98c52a4fea5fd/finish \
| jq .

Response:

{
  "success": true,
  "message": "Analyzed session."
}

Get JSON Results

curl -s \
     -H "Authorization: xyzzy" \
     -X GET \
     https://www.nutritionquest.com/ffqapi/user/1bb43d659f52ca986b2f360c0bb7025d/session/cbd42f733e4c8f65f8f98c52a4fea5fd/results \
| jq .

Response:

{
  "STATIC_ROOT": "https://www.nutritionquest.com",
  "ANSWER_1": true,
  "ANSWER_2": false,
  "RESPONDENTID": "123_1",
  "FINISHED": true,
  "TODAYSDATE": "02282024",
  "AGE": 40,
  "YOGURTQUAN": "3",
  "PLANTYOGURTQUAN": "2"
}

Get HTML Results

curl -s \
     -H "Authorization: xyzzy" \
     -X GET \
     https://www.nutritionquest.com/ffqapi/user/1bb43d659f52ca986b2f360c0bb7025d/session/cbd42f733e4c8f65f8f98c52a4fea5fd/results_html

Response:

<div>
  <div class="row">
    <div class="col m12">
       ...
    </div>
  </div>
</div>

Batch Import Records

curl -s \
     -H "Authorization: xyzzy" \
     -H "Content-Type: application/json" \
     -X POST \
     -d '[
    {
        "complete_flag": true,
        "date_completed": "01012024",
        "user_id": "0000000052",
        "answers": {
            "RespondID": "0000000052",
            "answer_1": "1",
            "answer_2": "2",
            "answer_3": "3"
        }
    }
]' \
     https://www.nutritionquest.com/ffqapi/import \
| jq .

Export by Session Cookies

curl -s \
     -H "Authorization: xyzzy" \
     -H "Content-Type: application/json" \
     -X POST \
     -d '{"session_cookies": ["c4becc52184869a8675f03acc4383670"]}' \
     https://www.nutritionquest.com/ffqapi/export \
| jq .

Response:

{
  "success": true,
  "url": "https://www.nutritionquest.com/login/downloads/data-2024-03-24-19-35-56-rand-3429.zip"
}

Update User Password and Session Limit

curl -s \
     -H "Authorization: xyzzy" \
     -H "Content-Type: application/json" \
     -X PUT \
     -d '{"user_password": "newpassword123", "sessions_per_user": 5}' \
     https://www.nutritionquest.com/ffqapi/user/USER_COOKIE \
| jq .

Response:

{
  "success": true,
  "message": "Updated user."
}
Note: The sessions_per_user value cannot exceed the group's default per-user limit. Attempting to set a higher value will result in an error.