๐ŸฅคBevFacts
Developer API

Put a nutrition label
on every order

Compute Dynamic Beverage Nutrition Facts for the exact drink a customer ordered โ€” from your POS, kiosk, or ordering app. The engine runs in the browser today; a hosted REST API is on the way.

What you can build

One engine, three integration surfaces

โšก

In-browser JS engine Live

Drop in engine.js and call window.BevFacts โ€” compute, round, declare, and render labels with zero network calls.

๐Ÿ”—

URL deep links Live

Encode a whole drink into a shareable link or QR code. Scannable by any phone, resolvable with no backend.

๐Ÿ›ฐ๏ธ

REST API Draft

Compute and persist labels server-side, render PNG/SVG, and pull vendor recipe tables over HTTP.

๐Ÿ””

Webhooks Draft

Subscribe to cup.returned and label.created events with signed, replay-protected payloads.

๐Ÿ—„๏ธ

Open recipe data Draft

Publish and consume base recipes, milks, syrups, and toppings as machine-readable JSON.

๐Ÿงพ

No keys client-side

The browser surfaces need no credentials โ€” keep API keys server-side, exactly where they belong.

Quickstart

Compute a label in three lines

The engine is a single static file with no dependencies. Everything below runs on this very page โ€” open your console and try it.

<script src="engine.js"></script>
<script>
  // Base recipe + the modifiers the customer ordered
  const order = {
    drinkName: "Caramel Latte",
    calories: 250, sugars: 33, addedSugars: 28, caffeine: 150,
    totalFat: 7, satFat: 4.5, sodium: 170, totalCarb: 35, protein: 10,
    sweetness: 100, pumps: 3, shots: 2          // +3 syrup pumps, +2 espresso shots
  };

  const facts    = BevFacts.compute(order);     // unrounded, as-ordered
  const declared = BevFacts.declare(facts);     // 21 CFR 101.9 rounded strings
  const warnings = BevFacts.warnings(facts);    // e.g. ["added_sugars_over_100pct_dv"]
  const link     = BevFacts.link(order);        // shareable deep link / QR target
</script>

Live playground

Run the engine now

Edit the order JSON and press Run. This calls the real window.BevFacts API loaded on this page โ€” the same code your integration would ship.

Order (JSON)

Result


        

Rendered label

Reference

The window.BevFacts API

MemberSignatureReturns
versionstringSpec version, e.g. "1.0-draft"
DVobjectDaily-value table (added sugars 50, sodium 2300, โ€ฆ)
PRESETSarrayExample base recipes
compute(order)(state) โ†’ nutrientsUnrounded as-ordered vector (sweetness, pumps, shots applied)
declare(nutrients)(nutrients) โ†’ stringsFDA-rounded declaration strings + %DV
warnings(nutrients)(nutrients) โ†’ string[]Machine-readable warning flags
round{calories, fat, โ€ฆ}The individual 21 CFR 101.9 rounding functions
labelHTML(order)(state) โ†’ stringInner HTML of a ready-to-style Nutrition Facts label
link(order)(state) โ†’ stringA deep-link URL encoding the whole order

Draft ยท hosted API

REST for server-side integrations

The wire format is specified and stable enough to build against; endpoints are not yet hosted. Full details โ€” auth, idempotency, pagination, webhooks, and errors โ€” live in Part 5 of the spec.

EndpointPurpose
POST /v1/labelsCompute & optionally render a label (PNG / SVG / JSON)
GET /v1/labels/{id}Retrieve a computed label document by id or hash
GET /v1/presetsList a vendor's published base recipes
GET /v1/cups/{id}Deposit / return state for a reusable cup
POST /v1/cups/{id}/returnRecord a return scan; emit cup.returned
curl https://api.bevfacts.example/v1/labels \
  -H "Authorization: Bearer bf_live_โ€ฆ" \
  -H "Content-Type: application/json" \
  -d '{ "drink": { "name": "Caramel Latte", "servingSize": { "amount": 16, "unit": "fl_oz", "ml": 473 } },
        "base": { "calories": 250, "sugars_g": 33, "addedSugars_g": 28, "caffeine_mg": 150 },
        "modifiers": [ { "type": "syrup_pump", "count": 3 }, { "type": "espresso_shot", "count": 2 } ],
        "render": ["png", "json"] }'

Want the hosted API, webhooks, or an SDK for your stack?

The REST surface, event signatures, and cup-return lifecycle are specified in the open. Follow along or weigh in via GitHub, or read the full API specification.