REST API Reference
Ice Cream Calculator REST API Reference
Introduction
This document provides complete technical reference for all Ice Cream Calculator REST API endpoints. Each endpoint is documented with request format, response structure, and example code.
📘 New to the API? Start with the Getting Started Guide to learn how to generate your API key and make your first request.
Base URL
https://icecreamcalc.com/api
All endpoints are relative to this base URL.
Authentication
All endpoints (except /recipes/test) require authentication using an API key.
Include API Key in Header
X-API-Key: icc_your_api_key_here
Authentication Errors
| Error | HTTP Code | Response |
|---|---|---|
| Missing API Key | 401 | {"error": "API key is required", "details": "Include X-API-Key header with your API key"} |
| Invalid API Key | 401 | {"error": "Invalid API key", "details": "The provided API key is not valid or the user account is inactive"} |
Endpoints Overview
| Endpoint | Method | Description |
|---|---|---|
/recipes | GET | List all your recipes |
/recipes/{id} | GET | Get a single recipe with ingredients |
/recipes/{id}/calculated | GET | Get calculated data for a recipe |
/ingredients | GET | List all accessible ingredients |
/ingredients/{id} | GET | Get a single ingredient with full details |
Recipe Endpoints
GET /api/recipes
Retrieve a list of all your recipes with basic information.
Request
GET /api/recipes
Headers:
X-API-Key: icc_your_api_key_here
Response (200 OK)
{
"success": true,
"count": 2,
"recipes": [
{
"id": 1,
"name": "Classic Vanilla Ice Cream",
"info": "Traditional vanilla base",
"evaporation": 0.05,
"createdDate": "2025-01-15T10:30:00Z",
"changedDate": "2025-11-08T14:20:00Z",
"hasChart": true,
"chartName": "Ice Cream Base",
"mixWeight": 1000.0,
"finalWeight": 950.0,
"ingredients": [
{
"id": 1,
"ingredientId": 42,
"ingredientName": "Heavy Cream",
"ingredientSource": "Default",
"isOverride": false,
"weight": 500.0,
"inclusion": false,
"infusion": false,
"position": 0,
"amountMin": 0.0,
"amountMax": 1.0
}
]
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Always true for successful requests |
count | integer | Number of recipes returned |
recipes | array | List of recipe objects |
Recipe Object Fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique recipe identifier |
name | string | Recipe name |
info | string | Recipe description/notes |
evaporation | number | Evaporation percentage (0.05 = 5%) |
mixWeight | number | Total mix weight in grams (before freezing) |
finalWeight | number | Final weight in grams (after evaporation) |
ingredients | array | List of ingredients with weights |
Example (curl)
curl -H "X-API-Key: icc_your_key" \
https://icecreamcalc.com/api/recipes
Example (Python)
import requests
response = requests.get(
"https://icecreamcalc.com/api/recipes",
headers={"X-API-Key": "icc_your_key"}
)
recipes = response.json()
for recipe in recipes['recipes']:
print(f"{recipe['name']} - {recipe['mixWeight']}g")
GET /api/recipes/{id}
Retrieve detailed information for a single recipe, including all ingredients.
Request
GET /api/recipes/1
Headers:
X-API-Key: icc_your_api_key_here
Response (200 OK)
{
"success": true,
"recipe": {
"id": 1,
"name": "Classic Vanilla Ice Cream",
"info": "Traditional vanilla base",
"evaporation": 0.05,
"createdDate": "2025-01-15T10:30:00Z",
"changedDate": "2025-11-08T14:20:00Z",
"hasChart": true,
"chartName": "Ice Cream Base",
"mixWeight": 1000.0,
"finalWeight": 950.0,
"ingredients": [...]
}
}
Error Responses
| HTTP Code | Response | Meaning |
|---|---|---|
404 | {"error": "Recipe not found"} | Recipe with this ID doesn’t exist |
403 | Forbidden | Recipe belongs to another user |
Example (curl)
curl -H "X-API-Key: icc_your_key" \
https://icecreamcalc.com/api/recipes/1
GET /api/recipes/{id}/calculated
Retrieve calculated data for a recipe including PAC, POD, serving temperatures, and all other ice cream science properties.
Note: This endpoint performs full recipe calculations, so it may take slightly longer than other endpoints.
Request
GET /api/recipes/1/calculated
Headers:
X-API-Key: icc_your_api_key_here
Response (200 OK)
{
"success": true,
"data": {
"recipeId": 1,
"recipeName": "Classic Vanilla Ice Cream",
"values": {
"PAC": {
"name": "PAC",
"displayValue": "285.43",
"numericValue": 285.43,
"info": "Freezing point depression",
"isTemperature": false
},
"POD": {
"name": "POD",
"displayValue": "32.15",
"numericValue": 32.15,
"info": "Relative sweetness",
"isTemperature": false
},
"Serving temp ice cream": {
"name": "Serving temp ice cream",
"displayValue": "-14.2°C",
"numericValue": -14.2,
"info": "Recommended serving temperature for ice cream",
"isTemperature": true
}
// ... many more calculated values
}
}
}
Calculated Values Included
- PAC – Freezing point depression
- POD – Relative sweetness
- Serving temperatures – For ice cream and gelato
- Nutritional data – Fat, protein, sugars, etc.
- Milk solids – MSNF, milk fat, milk protein
- Percentages – Water, solids, overrun, etc.
- Weights – Mix weight, final weight, additions
- And more – All calculated recipe properties
Example (Python)
import requests
response = requests.get(
"https://icecreamcalc.com/api/recipes/1/calculated",
headers={"X-API-Key": "icc_your_key"}
)
data = response.json()['data']
pac = data['values']['PAC']['numericValue']
pod = data['values']['POD']['numericValue']
print(f"PAC: {pac}, POD: {pod}")
Ingredient Endpoints
GET /api/ingredients
Retrieve a list of all ingredients you have access to (personal ingredients + shared/default ingredients).
Note: This endpoint returns basic information only. For full nutritional data, use /api/ingredients/{id}
Request
GET /api/ingredients
Headers:
X-API-Key: icc_your_api_key_here
Response (200 OK)
{
"success": true,
"count": 153,
"ingredients": [
{
"id": 1,
"name": "Whole Milk",
"category": "Dairy",
"source": "Default",
"isOverride": false,
"isRecipeDerived": false,
"created": "2024-01-01T00:00:00Z",
"changed": "2024-01-01T00:00:00Z"
},
{
"id": 42,
"name": "My Custom Sugar",
"category": "Sugar",
"source": "Personal",
"isOverride": false,
"isRecipeDerived": false,
"created": "2025-11-01T10:30:00Z",
"changed": "2025-11-08T14:20:00Z"
}
]
}
Ingredient Summary Fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique ingredient identifier |
name | string | Ingredient name |
category | string | Category (Dairy, Sugar, Fat, etc.) |
source | string | “Default”, “Personal”, or “Modified Default” |
isOverride | boolean | True if this is a modified default ingredient |
isRecipeDerived | boolean | True if created from a recipe |
Example (curl)
curl -H "X-API-Key: icc_your_key" \
https://icecreamcalc.com/api/ingredients
GET /api/ingredients/{id}
Retrieve complete details for a single ingredient including all nutritional data and ice cream properties.
Request
GET /api/ingredients/1
Headers:
X-API-Key: icc_your_api_key_here
Response (200 OK)
{
"success": true,
"ingredient": {
"id": 1,
"name": "Whole Milk",
"category": "Dairy",
"info": "Fresh whole milk",
"source": "Default",
"isOverride": false,
// Nutritional data (per 100g)
"water": 87.5,
"totalFat": 3.5,
"saturatedFat": 2.1,
"protein": 3.3,
"carbohydrates": 4.8,
"totalSugars": 4.8,
"lactose": 4.8,
// Ice cream specific
"msnf": 8.9,
"milkSolids": 12.4,
"milkProtein": 3.3,
"milkFat": 3.5,
"pac": 5.2,
"pod": 0.15,
// Allergens
"contains": ["Milk"],
"mayContain": [],
"created": "2024-01-01T00:00:00Z",
"changed": "2024-01-01T00:00:00Z"
}
}
Complete Ingredient Fields
Basic Information:
id,name,category,info,source
Nutritional Data (per 100g):
water,totalFat,saturatedFat,transFat,cholesterolsodium,salt,carbohydrates,fiber,totalSugarsprotein,alcohol,lactose,polyolsvitaminD,calcium,iron,potassium
Ice Cream Properties:
msnf– Milk solids non-fatmilkSolids– Total milk solidsmilkProtein– Milk protein contentmilkFat,cocoaFat,cocoaSolidspac– Freezing point depressionpod– Relative sweetnesshf– Hardening factorstabilizers,emulsifiers
Allergen Information:
contains– Array of allergens this ingredient containsmayContain– Array of potential cross-contamination allergens
Example (JavaScript)
fetch("https://icecreamcalc.com/api/ingredients/1", {
headers: {"X-API-Key": "icc_your_key"}
})
.then(r => r.json())
.then(data => {
const ing = data.ingredient;
console.log(`${ing.name}: ${ing.totalFat}g fat, ${ing.protein}g protein`);
console.log(`PAC: ${ing.pac}, POD: ${ing.pod}`);
});
Response Format
Success Response
All successful responses include a success field set to true:
{
"success": true,
// ... response data
}
Error Response
All error responses include success: false and error details:
{
"success": false,
"error": "Brief error message",
"details": "More detailed explanation"
}
HTTP Status Codes
| Code | Name | Meaning |
|---|---|---|
200 | OK | Request succeeded |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | You don’t have access to this resource |
404 | Not Found | Resource doesn’t exist |
500 | Server Error | Server-side error occurred |
Rate Limiting
Currently, there are no rate limits on the API. However, please use the API responsibly:
- Cache responses when appropriate
- Don’t make unnecessary repeated requests
- Implement exponential backoff for retries
- Be considerate of server resources
Note: Rate limiting may be introduced in the future if needed. We’ll provide advance notice if this changes.
Data Access Rules
What You Can Access
- ✅ Your own recipes (all types)
- ✅ Your personal ingredients
- ✅ Shared/default ingredients (public database)
- ✅ Your modified default ingredients (overrides)
What You Cannot Access
- ❌ Other users’ recipes
- ❌ Other users’ personal ingredients
- ❌ Temporary recipes (not accessible via API)
Best Practices
Security
- Always use HTTPS (required by the API)
- Store API keys in environment variables, not in code
- Never expose API keys in client-side JavaScript
- Regenerate your key if compromised
Performance
- Use
/api/recipes/{id}when you need one recipe, not/api/recipes - Use
/api/ingredientsfor browsing,/api/ingredients/{id}for details - Cache calculated data – it doesn’t change unless the recipe changes
- Handle errors gracefully with retry logic
Error Handling
try {
response = requests.get(url, headers=headers)
response.raise_for_status() # Raise exception for 4xx/5xx
data = response.json()
if not data.get('success'):
print(f"API Error: {data.get('error')}")
return None
return data
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
return None
Changelog
Version 1.0 (November 2025)
- Initial API release
- Recipe endpoints (list, single, calculated)
- Ingredient endpoints (list, single)
- API key authentication
Need Help?
- 📘 Getting Started Guide – Learn how to generate an API key and make your first request
- 🔬 API Test Page – Test endpoints interactively from your Account page
- 📧 Support – Contact us if you encounter issues
💡 Pro Tip: Use the API Test Page (accessible from your Account page) to explore endpoints and see example responses before writing code!