Recipes

Common patterns, ready to copy-paste.

Real working snippets. Drop in your sk_live_* key and run.

Search restaurants by city

Most common starting point. POST to /v1/search/restaurants with a query and optional state / cuisine filters.

const res = await fetch(
"https://api.sendside.xyz/v1/search/restaurants",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SOUSLAB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
q: "ramen",
state: "OR",
limit: 10,
}),
},
);
const { data, pagination } = await res.json();
console.log(`${data.length} of ${pagination.total_estimated}`);

Get a full menu by restaurant ID

Once you have a restaurant_id (from search), pull the normalized menus → sections → items in one call.

curl https://api.sendside.xyz/v1/restaurants/01KQQ8EZ3VM7FCTFVY9CWQ647X/menu \
-H "Authorization: Bearer $SOUSLAB_API_KEY" \
| jq '.data.menus[] | { menu: .menu_name, sections: (.sections | length) }'

Track Chipotle (CMG) prices by metro

Look up the chain by ticker, fetch its canonical menu items, then aggregate one item's prices by metro across all locations. The full path needed for a chain-level price tape.

import os, requests
auth = {"Authorization": f"Bearer {os.environ['SOUSLAB_API_KEY']}"}
# 1. Find the chain by ticker
chains = requests.get(
"https://api.sendside.xyz/v1/chains",
headers=auth, params={"ticker": "CMG"},
).json()
cmg = chains["data"][0]
print(cmg["display_name"], cmg["location_count"], "locations")
# 2. Get the canonical (chain-wide) menu items
items = requests.get(
f"https://api.sendside.xyz/v1/chains/{cmg['chain_id']}/canonical-items",
headers=auth,
).json()["data"]["items"]
# 3. Find the burrito and aggregate prices by metro
burrito = next(i for i in items if "Burrito" in i["canonical_name"])
summary = requests.get(
f"https://api.sendside.xyz/v1/chains/{cmg['chain_id']}/price-summary",
headers=auth,
params={
"canonical_item_id": burrito["canonical_item_id"],
"group_by": "metro",
},
).json()["data"]
for g in sorted(summary["groups"], key=lambda r: r["price_median"] or 0):
print(f"{g['group_key']}: ${g['price_median']:.2f} (n={g['location_count']})")

Build a foodservice CPI proxy from price-history

Pull the price-history feed for a basket of items at a chain and compute a chain-level inflation index. Useful for alt-data and category-level pricing analysis.

import os, statistics, requests
from datetime import datetime, timedelta
auth = {"Authorization": f"Bearer {os.environ['SOUSLAB_API_KEY']}"}
six_months_ago = (datetime.utcnow() - timedelta(days=180)).isoformat() + "Z"
# Replace these with item_uids from /v1/restaurants/{id}/menu or /v1/search/items
basket_uids = [
"9b2c1a4f8e6d3b7a5c9d8e6f1a2b3c4d",
# ...
]
deltas = []
for uid in basket_uids:
r = requests.get(
f"https://api.sendside.xyz/v1/items/{uid}/price-history",
headers=auth,
params={"since": six_months_ago, "limit": 100},
).json()
events = r["data"]["events"]
if len(events) < 2:
continue
pct = (events[0]["price"] - events[-1]["price"]) / events[-1]["price"]
deltas.append(pct)
print(f"6-month median price change: {statistics.median(deltas) * 100:.2f}%")

Find restaurants serving a specific dish

POST /v1/search/items finds menu items across the corpus. Group by restaurant_id in your code to surface places.

import os, requests
from collections import Counter
r = requests.post(
"https://api.sendside.xyz/v1/search/items",
headers={"Authorization": f"Bearer {os.environ['SOUSLAB_API_KEY']}"},
json={"q": "carbonara", "state": "CA"},
)
restaurants = Counter(item["restaurant_id"] for item in r.json()["data"])
for rid, count in restaurants.most_common(5):
print(rid, count, "carbonara variants")

Build a city-level price map

Combine /v1/stats/{state}/{city} across multiple cities to chart price-per-entrée by metro.

const cities = [
["NY", "new york"],
["CA", "san francisco"],
["IL", "chicago"],
["TX", "austin"],
];
const auth = { Authorization: `Bearer ${process.env.SOUSLAB_API_KEY}` };
const stats = await Promise.all(
cities.map(async ([state, city]) => {
const r = await fetch(
`https://api.sendside.xyz/v1/stats/${state}/${encodeURIComponent(city)}`,
{ headers: auth },
);
const { data } = await r.json();
return data;
}),
);
stats.sort((a, b) => a.p50_price - b.p50_price);
console.table(stats.map(s => ({ city: s.city, p50: s.p50_price })));