Getting Started with the FoodFiles API: Build Your First Food Recognition App
A comprehensive tutorial on integrating FoodFiles' powerful food recognition and recipe generation APIs into your applications.

Your Journey into Food AI Starts Here
Whether you’re building a meal planning app, a restaurant menu analyzer, or the next big food social network, the FoodFiles API gives you superpowers. In this tutorial, we’ll build a simple web app that can identify any dish from a photo and generate personalized recipe variations.
Prerequisites
Before we dive in, you’ll need:
- Basic knowledge of JavaScript or Python
- A FoodFiles API key (sign up here)
- Node.js or Python 3.8+ installed
- A cup of coffee (optional but recommended)
Setting Up Your Environment
Step 1: Install the SDK
For JavaScript/Node.js:
npm install @foodfiles/sdk
For Python:
pip install foodfiles-sdk
Step 2: Initialize the Client
JavaScript:
import { FoodFilesClient } from '@foodfiles/sdk';
const client = new FoodFilesClient({
apiKey: process.env.FOODFILES_API_KEY,
// Optional: specify region for lower latency
region: 'us-west-2'
});
Python:
from foodfiles import FoodFilesClient
client = FoodFilesClient(
api_key=os.environ['FOODFILES_API_KEY'],
region='us-west-2' # Optional
)
Your First API Call: Analyzing a Food Image
Let’s start with the basics—analyzing a food photo:
JavaScript Example
async function analyzeFood(imagePath) {
try {
const result = await client.analyze({
image: imagePath,
// Optional parameters
includeNutrition: true,
includeIngredients: true,
language: 'en'
});
console.log('Dish identified:', result.dish.name);
console.log('Confidence:', result.dish.confidence);
console.log('Ingredients:', result.ingredients);
console.log('Nutrition:', result.nutrition);
return result;
} catch (error) {
console.error('Analysis failed:', error);
}
}
// Usage
const analysis = await analyzeFood('./images/pasta.jpg');
Python Example
def analyze_food(image_path):
try:
result = client.analyze(
image=image_path,
include_nutrition=True,
include_ingredients=True,
language='en'
)
print(f"Dish identified: {result['dish']['name']}")
print(f"Confidence: {result['dish']['confidence']}")
print(f"Ingredients: {result['ingredients']}")
print(f"Nutrition: {result['nutrition']}")
return result
except Exception as e:
print(f"Analysis failed: {e}")
# Usage
analysis = analyze_food('./images/pasta.jpg')
Building a Recipe Generator
Now let’s generate a recipe based on the analyzed dish:
JavaScript Implementation
async function generateRecipe(dishAnalysis, preferences) {
const recipe = await client.generateRecipe({
baseDish: dishAnalysis.dish.id,
preferences: {
dietary: preferences.dietary || [], // ['vegan', 'gluten-free']
skillLevel: preferences.skillLevel || 'intermediate',
timeLimit: preferences.timeLimit || 30, // minutes
servings: preferences.servings || 4
},
// Optional: use detected ingredients as base
useIngredients: dishAnalysis.ingredients.map(i => i.name)
});
return recipe;
}
// Generate a vegan version of the detected dish
const veganRecipe = await generateRecipe(analysis, {
dietary: ['vegan'],
timeLimit: 45,
servings: 2
});
console.log('Recipe:', veganRecipe.title);
console.log('Prep time:', veganRecipe.prepTime);
console.log('Instructions:', veganRecipe.instructions);
Python Implementation
async def generate_recipe(dish_analysis, preferences):
recipe = await client.generate_recipe(
base_dish=dish_analysis['dish']['id'],
preferences={
'dietary': preferences.get('dietary', []),
'skill_level': preferences.get('skill_level', 'intermediate'),
'time_limit': preferences.get('time_limit', 30),
'servings': preferences.get('servings', 4)
},
use_ingredients=[i['name'] for i in dish_analysis['ingredients']]
)
return recipe
# Generate a vegan version
vegan_recipe = await generate_recipe(analysis, {
'dietary': ['vegan'],
'time_limit': 45,
'servings': 2
})
print(f"Recipe: {vegan_recipe['title']}")
print(f"Prep time: {vegan_recipe['prep_time']}")
Advanced Features
Batch Processing
Process multiple images efficiently:
const images = ['burger.jpg', 'salad.jpg', 'soup.jpg'];
const results = await client.batchAnalyze({
images: images,
options: {
includeNutrition: true,
parallel: true // Process in parallel
}
});
results.forEach((result, index) => {
console.log(`${images[index]}: ${result.dish.name}`);
});
Real-time Streaming
For live cooking applications:
const stream = client.createStream({
onFrame: async (frame) => {
const result = await client.quickAnalyze(frame);
updateUI(result);
},
fps: 2 // Analyze 2 frames per second
});
// Start streaming from webcam
navigator.mediaDevices.getUserMedia({ video: true })
.then(mediaStream => stream.start(mediaStream));
Webhooks for Async Processing
For large-scale applications:
// Submit for processing
const job = await client.submitJob({
images: largeBatchOfImages,
webhook: 'https://your-app.com/webhook',
options: {
priority: 'high',
includeAll: true
}
});
// Your webhook will receive:
// POST /webhook
// {
// jobId: 'job_123',
// status: 'completed',
// results: [...]
// }
Building a Complete Web App
Let’s put it all together in a simple Express app:
import express from 'express';
import multer from 'multer';
import { FoodFilesClient } from '@foodfiles/sdk';
const app = express();
const upload = multer({ dest: 'uploads/' });
const client = new FoodFilesClient({ apiKey: process.env.FOODFILES_API_KEY });
// Analyze uploaded image
app.post('/analyze', upload.single('image'), async (req, res) => {
try {
const analysis = await client.analyze({
image: req.file.path,
includeNutrition: true,
includeIngredients: true
});
res.json({
success: true,
data: analysis
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
// Generate recipe from analysis
app.post('/generate-recipe', async (req, res) => {
try {
const { dishId, preferences } = req.body;
const recipe = await client.generateRecipe({
baseDish: dishId,
preferences: preferences
});
res.json({
success: true,
recipe: recipe
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
app.listen(3000, () => {
console.log('FoodFiles app running on port 3000');
});
Error Handling and Best Practices
Rate Limiting
Implement exponential backoff:
async function analyzeWithRetry(image, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await client.analyze({ image });
} catch (error) {
if (error.code === 'RATE_LIMIT_EXCEEDED') {
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}
Caching Results
Reduce API calls and improve performance:
import NodeCache from 'node-cache';
const cache = new NodeCache({ stdTTL: 3600 });
async function analyzeCached(imageHash) {
const cached = cache.get(imageHash);
if (cached) return cached;
const result = await client.analyze({ image: imageHash });
cache.set(imageHash, result);
return result;
}
Monitoring and Analytics
Track your API usage:
client.on('request', (event) => {
console.log('API Request:', {
endpoint: event.endpoint,
duration: event.duration,
credits: event.creditsUsed
});
});
// Get usage statistics
const usage = await client.getUsage({
startDate: '2025-06-01',
endDate: '2025-06-30'
});
console.log('Total requests:', usage.totalRequests);
console.log('Credits used:', usage.creditsUsed);
Next Steps
Congratulations! You’ve learned the basics of the FoodFiles API. Here are some ideas for what to build next:
- Recipe Social Network: Let users share and remix recipes
- Meal Planner: Generate weekly meal plans based on dietary goals
- Restaurant Menu Analyzer: Help restaurants optimize their menus
- Grocery List Generator: Create shopping lists from meal photos
- Nutrition Tracker: Track daily nutrition from food photos
Resources
Get Help
Running into issues? We’re here to help:
- 📧 Email: developers@foodfiles.app
- 💬 Discord: Join our community
- 🐛 Issues: GitHub Issues
Happy coding, and may your apps be as delicious as the food they analyze! 🍕🤖