UCSB macros

Gaucho REST API

Dining menus, serving sizes, macros, and full nutrition labels from gaucho.mihir-s.com. Public JSON endpoints. No API key.

https://gaucho.mihir-s.com/api/v1

Endpoints

GETReturnsParameters
/hallsDining locations and sectionsNone
/menusPublished dates, meals, and menu IDshall; optional section, date
/menuAll foods on a menu, with serving sizes and macroshall; optional section, date, meal, menu, search
/itemOne food’s macros and source menuhall, item; optional section, date, meal, menu
/labelThe food plus full NetNutrition label HTMLSame as /item
/healthSnapshot timestamp, age, and freshnessNone

hall, section, and item accept an ID, an exact name, or a unique substring. For example, hall=Portola and hall=15 select the same location.

The section defaults to the daily menu, and the date defaults to today in California. The meal defaults to Lunch. Use /menus to discover Brunch and other available meals. A menu ID overrides date and meal selection. Everyday sections, such as Salad Bar, select their everyday menu.

Examples

curl "https://gaucho.mihir-s.com/api/v1/halls"
curl "https://gaucho.mihir-s.com/api/v1/menus?hall=Portola"
curl "https://gaucho.mihir-s.com/api/v1/menu?hall=Portola&meal=Lunch"
curl "https://gaucho.mihir-s.com/api/v1/menu?hall=Carrillo&section=Salad%20Bar"

Find a published menu, then request its foods:

const base = "https://gaucho.mihir-s.com/api/v1";
const choices = await fetch(`${base}/menus?hall=Portola`).then(r => r.json());
const menu = choices.menus.find(m => m.meal === "Lunch") ?? choices.menus[0];
const params = new URLSearchParams({
  hall: "Portola", menu: String(menu.id), search: "chicken"
});
const response = await fetch(`${base}/menu?${params}`);
const data = await response.json();
if (!response.ok) throw new Error(data.error);
console.log(data.items);

Try a request

/api/v1/menus?hall=Portola

Select an endpoint and send a request.

Response fields

FieldMeaning
items / itemMenu foods, or the requested food.
servingThe serving size printed on the original label.
caloriesCalories per listed serving.
protein_g, carbs_g, fat_gGrams per listed serving.
fiber_g, sugar_g, sodium_mgFiber and sugar in grams, sodium in milligrams, per listed serving.
macro_displayOriginal display values, including <1. Unknown numeric values are null.
label_fetched_atWhen the food’s label was collected. Future and everyday labels may be reused for up to 24 hours.
snapshotid, collected_at, published_at, age_seconds, and stale.
documentFull label HTML from /label, including ingredients and source styles. Render it in a sandboxed iframe.

Menus refresh every six hours. Successful JSON responses cache for 60 seconds. A snapshot older than 12 hours has stale: true. Compare snapshot IDs when combining several responses; retry if they differ.

Errors and access

Errors return {"error":"…"}. 400 means invalid input, 404 means unavailable data, 409 means an ambiguous name or a snapshot change, and 503 means a temporary service issue. Ambiguous names include a choices array; use an exact name or ID.

GET, HEAD, and OPTIONS are supported. Cross-origin browser requests are allowed. Writes return 405. Personal saved plans stay in the browser.

Existing endpoints used by the meal planner

/api/catalog, /api/options?hall=15&section=16, /api/menu?hall=15&section=16&menu=…, /api/label?hall=15&section=16&menu=…&item=…, and /api/health remain available.