CoCoffee

Recipes as open data

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.

Endpoint

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.

Schema

JSON Schema (draft 2020-12): https://cocoffee.app/recipe.schema.json. schema_version only changes on breaking changes; new fields are additive.

Example (trimmed)

{
  "$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}
}

What's inside

coffeethe bag as read from the label: roaster, name, origin (+ ISO code), process, roast level, roast intent (filter / espresso / omni), tasting notes, decaf
grindtarget 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 / americanomanual recipes: dose, water, temperature, timed pours or steps, notes
methods.xbloomphases with water, flow, hold, temperature, agitation — what our xBloom share link is built from
methods.aiden / es1the exact Fellow Aiden and Espresso One profiles we mint to brew.link
device_linksready links when a user already opened that device; null otherwise

Mapping to a machine

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.

License and fair use

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.