Every coffee CoCoffee has read gets a public page — and the same recipe as JSON, under CC0. Take it, map it to your machine, build on it. No key, no sign-up.
curl https://cocoffee.app/v1/recipes/<coffee_id>.json
The coffee_id is the last segment of a share link (https://cocoffee.app/c/<coffee_id>).
Responses are cached for five minutes; add ?src=yourapp so we can see who's brewing with the data.
JSON Schema (draft 2020-12): https://cocoffee.app/recipe.schema.json.
schema_version only changes on breaking changes; new fields are additive.
{
"$schema": "https://cocoffee.app/recipe.schema.json",
"schema_version": "1.0",
"id": "kX9…",
"url": "https://cocoffee.app/c/kX9…",
"license": "CC0-1.0",
"coffee": {
"roaster": "Svit Kavy", "name": "Ethiopia Yirgacheffe Konga",
"origin": "Ethiopia", "origin_iso2": "ET", "process": "washed",
"roast_level": "light", "roast_intent": "filter",
"tasting_notes": ["jasmine", "lemon", "bergamot", "black tea"]
},
"grind": {
"single": {"microns": 720, "settings": {"ode_gen2": "5.1", "opus": "6", "ode_ssp": "4.2"}},
"espresso": {"microns": 250, "settings": {"niche": 14.5, "df64": 12.0, "eureka": 2.5}}
},
"methods": {
"v60": {"dose_g": 15, "water_g": 250, "water_temp_c": 94, "bloom": {…}, "pours": [{…}]},
"aeropress": {"style": "standard", "dose_g": 12, "water_g": 200, "steps": [{…}]},
"espresso": {"dose_g": 18, "yield_g": 40, "time_s": 28, "water_temp_c": 93, "pressure_bar": 9},
"xbloom": {"dose_g": 15, "water_g": 240, "phases": [{…}]},
"aiden": {"ratio": 16, "bloomTemperature": 96, "ssPulsesNumber": 3, "…": "…"},
"es1": {"dose": 18, "ratio": 2.2, "temperature": 93, "infusion": [{…}], "…": "…"}
},
"device_links": {"aiden": "https://brew.link/p/…", "es1": null, "xbloom": null}
}
| coffee | the bag as read from the label: roaster, name, origin (+ ISO code), process, roast level, roast intent (filter / espresso / omni), tasting notes, decaf |
| grind | target particle size in µm for single cup, batch and espresso, plus dial positions for common grinders (Ode Gen 2, Opus, Niche, DF64, Eureka) |
| methods.v60 / aeropress / espresso / americano | manual recipes: dose, water, temperature, timed pours or steps, notes |
| methods.xbloom | phases with water, flow, hold, temperature, agitation — what our xBloom share link is built from |
| methods.aiden / es1 | the exact Fellow Aiden and Espresso One profiles we mint to brew.link |
| device_links | ready links when a user already opened that device; null otherwise |
Our own integrations are mappers from this shape: methods.aiden → Fellow brew.link profile,
methods.es1 → Espresso One, methods.xbloom → xBloom recipe. A new machine is one more
mapper. Building one? hello@cocoffee.app — we'll link it from here.
Recipes are CC0-1.0: no attribution required, though “recipe by CoCoffee” with a link back is appreciated. Bag names and roaster names belong to the roasters. Please keep to a few requests per second and cache what you fetch.
☕ Made with CoCoffee — scan a bag, brew it right.