Coffee operations platform

From the contract to the cup. One system of record.

Green contracts, inventory, roasting, quality, planning, orders and cafés — in one data model that a generic ERP cannot express.

Every screen here is built on the same public API you get.

app.roastery.run/inventory
The green coffee list, showing four lots with their codes, weights and statuses — one available, one reserved, one quarantined.

Seven areas, one data model

The value is not any single feature. It is that a green lot, a roast batch, a cupping, a blend and an order are the same coffee, and the system knows it.

Coffee Inventory

An append-only ledger behind every weight, so a stock figure is auditable rather than merely plausible.

inventory.green.*

Resource Planning

Demand merged by what would be roasted together, sized to your drums, and sequenced so the day actually runs.

production.schedule.*

Roasting & QC

Live curves from any bridge, cupping panels that report the spread as well as the mean, and gradings that actually quarantine a lot.

production.roast.*

Order Fulfillment

First-expiry-first-out allocation, shortfalls reported as shortfalls, and orders that cannot be double-promised.

orders.*

Green Contracts

Contracts, positions and milestones, with landed cost derived from what you bought rather than typed in twice.

sourcing.contract.*

Café Intelligence

Every shot, judged per group head, with a channeling alert in seconds rather than on tomorrow's report.

cafe.*

Sample Management

Offers, pre-shipments and arrivals in one place, with the answer to how long you sat on a decision.

sourcing.sample.*

The API is not an afterthought

The console is just another client of the same /rpc/v1 surface you get. There is no screen that can do something the API cannot — that gap is structurally impossible here, because building one would mean building it twice.

curl -X POST https://api.roastery.run/rpc/v1/inventory.green.listGreenLots \
  -H "Authorization: Bearer $ROASTERY_API_KEY" \
  -H "X-Roastery-Org: $ORG_ID" \
  -d '{"filter":{"status":"available"},"page":{"limit":50}}'