API Reference
Complete REST API documentation for BrewHoard's versioned API endpoints.
BrewHoard provides a comprehensive REST API for all operations. The API is versioned and follows RESTful conventions.
Base URL
Production: https://your-domain.com/api/v1
Development: http://localhost:5173/api/v1Authentication
The API supports two authentication methods:
Session Cookie (Browser)
For browser-based requests, authentication uses HTTP-only session cookies:
// Login creates a session cookie
const response = await fetch('/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
credentials: 'include' // Important for cookies
});API Key (Programmatic)
For server-to-server or CLI access, use API keys:
curl -X GET "https://api.brewhoard.com/api/v1/collection"
-H "Authorization: Bearer bv_live_xxxxxxxxxxxxxxxxxxxx"API keys are prefixed with bv_live_ (production) or bv_test_ (development).
Response Format
All responses follow a consistent structure:
Success Response
{
"success": true,
"data": {
// Response data here
},
"meta": {
"page": 1,
"limit": 20,
"total": 150
}
}Error Response
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid email format",
"details": {
"field": "email",
"constraint": "email"
}
}
}Common Error Codes
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid authentication |
FORBIDDEN | 403 | Insufficient permissions |
NOT_FOUND | 404 | Resource not found |
VALIDATION_ERROR | 400 | Invalid request data |
RATE_LIMITED | 429 | Too many requests |
SERVER_ERROR | 500 | Internal server error |
Rate Limiting
API requests are rate-limited per user/IP:
| Endpoint Type | Limit |
|---|---|
| Authentication | 10 requests/minute |
| Read operations | 100 requests/minute |
| Write operations | 30 requests/minute |
| File uploads | 10 requests/minute |
Rate limit headers are included in responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1699876543Authentication Endpoints
POST /auth/register
Create a new user account.
Request:
{
"email": "user@example.com",
"password": "securepassword123",
"displayName": "Beer Lover"
}Response:
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"displayName": "Beer Lover",
"createdAt": "2024-01-15T10:30:00Z"
}
}
}POST /auth/login
Authenticate and create a session.
Request:
{
"email": "user@example.com",
"password": "securepassword123"
}Response:
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"displayName": "Beer Lover"
},
"expiresAt": "2024-01-22T10:30:00Z"
}
}POST /auth/api-keys
Create a new API key.
Request:
{
"name": "CLI Access",
"scopes": ["collection:read", "collection:write"],
"expiresAt": "2025-01-15T00:00:00Z"
}Response:
{
"success": true,
"data": {
"id": "uuid",
"name": "CLI Access",
"key": "bv_live_xxxxxxxxxxxxxxxxxxxx",
"keyPrefix": "bv_live_",
"scopes": ["collection:read", "collection:write"],
"expiresAt": "2025-01-15T00:00:00Z"
}
}Note: The full API key is only returned once. Store it securely.
Beer Endpoints
GET /beers
Search and list beers.
Query Parameters: | Parameter | Type | Description |
|-----------|------|-------------|
| q | string | Search query (name, brewery) |
| style | string | Filter by beer style |
| minAbv | number | Minimum ABV |
| maxAbv | number | Maximum ABV |
| breweryId | uuid | Filter by brewery |
| page | number | Page number (default: 1) |
| limit | number | Results per page (default: 20, max: 100) |
Example:
curl "/api/v1/beers?q=IPA&minAbv=6&limit=10"Response:
{
"success": true,
"data": {
"beers": [
{
"id": "uuid",
"name": "Hop Heaven IPA",
"style": "IPA",
"abv": 6.5,
"ibu": 65,
"brewery": {
"id": "uuid",
"name": "Craft Brewery Co"
},
"avgRating": 4.2,
"ratingCount": 156
}
]
},
"meta": {
"page": 1,
"limit": 10,
"total": 45
}
}GET /beers/:id
Get detailed beer information.
Response:
{
"success": true,
"data": {
"id": "uuid",
"name": "Hop Heaven IPA",
"style": "IPA",
"substyle": "West Coast IPA",
"abv": 6.5,
"ibu": 65,
"description": "A bold, hop-forward IPA with citrus and pine notes.",
"imageUrl": "https://cdn.brewhoard.com/beers/hop-heaven.jpg",
"brewery": {
"id": "uuid",
"name": "Craft Brewery Co",
"country": "US",
"city": "Portland"
},
"stats": {
"avgRating": 4.2,
"ratingCount": 156,
"inCollections": 89
}
}
}GET /beers/styles
Get available beer styles.
Response:
{
"success": true,
"data": {
"styles": [
{ "name": "IPA", "count": 1250 },
{ "name": "Stout", "count": 890 },
{ "name": "Lager", "count": 756 }
]
}
}Collection Endpoints
GET /collection
Get the authenticated user’s collection.
Query Parameters: | Parameter | Type | Description |
|-----------|------|-------------|
| style | string | Filter by beer style |
| forTrade | boolean | Only show items marked for trade |
| sort | string | Sort field: name, addedAt, quantity |
| order | string | Sort order: asc, desc |
Response:
{
"success": true,
"data": {
"items": [
{
"id": "uuid",
"beer": {
"id": "uuid",
"name": "Hop Heaven IPA",
"style": "IPA",
"brewery": { "name": "Craft Brewery Co" }
},
"quantity": 6,
"containerType": "bottle",
"containerSizeMl": 330,
"storageLocation": "Beer Fridge",
"isForTrade": false,
"acquisitions": [
{
"id": "uuid",
"quantity": 6,
"purchasePrice": 12.99,
"purchaseCurrency": "USD",
"purchaseDate": "2024-01-10",
"purchaseLocation": "Local Brewery"
}
],
"createdAt": "2024-01-10T15:30:00Z"
}
],
"stats": {
"uniqueBeers": 45,
"totalBottles": 128,
"totalValue": 892.50
}
}
}POST /collection
Add a beer to the collection.
Request:
{
"beerId": "uuid",
"quantity": 6,
"containerType": "bottle",
"containerSizeMl": 330,
"storageLocation": "Beer Fridge",
"notes": "Anniversary edition",
"acquisition": {
"purchasePrice": 12.99,
"purchaseCurrency": "USD",
"purchaseDate": "2024-01-10",
"purchaseLocation": "Local Brewery"
}
}Response:
{
"success": true,
"data": {
"id": "uuid",
"beerId": "uuid",
"quantity": 6,
"createdAt": "2024-01-10T15:30:00Z"
}
}PATCH /collection/:id
Update a collection item.
Request:
{
"quantity": 5,
"storageLocation": "Cellar",
"isForTrade": true
}DELETE /collection/:id
Remove an item from the collection.
POST /collection/consume
Record consumption of a beer.
Request:
{
"collectionItemId": "uuid",
"quantity": 1,
"notes": "Shared with friends",
"rating": {
"overall": 4.5,
"reviewText": "Excellent hoppy character"
}
}Marketplace Endpoints
GET /marketplace/listings
Browse active marketplace listings.
Query Parameters: | Parameter | Type | Description |
|-----------|------|-------------|
| q | string | Search query |
| style | string | Filter by beer style |
| minPrice | number | Minimum price |
| maxPrice | number | Maximum price |
| shipsTo | string | Country code for shipping |
| sort | string | price, newest, popular |
Response:
{
"success": true,
"data": {
"listings": [
{
"id": "uuid",
"title": "Vintage 2020 Imperial Stout",
"beer": {
"id": "uuid",
"name": "Imperial Stout Reserve",
"style": "Imperial Stout"
},
"seller": {
"id": "uuid",
"displayName": "BeerCollector42",
"rating": 4.8,
"salesCount": 23
},
"quantity": 2,
"price": 45.00,
"currency": "USD",
"shippingCost": 12.00,
"condition": "aged",
"photos": ["https://cdn.brewhoard.com/listings/..."],
"createdAt": "2024-01-12T09:00:00Z"
}
]
}
}POST /marketplace/listings
Create a new listing.
Request:
{
"collectionItemId": "uuid",
"title": "Rare 2018 Barrel-Aged Stout",
"description": "Perfectly cellared for 6 years",
"quantity": 1,
"price": 75.00,
"currency": "USD",
"shippingCost": 15.00,
"shipsTo": ["US", "CA", "GB"],
"condition": "vintage",
"photos": ["data:image/jpeg;base64,..."]
}POST /marketplace/transactions
Initiate a purchase.
Request:
{
"listingId": "uuid",
"quantity": 1,
"shippingAddress": {
"name": "John Doe",
"street": "123 Main St",
"city": "Portland",
"state": "OR",
"postalCode": "97201",
"country": "US"
}
}Response:
{
"success": true,
"data": {
"transactionId": "uuid",
"stripeClientSecret": "pi_xxxxx_secret_xxxxx",
"amount": 90.00,
"currency": "USD"
}
}Rating Endpoints
GET /ratings
Get ratings for a beer.
Query Parameters: | Parameter | Type | Description |
|-----------|------|-------------|
| beerId | uuid | Required: Beer ID |
| sort | string | newest, highest, helpful |
POST /ratings
Submit a rating.
Request:
{
"beerId": "uuid",
"overallRating": 4.5,
"aromaRating": 4.0,
"appearanceRating": 4.5,
"tasteRating": 5.0,
"mouthfeelRating": 4.0,
"reviewText": "Exceptional hop character with a clean finish.",
"tastingNotes": {
"flavors": ["citrus", "pine", "tropical"],
"aromas": ["grapefruit", "floral"],
"mouthfeel": ["crisp", "medium-bodied"]
},
"servingType": "draft",
"isPublic": true
}Scanner Endpoints
POST /scanner/recognize
Identify a beer from an image.
Request:
Content-Type: multipart/form-data
image: <binary image data>Response:
{
"success": true,
"data": {
"matches": [
{
"beer": {
"id": "uuid",
"name": "Hop Heaven IPA",
"brewery": { "name": "Craft Brewery Co" }
},
"confidence": 0.92,
"matchedOn": ["label", "logo"]
},
{
"beer": {
"id": "uuid",
"name": "Hop Paradise IPA"
},
"confidence": 0.75
}
],
"extractedText": ["Hop Heaven", "IPA", "6.5% ABV"]
}
}POST /scanner/scan
Scan a barcode.
Request:
{
"barcode": "5901234123457",
"type": "EAN13"
}Export Endpoints
POST /export
Export collection data.
Request:
{
"format": "csv",
"includeHistory": true,
"includeRatings": true,
"dateRange": {
"start": "2023-01-01",
"end": "2024-01-15"
}
}Response:
{
"success": true,
"data": {
"downloadUrl": "https://cdn.brewhoard.com/exports/export-xxxxx.csv",
"expiresAt": "2024-01-16T10:30:00Z",
"recordCount": 145
}
}Webhooks
Configure webhooks to receive real-time notifications:
Available Events
| Event | Description |
|---|---|
transaction.created | New purchase initiated |
transaction.completed | Purchase completed |
listing.sold | Your listing was purchased |
rating.received | Someone rated your transaction |
Webhook Payload
{
"event": "transaction.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"transactionId": "uuid",
"buyerId": "uuid",
"sellerId": "uuid",
"amount": 90.00
}
}SDK Examples
JavaScript/TypeScript
// Using fetch
async function getCollection() {
const response = await fetch('/api/v1/collection', {
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
return response.json();
}
// Using the BrewHoard SDK (coming soon)
import { BrewHoard } from '@brewhoard/sdk';
const client = new BrewHoard({ apiKey: 'bv_live_xxx' });
const collection = await client.collection.list();cURL
# Get collection
curl -X GET "https://api.brewhoard.com/api/v1/collection"
-H "Authorization: Bearer bv_live_xxx"
# Add to collection
curl -X POST "https://api.brewhoard.com/api/v1/collection"
-H "Authorization: Bearer bv_live_xxx"
-H "Content-Type: application/json"
-d '{"beerId": "uuid", "quantity": 6}'Next Steps
- Authentication Guide - Detailed auth documentation
- Beers API - Full beers endpoint reference
- Collection API - Collection management
- Marketplace API - Trading endpoints