OpenGlaze API Reference

Current REST API for the Flask app in this repository.

**Base URL:** `http://localhost:8768/api` for Docker, `http://localhost:8767/api` for manual local runs unless `FLASK_PORT` is set.

**Authentication model:** default personal mode is single-user and mostly unauthenticated. Studio collaboration uses the lightweight simple-auth token returned by `/api/auth/simple-login`. Cloud/Ory auth exists in code, but PostgreSQL/cloud mode is not the default launch path.

Health

GET /health
GET /api/health

`/health` returns a basic status/version payload. `/api/health` also reports mode, feature flags, and rate-limit stats.

Auth

Simple login

POST /api/auth/simple-login
Content-Type: application/json

{
  "display_name": "Jane Potter"
}

Response:

{
  "user_id": "u_...",
  "display_name": "Jane Potter",
  "token": "..."
}

Send the token as:

Authorization: Bearer <token>

Current user

GET /api/auth/me
Authorization: Bearer <token>

Glazes

GET /api/glazes
GET /api/glazes/<glaze_id>
POST /api/glazes
PUT /api/glazes/<glaze_id>
DELETE /api/glazes/<glaze_id>
GET /api/glazes/<glaze_id>/umf?cone=10

Create/update payloads use the glaze fields accepted by `Glaze.from_dict`, including `id`, `name`, `family`, `hex`, `chemistry`, `behavior`, `layering`, `warning`, `recipe`, `catalog_code`, `food_safe`, and `notes`.

Combinations

GET /api/combinations
GET /api/combinations?type=research-backed
GET /api/combinations?type=user-prediction
GET /api/combinations/grouped
GET /api/combinations/<combo_id>
POST /api/combinations
PUT /api/combinations/<combo_id>
POST /api/combinations/<combo_id>/promote
POST /api/combinations/<combo_id>/simulate
POST /api/combinations/simulate-all
GET /api/combinations/<combo_id>/compatibility?cone=10

Chemistry

POST /api/chemistry/batch
POST /api/chemistry/scale
POST /api/chemistry/compare
POST /api/chemistry/optimize
POST /api/chemistry/substitutions
POST /api/chemistry/defects

Examples:

POST /api/chemistry/optimize
Content-Type: application/json

{
  "recipe": "Custer Feldspar 45, Silica 25, Whiting 18, EPK 12",
  "target": "reduce_cte",
  "max_suggestions": 5
}
POST /api/chemistry/scale
Content-Type: application/json

{
  "recipe": "Custer Feldspar 45, Silica 25, Whiting 18, EPK 12",
  "batch_size_grams": 1000,
  "unit": "grams"
}
POST /api/chemistry/compare
Content-Type: application/json

{
  "recipe_a": "Custer Feldspar 45, Silica 25, Whiting 18, EPK 12",
  "recipe_b": "Custer Feldspar 40, Silica 30, Whiting 18, EPK 12",
  "name_a": "Original",
  "name_b": "Revision",
  "cone": 10
}

Experiments

GET /api/experiments
GET /api/experiments?stage=ideation
GET /api/experiments/active
GET /api/experiments/stats
GET /api/experiments/<exp_id>
POST /api/experiments
POST /api/experiments/<exp_id>/advance
POST /api/experiments/<exp_id>/result
POST /api/experiments/<exp_id>/archive
POST /api/experiments/<exp_id>/firing-log
POST /api/experiments/<exp_id>/share

Uploads and photos

POST /api/upload
GET /api/photos

Upload expects multipart form-data with a `photo` field. Supported extensions are JPG, JPEG, PNG, and WebP; max size is 5 MB.

Studio collaboration

Studio endpoints require simple-auth or Ory user context.

POST /api/studios
GET /api/studios
POST /api/studios/join
GET /api/studios/<studio_id>
DELETE /api/studios/<studio_id>
POST /api/studios/<studio_id>/regenerate-code
GET /api/studios/<studio_id>/lab-queue
POST /api/studios/<studio_id>/lab-queue/<combo_id>/claim
POST /api/studios/<studio_id>/lab-queue/<combo_id>/release
GET /api/studios/<studio_id>/my-claims
GET /api/studios/<studio_id>/experiments

Progress, stats, and predictions

These endpoints require authenticated user context and may return `401` in default unauthenticated personal mode.

GET /api/stats
GET /api/progress
POST /api/predictions
GET /api/predictions/leaderboard

Templates

GET /api/templates
GET /api/templates/<template_id>
POST /api/templates/<template_id>/apply

Applying a template requires authenticated user context.

Demo endpoints

GET /api/demo/glazes
POST /api/demo/compatibility

These are public demo/reference endpoints backed by curated demo glaze data when available.

Error format

Most errors are returned as JSON:

{
  "error": "Human-readable message"
}

Rate limits return HTTP `429` with a `Retry-After` header.