Last Updated: 2025-11-29
API Base URL: https://data.cambeerfestival.app
Purpose: Documentation for multi-festival and multi-beverage-type support
The Cambridge Beer Festival Data API provides structured beverage and producer data for multiple festivals in JSON format. This API enables the app to support multiple festivals and multiple beverage types.
| Festival Code | Full Name | Years Available | Notes |
|---|---|---|---|
| cbf | Cambridge Beer Festival | cbf2023, cbf2024, cbf2025 | Main annual festival |
| cbfw | Cambridge Beer Festival Winter | cbfw2018, cbfw2019, cbfw2025 | Winter variant |
https://data.cambeerfestival.app/{festival_code}/{beverage_type}.json
https://data.cambeerfestival.app/cbf2025/beer.json
https://data.cambeerfestival.app/cbf2025/cider.json
https://data.cambeerfestival.app/cbfw2025/beer.json
| Beverage Type | Filename | Description |
|---|---|---|
| Beer | beer.json |
Domestic beer offerings |
| International Beer | international-beer.json |
Foreign/imported beers |
| Cider | cider.json |
Apple ciders |
| Mead | mead.json |
Honey wines |
| Perry | perry.json |
Pear ciders |
| Wine | wine.json |
Wines |
| Apple Juice | apple-juice.json |
Non-alcoholic apple juice |
| Low/No Alcohol | low-no.json |
Low or no-alcohol beverages |
| Beverage Type | Filename | Description |
|---|---|---|
| Beer | beer.json |
Winter beer offerings |
| Low/No Alcohol | low-no.json |
Low or no-alcohol beverages |
Note: Different festivals may offer different beverage types. Always check the festival configuration before attempting to fetch specific beverage types.
All beverage types follow the same consistent JSON structure with a two-level hierarchy:
- Producers (breweries, cideries, meaderies, wineries)
- Products (individual beverages)
{
"timestamp": "2025-05-24T00:01:00Z",
"producers": [ /* array of producer objects */ ]
}| Field | Type | Description |
|---|---|---|
timestamp |
string (ISO 8601) | Last update time for this dataset |
producers |
array | Array of producer objects (see below) |
Each producer (brewery, cidery, etc.) contains:
{
"name": "All Day",
"location": "Reepham, Norfolk",
"id": "632047e5b2a712a7707f6b28ac722b1e706f1589",
"year_founded": 2014,
"notes": "Reepham, Norfolk est. 2014",
"products": [ /* array of product objects */ ]
}| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Producer name |
location |
string | Yes | Geographic location |
id |
string | Yes | Unique identifier (SHA-1 hash) |
year_founded |
integer | No | Year the producer was established |
notes |
string | No | Additional information about the producer |
products |
array | Yes | Array of product objects (beverages) |
Each product (individual beverage) contains:
{
"name": "Let's Cask - Strong Golden Ale",
"id": "3e908babc017695281dc1f9887be46c6ffb9e0a3",
"category": "beer",
"style": "Golden Ale",
"dispense": "cask",
"abv": "5.4",
"notes": "Heritage Range - Crisp Heritage malts and a massive whack of fresh Goldings...",
"status_text": "Plenty left",
"bar": "Arctic",
"allergens": {"gluten": 1}
}| Field | Type | Required | Description | Example Values |
|---|---|---|---|---|
name |
string | Yes | Product name | "Let's Cask - Strong Golden Ale" |
id |
string | Yes | Unique identifier (SHA-1 hash) | "3e908babc017..." |
category |
string | Yes | Beverage category | "beer", "cider", "mead", "foreign beer" |
abv |
string/number | Yes | Alcohol by volume (%) | "5.4", "8.4", "14.5" |
dispense |
string | Yes | Serving method | See dispense methods below |
style |
string | No | Style/variety | "Golden Ale", "IPA", "Dry" |
notes |
string | No | Flavor description | "Crisp Heritage malts..." |
status_text |
string | No | Availability status | "Plenty left", "Arrived" |
bar |
string/boolean | No | Venue/location | "Arctic", "Main Bar", true/false |
is_vegan |
boolean/integer/string | No | Vegan suitability | true, false, 1, 0, "yes" |
allergens |
object | No | Allergen flags | {"gluten": 1, "sulphites": 1} |
Common values for the dispense field:
| Value | Description | Common For |
|---|---|---|
cask |
Traditional cask ale | Beer |
keg |
Standard keg | Beer |
keykeg |
KeyKeg (pressurized) | Beer, low-no |
bottle |
Bottled | International beer, mead, wine |
cider tub |
Cider serving vessel | Cider, perry |
mead polypin |
Mead container | Mead |
The allergens object uses numeric/boolean flags (1/true = present):
"allergens": {
"gluten": 1,
"sulphites": 1
}Common allergens:
glutensulphites
Note: An empty object {} means no allergens listed.
| Feature | beer.json | international-beer.json |
|---|---|---|
| Category value | "beer" | "foreign beer" |
| Location tracking | UK-focused | Global (15+ countries) |
| Status field | Less common | "Arrived" tracking |
| Dispense | Cask-heavy | Bottle/keg-heavy |
stylefield often nulldispensetypically "cider tub"- Focus on sweetness/dryness in notes
dispensetypically "bottle" or "mead polypin"- Higher ABV range (10-17%)
- Common allergen: sulphites
- Traditional wine categories
- Bottle dispense
- Wine-specific styling
- ABV typically < 0.5%
- Various dispense methods
- Mixed beverage types (beer-style, cider-style)
curl https://data.cambeerfestival.app/cbf2025/beer.jsoncurl https://data.cambeerfestival.app/cbf2025/cider.jsoncurl https://data.cambeerfestival.app/cbfw2025/beer.jsonThis Flutter app maps the API data to Dart models as follows:
Producer.fromJson(json) → {
id: json['id'],
name: json['name'],
location: json['location'],
yearFounded: json['year_founded'], // Handles int or String
notes: json['notes'],
products: json['products'].map(Product.fromJson),
}Product.fromJson(json) → {
id: json['id'],
name: json['name'],
category: json['category'],
style: json['style'],
dispense: json['dispense'],
abv: parseDouble(json['abv']), // Handles String or number
notes: json['notes'],
statusText: json['status_text'],
bar: json['bar'], // Handles String, int, or boolean
vegan: json['is_vegan'] ?? json['vegan'], // Handles bool, int, or String; 'vegan' is legacy fallback
allergens: parseAllergens(json['allergens']), // Handles int, bool, or num
}- ABV can be
String,int, ordouble - Allergens values can be
int,bool, ornum - Year founded can be
intorString - Bar can be
String,int, orboolean - is_vegan can be
bool,int/num, orString("yes"/"no"/"true"/"false"/"1"/"0"); legacy keyveganis also supported as a fallback - Handle null values gracefully with
?.and??
| Status Code | Meaning | Action |
|---|---|---|
| 200 | Success | Parse response |
| 404 | Not found | Festival or beverage type not available |
| 5xx | Server error | Retry with backoff |
- Check JSON structure before parsing
- Validate required fields present
- Handle malformed data gracefully
Update Schedule: Data files are typically updated:
- Before festival start (finalized lineup)
- During festival (status_text changes for "sold out", etc.)
- May be updated multiple times during festival
Caching Strategy:
- Check timestamp field for data freshness
- Re-fetch if timestamp changed
- Consider TTL of 1-4 hours during festival
- Longer TTL (24h) outside festival dates
- No API Key Required - Public access
- No Rate Limiting Observed - Be respectful with requests
- No Versioning - API structure may change
- No Pagination - Full datasets in single response
- No Filtering - Must fetch full file and filter client-side
- No Real-time Updates - Static JSON files, not live API
{
"timestamp": "2025-05-24T00:01:00Z",
"producers": [
{
"name": "All Day",
"location": "Reepham, Norfolk",
"id": "632047e5b2a712a7707f6b28ac722b1e706f1589",
"year_founded": 2014,
"notes": "Reepham, Norfolk est. 2014",
"products": [
{
"name": "Let's Cask - Strong Golden Ale",
"style": "Golden Ale",
"dispense": "cask",
"abv": "5.4",
"status_text": "Plenty left",
"allergens": {"gluten": 1},
"id": "3e908babc017695281dc1f9887be46c6ffb9e0a3",
"notes": "Heritage Range - Crisp Heritage malts...",
"category": "beer",
"bar": "Arctic"
}
]
}
]
}{
"timestamp": "2025-05-24T00:01:00Z",
"producers": [
{
"name": "Ross on Wye Cider & Perry Co.",
"location": "Ross on Wye, Herefordshire",
"id": "abc123...",
"products": [
{
"name": "Strong Kentish Cider",
"abv": "8.4",
"category": "cider",
"dispense": "cider tub",
"style": null,
"allergens": {},
"id": "def456...",
"notes": "Made from Kentish cider apples",
"bar": "Cider Bar"
}
]
}
]
}- beer-list-schema.json - JSON Schema for API responses
- festival-registry-schema.json - JSON Schema for festival config
- BeerFestApp - Original Android app
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2025-11-29 | Initial documentation for Flutter app |
| 1.1.0 | 2026-05-11 | Add is_vegan field (with legacy vegan fallback) |