Node.js guide
Food Search with Node.js
A thin Node.js client around the search endpoints gives every service in your stack one quota-friendly path to food data. This guide covers the client, pagination, an in-memory cache, and retry behavior that respects the rate-limit headers.
A minimal typed client
calorieApi.js
const API_BASE = 'https://calorieapiadmin.com/api/v1'
async function apiGet(path, params = {}) {
const url = new URL(API_BASE + path)
for (const [k, v] of Object.entries(params)) {
if (v !== undefined) url.searchParams.set(k, String(v))
}
const res = await fetch(url, {
headers: { 'X-API-Key': process.env.CALORIE_API_KEY },
})
if (res.status === 429) {
const reset = res.headers.get('X-RateLimit-Reset')
throw new RateLimitError(reset)
}
if (!res.ok) throw new ApiError(res.status, await res.text())
return res.json()
}
exports.searchFoods = (q, { limit = 30, skip = 0, verifiedOnly = false } = {}) =>
apiGet('/search/foods', { q, limit, skip, verified_only: verifiedOnly })
exports.getFood = (id) => apiGet(`/foods/${id}`)
exports.lookupBarcode = (upc) => apiGet(`/search/barcode/${upc}`)Pagination
Search returns a paginated envelope (data, total, skip, limit). Page with skip/limit and stop when skip + data.length reaches total, limit maxes out at 100 per request.
Cache before you retry
Cached food details
const details = new Map()
async function getFoodCached(id) {
if (details.has(id)) return details.get(id)
const food = await getFood(id)
details.set(id, food) // IDs are stable, cache aggressively
return food
}Respecting rate limits
- On 429, wait until X-RateLimit-Reset before retrying; add jitter when many workers share the account.
- Treat 402 (monthly quota) as terminal: alert and stop retrying.
- Batch jobs should iterate over your users’ actual foods, not the whole catalog.
Frequently asked questions
Should each microservice get its own API key?
Keys share the account’s limits either way, but separate keys per service make dashboards and revocation cleaner. Rate limits apply per account, not per key.
How do I avoid hitting the coverage cap in batch jobs?
Only fetch foods your users actually reference and cache by ID. The 5% monthly cap on distinct foods exists to block catalog scraping, not normal batch processing.
