You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: complete API v2.0.0 public read spec and sync README
HKW pass after v2.6.2 — full API.md for Phase 1 routes, limits, and
examples; README public chart curl; rebuild dist; changelog [Unreleased].
Co-authored-by: Cursor <cursoragent@cursor.com>
The server listens on `API_PORT` (default `3000`).
22
22
23
+
Production chart API hosting is maintainer-operated (not served from GitHub Pages). The static app lives at `https://earlution.github.io/6-axis-compass/`; run `npm run api` locally or deploy `api/server.js` behind HTTPS.
**Error — 401 Unauthorized** (only when `API_PUBLIC_READ=false` and Bearer missing/invalid)
106
177
107
178
```json
108
179
{ "error": "Unauthorized" }
@@ -116,9 +187,10 @@ Returns the full record for a single actor, including metadata, scores, per-ques
116
187
117
188
```http
118
189
GET /api/actors/:slug
119
-
Authorization: Bearer <API_SECRET>
120
190
```
121
191
192
+
Public read (default): no `Authorization` header.
193
+
122
194
The `:slug` parameter is the URL-safe identifier from `data/actors/{slug}.json` (e.g. `conservative-party`, `restore-britain-2025-2026`).
123
195
124
196
**Response — 200 OK**
@@ -160,13 +232,15 @@ The `:slug` parameter is the URL-safe identifier from `data/actors/{slug}.json`
160
232
}
161
233
```
162
234
235
+
**Response headers:**`Cache-Control: public, max-age=300`, `ETag`, `Last-Modified`. Send `If-None-Match` with the prior `ETag` to receive **304 Not Modified** when the file is unchanged.
236
+
163
237
**Error — 404 Not Found**
164
238
165
239
```json
166
240
{ "error": "Actor not found" }
167
241
```
168
242
169
-
**Error — 401 Unauthorized**
243
+
**Error — 401 Unauthorized** (only when `API_PUBLIC_READ=false`)
170
244
171
245
```json
172
246
{ "error": "Unauthorized" }
@@ -176,29 +250,34 @@ The `:slug` parameter is the URL-safe identifier from `data/actors/{slug}.json`
176
250
177
251
### 4. Render Chart
178
252
179
-
Generates a radar-chart image from your scores, optionally overlaying known actors.
253
+
Generates a radar-chart image from your scores, optionally overlaying known actors.**Rate-limited** on public deployments (see below).
180
254
181
255
```http
182
256
POST /api/chart
183
-
Authorization: Bearer <API_SECRET>
184
257
Content-Type: application/json
185
258
```
186
259
260
+
Public read (default): no `Authorization` header.
261
+
187
262
**Request Body**
188
263
189
264
| Field | Type | Required | Default | Description |
|`scores`|`object`| No | All axes `0`| Six-axis scores. Each key must be one of: `Cultural`, `Economic`, `Military`, `Sovereignty`, `Governance`, `Class`. Each value must be a number `0–10`. |
192
-
|`actors`|`string[]`| No |`[]`|Names of actors to overlay on the chart. Must match the `name`field from `/api/actors`. |
193
-
|`format`|`string`| No |`"svg"`|Output format: `"svg"` or `"png"`. |
194
-
|`orientation`|`string`| No |`"flat"`|Chart orientation: `"flat"` (edge-up hexagon; **Cultural** at the top flat edge) or `"pointy"`. |
195
-
|`axes`|`string[]`| No | Canonical order (below) | Clockwise spoke order. Must be a permutation of the six axis names. |
196
-
|`register`|`string`| No |`"primary"`|Actor overlay score register: `"primary"`, `"declared"`, or `"structural"`(uses `dualRegister`when present). |
197
-
|`showUser`|`boolean`| No |`true`|Whether to draw the user’s own score polygon. |
267
+
|`actors`|`string[]`| No |`[]`|Actor overlays by `name` from `/api/actors`.**Max 8.**|
268
+
|`format`|`string`| No |`"svg"`|`"svg"` or `"png"`. |
269
+
|`orientation`|`string`| No |`"flat"`|`"flat"` (**Cultural** at top flat edge) or `"pointy"`. |
270
+
|`axes`|`string[]`| No | Canonical order (below) | Clockwise spoke permutation of the six axis names. |
271
+
|`register`|`string`| No |`"primary"`|`"primary"`, `"declared"`, or `"structural"`for overlays when `dualRegister`exists. |
272
+
|`showUser`|`boolean`| No |`true`|Draw the userscore polygon (`false` for actor-only charts). |
198
273
|`colors.user`|`string`| No |`"#c8a84b"`| Hex colour for the user polygon. |
199
-
|`title`|`string`| No |`"Chart"`| Chart title (embedded in SVG/PNG metadata). |
200
-
|`width`|`number`| No |`600`| PNG width in pixels (PNG only). |
201
-
|`height`|`number`| No |`600`| PNG height in pixels (PNG only). |
274
+
|`title`|`string`| No |`"Chart"`| Chart title. **Max 200 characters.**|
275
+
|`width`|`number`| No |`600`| PNG width (PNG only). Max **4096**; `width × height` ≤ **16_777_216**. |
276
+
|`height`|`number`| No |`600`| PNG height (PNG only). Same limits as `width`. |
277
+
278
+
**Rate limiting (public read):** Default **60** requests per client IP per minute (`API_CHART_RATE_LIMIT`). Excess requests return **429** with `Retry-After` (seconds).
279
+
280
+
**Permutation coverage:** Any valid combination of actor set (0–8), register, custom `scores`, `axes` order, `orientation`, and `format` supported by the table above.
202
281
203
282
**Example Request — SVG**
204
283
@@ -262,23 +341,80 @@ Returns raw PNG bytes with `Content-Type: image/png`.
262
341
{ "error": "Invalid format. Use svg or png." }
263
342
```
264
343
265
-
**Error — 401 Unauthorized**
344
+
```json
345
+
{ "error": "At most 8 actor overlays allowed" }
346
+
```
347
+
348
+
```json
349
+
{ "error": "Too many requests", "retryAfter": 42 }
350
+
```
351
+
352
+
**Error — 401 Unauthorized** (only when `API_PUBLIC_READ=false`)
266
353
267
354
```json
268
355
{ "error": "Unauthorized" }
269
356
```
270
357
358
+
**Error — 429 Too Many Requests**
359
+
360
+
```json
361
+
{ "error": "Too many requests", "retryAfter": 42 }
362
+
```
363
+
364
+
Response header: `Retry-After: 42`
365
+
366
+
---
367
+
368
+
### 5. Axis catalog
369
+
370
+
Canonical OQ2 axis order and pole labels (for clients building manifests without scraping this document).
0 commit comments