Code Examples
Ready-to-use code examples for common use cases in curl, Python, and JavaScript.
curl Examples
Basic text estimation
curl -X POST https://api.macroestimator.com/v1/estimate/sync \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": "2 eggs, 2 slices of bacon, and a slice of toast with butter"
}
]
}'Upload and estimate from image
# First, upload the image
IMAGE_URL=$(curl -s -X POST https://api.macroestimator.com/v1/upload/base64 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{
"image": "data:image/jpeg;base64,$(base64 -i meal.jpg)"
}" | jq -r '.url')
# Then estimate from the image
curl -X POST https://api.macroestimator.com/v1/estimate/sync \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "$IMAGE_URL"
}
},
{
"type": "text",
"text": "What are the macros?"
}
]
}
]
}"Search foods database
curl "https://api.macroestimator.com/v1/foods?q=grilled%20salmon&limit=5" \
-H "Authorization: Bearer YOUR_API_KEY"Create a custom recipe
curl -X POST https://api.macroestimator.com/v1/recipes \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "My Post-Workout Shake",
"calories": 450,
"protein": 40,
"carbs": 55,
"fat": 8,
"serving_description": "1 shake (24oz)",
"aliases": ["protein shake", "workout shake", "PWO shake"]
}'Python Examples
Basic estimation with error handling
import requests
from typing import Optional
class MacroEstimator:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.macroestimator.com"
def estimate(self, description: str) -> Optional[dict]:
"""Estimate nutrition from a text description."""
try:
response = requests.post(
f"{self.base_url}/v1/estimate/sync",
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
},
json={
"messages": [
{"role": "user", "content": description}
]
},
timeout=30
)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f"Error: {e}")
return None
# Usage
client = MacroEstimator("YOUR_API_KEY")
result = client.estimate("chicken caesar salad with croutons")
if result:
print(f"Total calories: {result['totals']['calories']}")
print(f"Protein: {result['totals']['protein']}g")
print(f"Carbs: {result['totals']['carbs']}g")
print(f"Fat: {result['totals']['fat']}g")
print("\nBreakdown:")
for item in result["items"]:
print(f" - {item['name']}: {item['calories']} cal")Image upload and estimation
import requests
import base64
from pathlib import Path
class MacroEstimator:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.macroestimator.com"
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def upload_image(self, image_path: str) -> str:
"""Upload an image and return the URL."""
image_data = Path(image_path).read_bytes()
b64_data = base64.b64encode(image_data).decode()
# Detect content type
suffix = Path(image_path).suffix.lower()
content_type = {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".webp": "image/webp"
}.get(suffix, "image/jpeg")
response = requests.post(
f"{self.base_url}/v1/upload/base64",
headers=self.headers,
json={"image": f"data:{content_type};base64,{b64_data}"}
)
response.raise_for_status()
return response.json()["url"]
def estimate_from_image(self, image_path: str, prompt: str = "What are the macros?") -> dict:
"""Upload an image and get nutrition estimate."""
image_url = self.upload_image(image_path)
response = requests.post(
f"{self.base_url}/v1/estimate/sync",
headers=self.headers,
json={
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"url": image_url}
},
{"type": "text", "text": prompt}
]
}
]
}
)
response.raise_for_status()
return response.json()
# Usage
client = MacroEstimator("YOUR_API_KEY")
result = client.estimate_from_image("lunch.jpg", "Estimate the macros for this meal")
print(f"Total: {result['totals']['calories']} calories")Managing recipes
import requests
class RecipeManager:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.macroestimator.com/v1/recipes"
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def list_recipes(self) -> list:
"""Get all saved recipes."""
response = requests.get(self.base_url, headers=self.headers)
response.raise_for_status()
return response.json()["recipes"]
def create_recipe(self, name: str, calories: int, protein: int,
carbs: int, fat: int, **kwargs) -> dict:
"""Create a new recipe."""
data = {
"name": name,
"calories": calories,
"protein": protein,
"carbs": carbs,
"fat": fat,
**kwargs
}
response = requests.post(self.base_url, headers=self.headers, json=data)
response.raise_for_status()
return response.json()
def delete_recipe(self, recipe_id: str) -> bool:
"""Delete a recipe."""
response = requests.delete(
f"{self.base_url}/{recipe_id}",
headers=self.headers
)
return response.status_code == 200
# Usage
recipes = RecipeManager("YOUR_API_KEY")
# Create a recipe
new_recipe = recipes.create_recipe(
name="Homemade Granola",
calories=280,
protein=6,
carbs=42,
fat=10,
serving_description="1/2 cup",
aliases=["granola", "my granola"]
)
print(f"Created: {new_recipe['id']}")
# List all recipes
for recipe in recipes.list_recipes():
print(f"- {recipe['name']}: {recipe['calories']} cal")JavaScript Examples
Basic estimation with TypeScript types
interface EstimateItem {
name: string;
quantity: number;
unit: string;
calories: number;
protein: number;
carbs: number;
fat: number;
}
interface EstimateResponse {
items: EstimateItem[];
totals: {
calories: number;
protein: number;
carbs: number;
fat: number;
};
}
class MacroEstimator {
private apiKey: string;
private baseUrl = "https://api.macroestimator.com";
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async estimate(description: string): Promise<EstimateResponse> {
const response = await fetch(`${this.baseUrl}/v1/estimate/sync`, {
method: "POST",
headers: {
"Authorization": `Bearer ${this.apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
messages: [{ role: "user", content: description }]
})
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return response.json();
}
}
// Usage
const client = new MacroEstimator("YOUR_API_KEY");
const result = await client.estimate("grilled cheese sandwich with tomato soup");
console.log(`Total: ${result.totals.calories} calories`);
result.items.forEach(item => {
console.log(` ${item.name}: ${item.calories} cal`);
});Streaming response handling
async function* streamEstimate(
apiKey: string,
description: string
): AsyncGenerator<string> {
const response = await fetch(
"https://api.macroestimator.com/v1/estimate",
{
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
messages: [{ role: "user", content: description }]
})
}
);
if (!response.body) {
throw new Error("No response body");
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
yield chunk;
}
}
// Usage
async function main() {
for await (const chunk of streamEstimate("YOUR_API_KEY", "spaghetti and meatballs")) {
process.stdout.write(chunk);
}
}
main();React hook for estimation
import { useState, useCallback } from "react";
interface UseEstimateResult {
estimate: (description: string) => Promise<void>;
result: EstimateResponse | null;
loading: boolean;
error: string | null;
}
export function useEstimate(apiKey: string): UseEstimateResult {
const [result, setResult] = useState<EstimateResponse | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const estimate = useCallback(async (description: string) => {
setLoading(true);
setError(null);
try {
const response = await fetch(
"https://api.macroestimator.com/v1/estimate/sync",
{
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
messages: [{ role: "user", content: description }]
})
}
);
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
const data = await response.json();
setResult(data);
} catch (err) {
setError(err instanceof Error ? err.message : "Unknown error");
} finally {
setLoading(false);
}
}, [apiKey]);
return { estimate, result, loading, error };
}
// Usage in a component
function NutritionEstimator() {
const { estimate, result, loading, error } = useEstimate("YOUR_API_KEY");
const [input, setInput] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
estimate(input);
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Describe your meal..."
/>
<button type="submit" disabled={loading}>
{loading ? "Estimating..." : "Estimate"}
</button>
</form>
{error && <p className="error">{error}</p>}
{result && (
<div>
<h3>Total: {result.totals.calories} calories</h3>
<ul>
{result.items.map((item, i) => (
<li key={i}>
{item.name}: {item.calories} cal,
{item.protein}g protein,
{item.carbs}g carbs,
{item.fat}g fat
</li>
))}
</ul>
</div>
)}
</div>
);
}Error Handling
Here is an example of comprehensive error handling:
import requests
from requests.exceptions import RequestException, Timeout, HTTPError
def safe_estimate(api_key: str, description: str) -> dict:
"""Make an API request with comprehensive error handling."""
try:
response = requests.post(
"https://api.macroestimator.com/v1/estimate/sync",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
json={"messages": [{"role": "user", "content": description}]},
timeout=30
)
# Check rate limits
remaining = response.headers.get("X-RateLimit-Remaining")
if remaining and int(remaining) < 10:
print(f"Warning: Only {remaining} requests remaining")
response.raise_for_status()
return response.json()
except Timeout:
print("Request timed out. Please try again.")
return {"error": "timeout"}
except HTTPError as e:
if e.response.status_code == 401:
print("Invalid API key")
elif e.response.status_code == 429:
retry_after = e.response.headers.get("Retry-After", "60")
print(f"Rate limited. Retry after {retry_after} seconds")
elif e.response.status_code >= 500:
print("Server error. Please try again later.")
else:
print(f"HTTP error: {e.response.status_code}")
return {"error": str(e)}
except RequestException as e:
print(f"Network error: {e}")
return {"error": "network"}
# Usage
result = safe_estimate("YOUR_API_KEY", "turkey sandwich")
if "error" not in result:
print(f"Calories: {result['totals']['calories']}")