Introduction
January AI’s Enterprise API gives you direct access to metabolic health and food intelligence tools, built for seamless B2B integration. Use our RESTful APIs to integrate advanced metabolic health insights and lifestyle intelligence directly into your platform. Our proprietary food database, enhanced with AI/ML, covers 54 million+ verified items across branded foods, groceries, and restaurant menus.
Integrate the most accurate food logging, glucose prediction, and food analysis tools available into your platform.
With January’s APIs, developers can:
- 🔍 Search millions of food items by name, barcode, or natural language (e.g., “milkshake with banana”).
- 📸 Scan foods using our market-leading AI vision model for nutrient detection, with industry-best accuracy.
- 🍽️ Find menu items from local and national restaurants by name and location.
- 📝 Log food: Create, retrieve, and manage user entries with precision.
- 🧬 Predict glucose: Enable users to see how food will impact their blood sugar before they eat it, based on their demographics, health condition, and activity—no CGM or sensors required.
- 🔄 Recommend food swaps: Suggest healthier, semantically-similar foods based on user preferences, health goals, and restrictions.
Authentication
To authorize, use this code:
import requests
import json
# Replace YOUR_API_KEY with your actual API key
api_key = 'YOUR_API_KEY'
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
# With shell, you can just pass the correct header with each request
curl "https://partners.january.ai/v1.1/endpoint" \
-H "Authorization: Bearer YOUR_API_KEY"
const axios = require('axios');
// Replace YOUR_API_KEY with your actual API key
const apiKey = 'YOUR_API_KEY';
const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
};
Make sure to replace
YOUR_API_KEYwith your actual API key.
The January AI API uses bearer tokens for authentication. To obtain an API key, please send an email with your request.
The API key must be included in all API requests to the server in a header that looks like the following:
Authorization: Bearer YOUR_API_KEY
Lifestyle Intelligence APIs
Search, analyze, and interpret food data using these Lifestyle Intelligence APIs.
Food Search (By Name or Barcode)
import requests
url = 'https://partners.january.ai/v1.1/search/foods'
params = {
'query': 'banana',
'category': 'branded'
}
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'your-user-id'
}
response = requests.get(url, params=params, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/search/foods?query=banana&category=branded' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: your-user-id'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/search/foods',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'your-user-id'
},
params: {
query: 'banana',
category: 'branded'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"totalCount": 40,
"items": [
{
"id": 84222716,
"name": "banana",
"protein": 2,
"energy": 160,
"brand_name": "One",
"carbs": 15,
"fat": 10,
"fat_total_saturated": 5,
"net_carbs": 13,
"sodium": 20,
"sugars": 13,
"added_sugars": 11,
"gi": 34.899727,
"gl": 5.234959,
"fiber": 2,
"potassium": 170,
"cholesterol": 2.5,
"photo_url": null,
"servings": [
{
"id": 67943292,
"scaling_factor": 1,
"quantity": 5,
"unit": "pieces",
"weight_grams": 28,
"is_primary": true
}
]
}
]
}
Search for food items by name or barcode from January’s verified database of 54+ million foods, including branded, grocery, and restaurant items.
HTTP Request
GET https://partners.january.ai/v1.1/search/foods
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| x-partner-user-id | No | Unique user ID from your system |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| query | Optional | The search term for food items |
| category | Optional | The category of food items to filter results ('branded' or 'general') |
| upc | Optional | The UPC representing the barcode of a food item |
Response Structure
The response includes:
- totalCount: Total number of matching food items
- items: Array of food objects, each containing properties such as
id,name,brand_name,nutrients, andservings(with detailed nutrients and servings information)
NLP Food Search
import requests
url = 'https://partners.january.ai/v1.1/search/foods/nlp'
params = {
'query': '1 banana, 1 bowl of oatmeal, glass of orange juice'
}
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'your-user-id'
}
response = requests.get(url, params=params, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/search/foods/nlp?query=1%20banana%2C%201%20bowl%20of%20oatmeal%2C%20glass%20of%20orange%20juice' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: your-user-id'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/search/foods/nlp',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'your-user-id'
},
params: {
query: '1 banana, 1 bowl of oatmeal, glass of orange juice'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"totalNutrients": {
"calories": {
"value": 435,
"unit": "kcal"
},
"carbs": {
"value": 92,
"unit": "g"
},
"protein": {
"value": 8.5,
"unit": "g"
}
},
"detections": [
{
"food": {
"name": "Banana",
"id": 123456,
"brandName": null,
"nutrients": {
"calories": {
"value": 105,
"unit": "kcal"
}
},
"servings": [
{
"id": 78901,
"quantity": 1,
"unit": "medium banana"
}
]
}
}
]
}
Search for multiple foods at once by describing them in plain English — via voice or text.
HTTP Request
GET https://partners.january.ai/v1.1/search/foods/nlp
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| x-partner-user-id | No | Unique user ID from your system |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| query | Yes | The search term for food items in natural language |
Response Structure
The response includes:
- totalNutrients: Summary of total nutritional content
- detections: Array of detected food items with detailed information
Restaurant Search
import requests
url = 'https://partners.january.ai/v1.1/search/restaurants'
params = {
'query': 'mcdonalds',
'lat': 37.549,
'lon': -121.989
}
headers = {
'Authorization': 'Bearer YOUR_API_KEY'
}
response = requests.get(url, params=params, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/search/restaurants?query=mcdonalds&lat=37.549&lon=-121.989' \
--header 'Authorization: Bearer YOUR_API_KEY'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/search/restaurants',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
params: {
query: 'mcdonalds',
lat: 37.549,
lon: -121.989
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"items": [
{
"type": "restaurant",
"id": "53fc3b8a-e6bf-404d-83c8-9f42124d1bee",
"name": "McDonald's",
"is_chain": false,
"distance": 8,
"city": "San Francisco",
"address1": "123 Main Street",
"address2": "Suite 100"
}
]
}
This endpoint allows you to search for restaurants (local and/or chain) by name.
HTTP Request
GET https://partners.january.ai/v1.1/search/restaurants
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| query | Yes | The search term related to the restaurant. Leave empty to return all nearest restaurants. |
| lat | Optional | Latitude coordinate for proximity search |
| lon | Optional | Longitude coordinate for proximity search |
| distance | Optional | Distance in meters to search for restaurants. Default is 16093 meters (~10 miles) |
| limit | Optional | Maximum number of results to return. Default is 50 |
Response Structure
The response includes:
- items: Array of restaurant locations with id, name, chain status, distance, and address information
Menu within a Restaurant Search
import requests
url = 'https://partners.january.ai/v1.1/search/restaurants/menu'
params = {
'query': 'burger',
'lat': 37.549,
'lon': -121.989
}
headers = {
'Authorization': 'Bearer YOUR_API_KEY'
}
response = requests.get(url, params=params, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/search/restaurants/menu?query=burger&lat=37.549&lon=-121.989' \
--header 'Authorization: Bearer YOUR_API_KEY'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/search/restaurants/menu',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
},
params: {
query: 'burger',
lat: 37.549,
lon: -121.989
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"items": [
{
"type": "menu_item",
"id": "228990954",
"name": "burger",
"restaurant_name": "morning due cafe",
"is_chain": false,
"data_source_id": 12,
"source_original_id": "ngxZD7tEA1cQGCuOYBF05Ckft2ZP3z3Ja88wVaXYqqr7P7F3QiGFN1BSCl6H0Bt_5iN7y",
"protein": 48,
"energy": 800,
"carbs": 40,
"net_carbs": 38,
"sugars": 6,
"added_sugars": null,
"fat": 45,
"gi": 48.507698,
"gl": 36.67089,
"fiber": 2,
"photo_url": "https://cdn-img.ai/23361362e6a706567",
"servings": [
{
"id": 189343592,
"scaling_factor": 1,
"quantity": 1,
"unit": "serving",
"weight_grams": null,
"is_primary": true
}
],
"distance": 124
}
]
}
This endpoint allows you to search for restaurants (local and/or chain) by name.
HTTP Request
GET https://partners.january.ai/v1.1/search/restaurants/menu
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| query | Yes | The search term related to the menu (food name or restaurant name) |
| lat | Yes | Latitude coordinate for proximity search |
| lon | Yes | Longitude coordinate for proximity search |
| distance | Optional | Distance in meters to search for restaurant menus. Default is 16093 meters (~10 miles) |
| limit | Optional | Maximum number of results to return. Default is 50 |
Response Structure
The response includes:
- items: Array of menu items with id, name, restaurant name, photo URL, nutrients and primary serving information
Photo Scan
import requests
import json
url = 'https://partners.january.ai/v1.1/vision/foods'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
data = {
"photoUrl": "https://i.imgur.com/bTQIGxf.png"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/vision/foods' \
--header 'Content-Type: application/json' \
--header 'x-partner-user-id: your-user-id' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"photoUrl": "https://i.imgur.com/bTQIGxf.png"
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/vision/foods',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
},
data: {
photoUrl: 'https://i.imgur.com/bTQIGxf.png'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"mealName": "Breakfast Bowl",
"totalNutrients": {
"calories": {
"value": 520,
"unit": "kcal"
},
"carbs": {
"value": 68,
"unit": "g"
},
"protein": {
"value": 15,
"unit": "g"
}
},
"detections": [
{
"confidenceScore": "high",
"food": {
"name": "Oatmeal",
"id": 789012,
"brandName": null,
"nutrients": {
"calories": {
"value": 300,
"unit": "kcal"
}
},
"servings": [
{
"id": 45678,
"quantity": 1,
"unit": "cup"
}
]
}
}
]
}
Scan a photo of a meal to identify and retrieve nutritional data for the foods detected.
HTTP Request
POST https://partners.january.ai/v1.1/vision/foods
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Unique user ID from your system |
Request Body
| Parameter | Required | Description |
|---|---|---|
| photoUrl | No | The URL of the image to be analyzed |
| photoBase64 | No | Base64 encoded image data (if not using photoUrl) |
Photo Requirements
- Must be at least 512x512 pixels in JPG or JPEG format
- Maximum resolution: 1024x1024 pixels
- Maximum file size: 4 MB
- Must not include location or personal metadata
- Must not be blurry or dark
Response Structure
The response includes:
- mealName: Name of the meal identified in the image
- totalNutrients: Summary of total nutritional content
- detections: Array of detected food items with confidence scores
Edit Photo Scan Results
import requests
import json
url = 'https://partners.january.ai/v1.1/vision/fix-ai'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
data = {
"mealName": "Breakfast Bowl",
"detections": [
{
"confidenceScore": "high",
"food": {
"name": "Oatmeal",
"id": 789012,
"brandName": null,
"nutrients": {
"calories": {
"value": 300,
"unit": "kcal"
}
},
"servings": [
{
"id": 45678,
"quantity": 1,
"unit": "cup"
}
]
}
}
],
"userInput": "change oatmeal to steel-cut oats"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/vision/fix-ai' \
--header 'Content-Type: application/json' \
--header 'x-partner-user-id: your-user-id' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"mealName": "Breakfast Bowl",
"detections": [
{
"confidenceScore": "high",
"food": {
"name": "Oatmeal",
"id": 789012,
"brandName": null,
"nutrients": {
"calories": {
"value": 300,
"unit": "kcal"
}
},
"servings": [
{
"id": 45678,
"quantity": 1,
"unit": "cup"
}
]
}
}
],
"userInput": "change oatmeal to steel-cut oats"
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/vision/fix-ai',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
},
data: {
"mealName": "Breakfast Bowl",
"detections": [
{
"confidenceScore": "high",
"food": {
"name": "Oatmeal",
"id": 789012,
"brandName": null,
"nutrients": {
"calories": {
"value": 300,
"unit": "kcal"
}
},
"servings": [
{
"id": 45678,
"quantity": 1,
"unit": "cup"
}
]
}
}
],
"userInput": "change oatmeal to steel-cut oats"
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"mealName": "Breakfast Bowl",
"totalNutrients": {
"calories": {
"value": 520,
"unit": "kcal"
},
"carbs": {
"value": 68,
"unit": "g"
},
"protein": {
"value": 15,
"unit": "g"
}
},
"detections": [
{
"confidenceScore": "high",
"food": {
"name": "Oatmeal",
"id": 789012,
"brandName": null,
"nutrients": {
"calories": {
"value": 300,
"unit": "kcal"
}
},
"servings": [
{
"id": 45678,
"quantity": 1,
"unit": "cup"
}
]
}
}
]
}
This API lets users update food types and quantities from a photo scan using natural language, either by voice or text. For example, after scanning a photo of a Mexican chicken and rice bowl and noticing a couple of inaccuracies, a user might say:
"It was actually 1 cup of chicken. It was also white rice, not brown rice."
The API parses this input and updates the scan results accordingly.
HTTP Request
POST https://partners.january.ai/v1.1/vision/fix-ai
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Unique user ID from your system |
Request Body
| Parameter | Required | Description |
|---|---|---|
| mealName | Yes | Name of the meal to edit |
| detections | Yes | Array of detected food items to edit |
| userInput | Yes | Text representation of changes to make |
Response Structure
The response includes:
- mealName: Modified name of the meal
- totalNutrients: Summary of total nutritional content
- detections: Array of modified food items with confidence scores
Healthy Alternatives
import requests
import json
url = 'https://partners.january.ai/v1.1/food-alternatives/5467772'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
data = {
"dietRestrictions": ["Gluten"],
"dietPreferences": ["Vegan"]
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/food-alternatives/5467772' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"dietRestrictions": ["Gluten"],
"dietPreferences": ["Vegan"]
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/food-alternatives/5467772',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
data: {
dietRestrictions: ["Gluten"],
dietPreferences: ["Vegan"]
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"alternatives": [
{
"food": {
"name": "Gluten-Free Oat Bread",
"id": 9876543,
"brandName": "Nature's Path",
"nutrients": {
"calories": {
"value": 80,
"unit": "kcal"
},
"carbs": {
"value": 15,
"unit": "g"
}
},
"servings": [
{
"id": 12345,
"quantity": 1,
"unit": "slice"
}
]
}
}
]
}
Get healthier alternatives for individual foods based on nutrition, context, and user preferences.
HTTP Request
POST https://partners.january.ai/v1.1/food-alternatives/{foodId}
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
URL Parameters
| Parameter | Description |
|---|---|
| foodId | The unique identifier of the food item to find alternatives for |
Request Body
| Parameter | Required | Description |
|---|---|---|
| dietRestrictions | Yes | Array of dietary restrictions/allergies |
| dietPreferences | Yes | Array of dietary preferences |
Dietary Restrictions
Valid dietary restrictions include:
- Gluten
- Lactose
- Yeast
- Tree nuts
- Peanuts
- Dairy
- Eggs
- Sulfites
- Soy
- Wheat
- Shellfish
- Fish
- Mushrooms
- Sesame
- MSG
- Caffeine
- FODMAPs
Dietary Preferences
Valid dietary preferences include:
- Vegetarian
- Vegan
- Keto
- Paleo
- Pescatarian
- Low carbohydrate
- High protein
- Kosher
Response Structure
The response includes:
- alternatives: Array of alternative food items with name, id, brandName, nutrients, and servings information
Food Logging APIs
Create, retrieve, and manage food logs with these Food Logging APIs.
Create Food Logs
import requests
import json
url = 'https://partners.january.ai/v1.1/logs/foods'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
data = {
"foods": [
{
"id": 101963552,
"serving": {
"id": 68051535,
"quantity": 1.4
}
}
],
"timestampUtc": "2024-09-13T11:34:56Z"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/logs/foods' \
--header 'Content-Type: application/json' \
--header 'x-partner-user-id: your-user-id' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"foods": [
{
"id": 101963552,
"serving": {
"id": 68051535,
"quantity": 1.4
}
}
],
"timestampUtc": "2024-09-13T11:34:56Z"
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/logs/foods',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
},
data: {
foods: [
{
id: 101963552,
serving: {
id: 68051535,
quantity: 1.4
}
}
],
timestampUtc: "2024-09-13T11:34:56Z"
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
Associate logged foods with a specific user.
HTTP Request
POST https://partners.january.ai/v1.1/logs/foods
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Unique user ID from your system |
Request Body
| Parameter | Required | Description |
|---|---|---|
| foods | Yes | Array of food items to be logged |
| foods[].id | Yes | Unique identifier of the food item |
| foods[].serving | Yes | Serving details of the food item |
| foods[].serving.id | Yes | Serving size identifier |
| foods[].serving.quantity | Yes | Amount of the serving consumed |
| timestampUtc | Yes | UTC timestamp when food was consumed (YYYY-MM-DDTHH:MM:SSZ) |
| name | Optional | Name of the meal |
Retrieve Food Logs
import requests
url = 'https://partners.january.ai/v1.1/logs/foods'
params = {
'start': '2023-09-12',
'end': '2024-09-15'
}
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'your-user-id'
}
response = requests.get(url, params=params, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/logs/foods?start=2023-09-12&end=2024-09-15' \
--header 'x-partner-user-id: your-user-id' \
--header 'Authorization: Bearer YOUR_API_KEY'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/logs/foods',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'your-user-id'
},
params: {
start: '2023-09-12',
end: '2024-09-15'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
Retrieve food logs for a specific user over a defined date range.
HTTP Request
GET https://partners.january.ai/v1.1/logs/foods
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| x-partner-user-id | Yes | Unique user ID from your system |
Query Parameters
| Parameter | Required | Description |
|---|---|---|
| start | Yes | Start date (YYYY-MM-DD format) |
| end | Yes | End date (YYYY-MM-DD format) |
Delete Food Log
import requests
url = 'https://partners.january.ai/v1.1/logs/foods/78129823-8ba2-4183-b13b-71f0e963c606'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'user123'
}
response = requests.delete(url, headers=headers)
print(response.status_code)
curl --location --request DELETE 'https://partners.january.ai/v1.1/logs/foods/78129823-8ba2-4183-b13b-71f0e963c606' \
--header 'x-partner-user-id: user123' \
--header 'Authorization: Bearer YOUR_API_KEY'
const axios = require('axios');
const config = {
method: 'delete',
url: 'https://partners.january.ai/v1.1/logs/foods/78129823-8ba2-4183-b13b-71f0e963c606',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-partner-user-id': 'user123'
}
};
axios(config)
.then(response => {
console.log(response.status);
})
.catch(error => {
console.log(error);
});
Delete food logs associated with a specific user.
HTTP Request
DELETE https://partners.january.ai/v1.1/logs/foods/{logId}
URL Parameters
| Parameter | Description |
|---|---|
| logId | The unique identifier of the food log to delete |
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| x-partner-user-id | Yes | Unique user ID from your system |
Glucose Insights APIs
Predict post-meal glucose responses with these Glucose Insights APIs.
Glucose Prediction
import requests
import json
url = 'https://partners.january.ai/v1.1/cgm/glucose-predict'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-timezone': 'America/Los_Angeles'
}
data = {
"userProfile": {
"age": 25,
"gender": "male",
"height": 65,
"weight": 165,
"activityLevel": "very_active",
"healthConditions": ["Type 2 diabetes"]
},
"startTime": "2025-04-09T19:06:12Z",
"foods": [
{
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
],
"cgmData": [
# Optional CGM data array
{
"timestamp": "2025-04-03T14:56:03Z",
"value": 92
},
{
"timestamp": "2025-04-03T14:59:40Z",
"value": 95
}
],
"consumedFoods": [
# Optional historical user foods
{
"timestamp": "2025-04-03T14:56:03Z",
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/cgm/glucose-predict' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-timezone: America/Los_Angeles' \
--data '{
"userProfile": {
"age": 25,
"gender": "male",
"height": 65,
"weight": 165,
"activityLevel": "very_active",
"healthConditions": ["Type 2 diabetes"]
},
"startTime": "2025-04-09T19:06:12Z",
"foods": [
{
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
],
"cgmData": [
{
"timestamp": "2025-04-03T14:56:03Z",
"value": 92
},
{
"timestamp": "2025-04-03T14:59:40Z",
"value": 95
}
],
"consumedFoods": [
{
"timestamp": "2025-04-03T14:56:03Z",
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/cgm/glucose-predict',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-timezone': 'America/Los_Angeles'
},
data: {
userProfile: {
age: 25,
gender: "male",
height: 65,
weight: 165,
activityLevel: "very_active",
healthConditions: ["Type 2 diabetes"]
},
startTime: "2025-04-09T19:06:12Z",
foods: [
{
id: 70380652,
serving: {
id: 34176931,
quantity: 1
}
}
],
cgmData: [
// Optional CGM data array
{
"timestamp": "2025-04-03T14:56:03Z",
"value": 92
}
],
consumedFoods: [
// Optional historical user foods
{
timestamp: "2025-04-03T14:56:03Z",
id: 70380652,
serving: {
id: 34176931,
quantity: 1
}
}
]
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"cgp": [
[0, 95],
[15, 110],
[30, 140],
[45, 155],
[60, 145],
[75, 125],
[90, 110],
[105, 100],
[120, 95],
[135, 92]
],
"scoring": "medium_impact",
"cgp_min": 70,
"cgp_max": 140
}
This endpoint returns two-hour glucose predictions for a user based on individual food or meal lookups.
You can optionally provide cgmData and consumedFoods to enable hyper-personalized glucose predictions. To complete training, the data must include at least five “complete” training days.
A training day is considered complete if it meets both of the following criteria: - At least 12 hours of CGM data - At least 2 logged meals at different times of the day
HTTP Request
POST https://partners.january.ai/v1.1/cgm/glucose-predict
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-timezone | Yes | User local timezone (e.g. America/New_York or US/Pacific) |
Request Body
| Parameter | Required | Description |
|---|---|---|
| userProfile | Yes | User's profile data |
| userProfile.age | Yes | User's age |
| userProfile.gender | Yes | User's gender ('male' or 'female') |
| userProfile.height | Yes | User's height in inches |
| userProfile.weight | Yes | User's weight in pounds |
| userProfile.activityLevel | Yes | Activity level ('sedentary', 'lightly_active', 'moderately_active', 'very_active') |
| userProfile.healthConditions | Yes | Array of health conditions |
| foods | Yes | Array of foods and servings for prediction |
| foods[].id | Yes | Unique identifier of the food item |
| foods[].serving | Yes | Serving details |
| foods[].serving.id | Yes | Serving size identifier |
| foods[].serving.quantity | Yes | Amount of serving consumed |
| startTime | Yes | ISO 8601 timestamp for when foods are consumed |
| cgmData | No | CGM data array for AI training. Please provide at least one data point per 15 minutes. If cgmData is provided, consumedFoods must be provided also. |
| cgmData[].timestamp | Yes | ISO 8601 timestamp for the CGM data point |
| cgmData[].value | Yes | Blood sugar level (in mg/dL) |
| consumedFoods | No | Array of historical user foods and servings for AI training. |
| consumedFoods[].timestamp | Yes | ISO 8601 timestamp for when the food is consumed |
| consumedFoods[].id | Yes | Unique identifier of the food item |
| consumedFoods[].serving | Yes | Serving details |
| consumedFoods[].serving.id | Yes | Serving size identifier |
| consumedFoods[].serving.quantity | Yes | Amount of serving consumed |
Health Conditions
Valid health conditions include:
- Type 1 diabetes
- Type 2 diabetes
- Prediabetes
- Gestational diabetes (prior pregnancy)
- Latent autoimmune diabetes in adults (LADA)
- Cystic-fibrosis related diabetes
- Diabetes, but not sure which type
- None of the above
- Other
Response Structure
The response includes:
- cgp: Array of data points representing glucose response curve [minute, glucose_value]
- scoring: Qualitative impact scoring ('low_impact', 'medium_impact', 'high_impact')
- cgp_min: User's minimum glucose level (in mg/dL), based on the input user profile.
- cgp_max: User's maximum glucose level (in mg/dL), based on the input user profile.
AI-Trained Glucose Prediction
import requests
import json
url = 'https://partners.january.ai/v1.1/cgm/user-glucose-predict'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'YOUR_PARTNER_USER_ID',
'x-partner-timezone': 'America/Los_Angeles'
}
data = {
"startTime": "2025-04-09T19:06:12Z",
"foods": [
{
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/cgm/user-glucose-predict' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: YOUR_PARTNER_USER_ID' \
--header 'x-partner-timezone: America/Los_Angeles' \
--data '{
"startTime": "2025-04-09T19:06:12Z",
"foods": [
{
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/cgm/user-glucose-predict',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'YOUR_PARTNER_USER_ID',
'x-partner-timezone': 'America/Los_Angeles'
},
data: {
startTime: "2025-04-09T19:06:12Z",
foods: [
{
id: 70380652,
serving: {
id: 34176931,
quantity: 1
}
}
]
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"cgp": [
[0, 95],
[15, 110],
[30, 140],
[45, 155],
[60, 145],
[75, 125],
[90, 110],
[105, 100],
[120, 95],
[135, 92]
],
"scoring": "medium_impact",
"cgp_min": 70,
"cgp_max": 140
}
Returns a two-hour glucose prediction using a personalized AI model trained on a specific user's CGM and meal history.
To use this endpoint, pass the user’s ID in the x-partner-user-id header. The user must already exist and have completed AI training (see User Management APIs).
Accepts either the foods or nutrients parameter as input. Unlike the standard glucose prediction endpoint, this version does not require passing CGM data in the request — improving performance by using previously stored training data.
HTTP Request
POST https://partners.january.ai/v1.1/cgm/user-glucose-predict
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Partner User ID (UUID format) |
| x-partner-timezone | Yes | User local timezone (e.g. America/New_York or US/Pacific) |
Request Body
| Parameter | Required | Description |
|---|---|---|
| startTime | No | ISO 8601 timestamp for when foods are consumed (default is current time) |
| foods | No | Array of foods and servings for prediction. If not specified, then nutrients parameter is applied. |
| foods[].id | Yes | Unique identifier of the food item |
| foods[].serving | Yes | Serving details |
| foods[].serving.id | Yes | Serving size identifier |
| foods[].serving.quantity | Yes | Amount of serving consumed |
| nutrients | No | Object with nutrients quantities (applied only when foods parameter is not specified) |
| nutrients.water | No | Quantity of water (g) |
| nutrients.energy | No | Quantity of energy (calories) |
| nutrients.protein | No | Quantity of protein (g) |
| nutrients.fat_total_lipid | No | Quantity of total fat (g) |
| nutrients.carbohydrate | No | Quantity of carbohydrates (g) |
| nutrients.fiber | No | Quantity of fiber (g) |
| nutrients.sugars | No | Quantity of sugars (g) |
| nutrients.calcium | No | Quantity of calcium (g) |
| nutrients.iron | No | Quantity of iron (g) |
| nutrients.potassium | No | Quantity of potassium (g) |
| nutrients.sodium | No | Quantity of sodium (mg) |
| nutrients.vit_c | No | Quantity of vit C (g) |
| nutrients.vit_a_iu | No | Quantity of vit A iu (g) |
| nutrients.fat_total_saturated | No | Quantity of saturated fat (g) |
| nutrients.fat_total_monounsaturated | No | Quantity of monounsaturated fat (g) |
| nutrients.fat_total_polyunsaturated | No | Quantity of polyunsaturated fat (g) |
| nutrients.fat_total_trans | No | Quantity of trans fat (g) |
| nutrients.cholesterol | No | Quantity of cholesterol (g) |
| nutrients.caffeine | No | Quantity of caffeine (g) |
Response Structure
The response includes:
- cgp: Array of data points representing glucose response curve [minute, glucose_value]
- scoring: Qualitative impact scoring ('low_impact', 'medium_impact', 'high_impact')
- cgp_min: User's minimum glucose level (in mg/dL), based on the input user profile.
- cgp_max: User's maximum glucose level (in mg/dL), based on the input user profile.
User Management APIs
Create, update, and delete users, and check whether they meet the criteria for AI training to enable personalized glucose predictions.
Create User
import requests
import json
url = 'https://partners.january.ai/v1.1/user'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
data = {
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/user' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/user',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
data: {
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"user_id": "a88888ef-cc9c-5882-ba2c-9cbee8a4b73c",
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
Creates a user and returns the user ID. Requires a user profile in the request.
HTTP Request
POST https://partners.january.ai/v1.1/user
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
Request Body
| Parameter | Required | Description |
|---|---|---|
| profile | Yes | User profile object |
| profile.age | Yes | User's age |
| profile.gender | Yes | User's gender ('male' or 'female') |
| profile.height | Yes | User's height in inches |
| profile.weight | Yes | User's weight in pounds |
| profile.activityLevel | No | Activity level ('sedentary', 'lightly_active', 'moderately_active', 'very_active') |
| profile.healthConditions | No | Array of health conditions |
Health Conditions
Valid health conditions include:
- Type 1 diabetes
- Type 2 diabetes
- Prediabetes
- Gestational diabetes (prior pregnancy)
- Latent autoimmune diabetes in adults (LADA)
- Cystic-fibrosis related diabetes
- Diabetes, but not sure which type
- None of the above
- Other
Response Structure
The response includes:
- user_id: Created user ID
- profile: User profile object
Get User Profile
import requests
import json
url = 'https://partners.january.ai/v1.1/user'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
response = requests.get(url, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/user' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: your-user-id'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/user',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"user_id": "a88888ef-cc9c-5882-ba2c-9cbee8a4b73c",
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
Returns the partner user's ID and profile. Returns a 404 Not Found error if the specified user ID does not exist.
HTTP Request
GET https://partners.january.ai/v1.1/user
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Your user ID |
Response Structure
The response includes:
- user_id: Partner user ID
- profile: User profile object
Update User Profile
import requests
import json
url = 'https://partners.january.ai/v1.1/user'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
data = {
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
response = requests.patch(url, headers=headers, json=data)
print(response.json())
curl --location --request PATCH 'https://partners.january.ai/v1.1/user' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: your-user-id'
--data '{
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}'
const axios = require('axios');
const config = {
method: 'patch',
url: 'https://partners.january.ai/v1.1/user',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
},
data: {
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"user_id": "a88888ef-cc9c-5882-ba2c-9cbee8a4b73c",
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
}
Updates the user's profile and returns their user information. Requires a user profile in the request body.
HTTP Request
PATCH https://partners.january.ai/v1.1/user
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Your user ID |
Request Body
| Parameter | Required | Description |
|---|---|---|
| profile | Yes | User profile object |
| profile.age | Yes | User's age |
| profile.gender | Yes | User's gender ('male' or 'female') |
| profile.height | Yes | User's height in inches |
| profile.weight | Yes | User's weight in pounds |
| profile.activityLevel | No | Activity level ('sedentary', 'lightly_active', 'moderately_active', 'very_active') |
| profile.healthConditions | No | Array of health conditions |
Health Conditions
Valid health conditions include:
- Type 1 diabetes
- Type 2 diabetes
- Prediabetes
- Gestational diabetes (prior pregnancy)
- Latent autoimmune diabetes in adults (LADA)
- Cystic-fibrosis related diabetes
- Diabetes, but not sure which type
- None of the above
- Other
Response Structure
The response includes:
- user_id: Partner user ID
- profile: User profile object
Delete User
import requests
import json
url = 'https://partners.january.ai/v1.1/user'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
response = requests.delete(url, headers=headers)
print(response.json())
curl --location --request DELETE 'https://partners.january.ai/v1.1/user' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: your-user-id'
const axios = require('axios');
const config = {
method: 'delete',
url: 'https://partners.january.ai/v1.1/user',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
Deletes the user. If the specified user ID does not exist, the request still returns a success status.
HTTP Request
DELETE https://partners.january.ai/v1.1/user
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Your user ID to delete |
Get All Users
import requests
import json
url = 'https://partners.january.ai/v1.1/users'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
response = requests.get(url, headers=headers)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/users' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY'
const axios = require('axios');
const config = {
method: 'get',
url: 'https://partners.january.ai/v1.1/users',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON array like this:
[
{
"user_id": "a88888ef-cc9c-5882-ba2c-9cbee8a4b73c",
"profile": {
"age": 20,
"gender": "male",
"weight": 80,
"height": 36,
"activity_level": "sedentary",
"medical_conditions": []
}
},
....
]
This endpoint returns all partner user IDs and profiles.
HTTP Request
GET https://partners.january.ai/v1.1/users
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
Response Structure
The response includes array of:
- user_id: Partner user ID
- profile: User profile object
Mark User as AI-Trained
import requests
import json
url = 'https://partners.january.ai/v1.1/user/training'
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
}
data = {
"cgm_data": [
# CGM data array
{
"timestamp": "2025-04-03T14:56:03Z",
"value": 92
},
{
"timestamp": "2025-04-03T14:59:40Z",
"value": 95
}
],
"consumed_foods": [
# Historical user foods
{
"timestamp": "2025-04-03T14:56:03Z",
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
curl --location 'https://partners.january.ai/v1.1/user/training' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'x-partner-user-id: your-user-id' \
--data '{
"cgm_data": [
{
"timestamp": "2025-04-03T14:56:03Z",
"value": 92
},
{
"timestamp": "2025-04-03T14:59:40Z",
"value": 95
}
],
"consumed_foods": [
{
"timestamp": "2025-04-03T14:56:03Z",
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}'
const axios = require('axios');
const config = {
method: 'post',
url: 'https://partners.january.ai/v1.1/user/training',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-partner-user-id': 'your-user-id'
},
data: {
"cgm_data": [
// CGM data array
{
"timestamp": "2025-04-03T14:56:03Z",
"value": 92
},
{
"timestamp": "2025-04-03T14:59:40Z",
"value": 95
}
],
"consumed_foods": [
// Historical user foods
{
"timestamp": "2025-04-03T14:56:03Z",
"id": 70380652,
"serving": {
"id": 34176931,
"quantity": 1
}
}
]
}
};
axios(config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
The above command returns JSON structured like this:
{
"good_days": [
"2025-09-01",
"2025-09-02",
"2025-09-03",
"2025-09-04",
"2025-09-05"
]
}
Sets user AI training data for personalized glucose predictions.
Requires cgm_data and consumed_foods parameters with sufficient data to complete training. Training is considered complete if the input includes five or more valid training days.
A valid training day must include:
- At least 12 hours of CGM data
- At least 2 logged meals at different times of the day
If the data does not meet these requirements, the endpoint returns a 400 Bad Request error.
HTTP Request
POST https://partners.january.ai/v1.1/user/training
Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token for authentication |
| Content-Type | Yes | Must be application/json |
| x-partner-user-id | Yes | Your user ID |
Request Body
| Parameter | Required | Description |
|---|---|---|
| cgm_data | Yes | CGM data array for AI training. Please provide at least one data point per 15 minutes. |
| cgm_data[].timestamp | Yes | ISO 8601 timestamp for the CGM data point |
| cgm_data[].value | Yes | Blood sugar level (in mg/dL) |
| consumed_foods | Yes | Array of historical user foods and servings for AI training. |
| consumed_foods[].timestamp | Yes | ISO 8601 timestamp for when the food is consumed |
| consumed_foods[].id | Yes | Unique identifier of the food item |
| consumed_foods[].serving | Yes | Serving details |
| consumed_foods[].serving.id | Yes | Serving size identifier |
| consumed_foods[].serving.quantity | Yes | Amount of serving consumed |
Response Structure
The response includes:
- good_days: Array of good days (ISO 8601 date format)
Errors
The January AI API uses the following error codes:
| Error Code | Meaning |
|---|---|
| 400 | Bad Request -- Your request is invalid or malformed. |
| 401 | Unauthorized -- Your API key is invalid or missing. |
| 403 | Forbidden -- You don't have permission to access this resource. |
| 404 | Not Found -- The specified resource could not be found. |
| 405 | Method Not Allowed -- You tried to access a resource with an invalid HTTP method. |
| 406 | Not Acceptable -- You requested a format that isn't supported. |
| 422 | Unprocessable Entity -- The request was well-formed but contains semantic errors. |
| 429 | Too Many Requests -- You're making too many requests! Please slow down. |
| 500 | Internal Server Error -- We had a problem with our server. Try again later. |
| 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Error Response Format
Error responses are formatted like this:
{
"error": {
"code": 400,
"message": "Bad Request",
"details": "The 'query' parameter is required for this endpoint."
}
}
All error responses follow a consistent format with an error object containing:
- code: HTTP status code
- message: Human-readable error message
- details: Additional information about the error (when available)
Common Error Scenarios
Authentication Errors
- 401 Unauthorized: Missing or invalid API key
- 403 Forbidden: Valid API key but insufficient permissions
Request Errors
- 400 Bad Request: Missing required parameters or invalid parameter values
- 422 Unprocessable Entity: Valid request format but business logic errors
- 429 Too Many Requests: Rate limiting exceeded
Server Errors
- 500 Internal Server Error: Unexpected server-side error
- 503 Service Unavailable: Temporary service outage