# DomiSol Public API

A small, read-only HTTP API for third-party integrations (church-management
software, blog plugins, AI agents). It exposes scores that authors have already
published via a share link, plus aggregate usage counts. There is no new data
exposure beyond what the public `/s/{slug}` share pages already show.

- **Base URL:** `https://us-central1-domisol-prod.cloudfunctions.net/publicApi`
- **Machine description (OpenAPI 3.1):** <https://domisol.app/.well-known/openapi.json>
- **API catalog (RFC 9727):** <https://domisol.app/.well-known/api-catalog>
- **Authentication:** <https://domisol.app/auth.md>
- **CORS:** open to any origin.
- **Method:** `GET` only. Anything else returns `405`.

## Endpoints

### `GET /v1/scores/{slug}`

Fetch a published score by the slug from its share link
(`https://dash.domisol.app/s/{slug}`). Returns clean JSON — no `user_id`, no
internal metadata. Only scores whose author has published them are returned;
everything else is `404`.

```
curl https://us-central1-domisol-prod.cloudfunctions.net/publicApi/v1/scores/amazing-grace
```

Response (`200`, edge-cached 60s):

```json
{
  "id": "…",
  "slug": "amazing-grace",
  "title": "Amazing Grace",
  "composer": "John Newton",
  "arranger": null,
  "key": "G",
  "time_signature": [3, 4],
  "tempo": 100,
  "notation": "solfa",
  "parts": [ … ],
  "lyrics": [ … ],
  "updated_at": "2026-01-01T00:00:00.000Z"
}
```

`parts` hold measures of notes in DomiSol's degree/beats model (degree `0–6` =
do–ti / 1–7, `octave_shift`, `beats`, `dotted`, …). See the notation reference
at <https://domisol.app/learn/solfa/> and <https://domisol.app/learn/jianpu/>,
or the machine-readable schema in the OpenAPI document.

### `GET /v1/stats`

Aggregate counts behind the marketing site's homepage figures. Open (never
gated by an API key). Cache-able for one hour.

```json
{ "musicians": 1200, "scores": 1800, "exports": 400, "generated_at": "…" }
```

### `GET /v1/health`

Liveness check. Returns `200` with `{ "status": "ok", … }` when the API is up.
Open (never gated). This is the `status` link relation target in the API
catalog.

## Errors

Errors are JSON: `{ "error": "…" }`. Status codes: `401` (missing/invalid API
key, only when a key gate is configured), `404` (no such public score / unknown
route), `405` (non-GET method), `500` (internal error).
