|
2 | 2 | "openapi": "3.1.0", |
3 | 3 | "info": { |
4 | 4 | "title": "Six-Axis Compass API", |
5 | | - "version": "2.0.0", |
6 | | - "description": "Public read API (unauthenticated by default). Private write under /api/admin/* requires ADMIN_SECRET (Phase 2)." |
| 5 | + "version": "2.1.0", |
| 6 | + "description": "Public read API (unauthenticated by default). Merch checkout routes added in v2.1.0." |
7 | 7 | }, |
8 | 8 | "servers": [{ "url": "/" }], |
9 | 9 | "paths": { |
|
30 | 30 | "/api/chart": { |
31 | 31 | "post": { |
32 | 32 | "summary": "Render radar chart", |
33 | | - "requestBody": { "content": { "application/json": { "schema": { "type": "object" } } } }, |
| 33 | + "requestBody": { |
| 34 | + "content": { |
| 35 | + "application/json": { |
| 36 | + "schema": { |
| 37 | + "type": "object", |
| 38 | + "properties": { |
| 39 | + "background": { "enum": ["white", "transparent", "dark"] }, |
| 40 | + "labelMerch": { "type": "boolean" }, |
| 41 | + "labelMode": { "enum": ["trigram", "full"] } |
| 42 | + } |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | + }, |
34 | 47 | "responses": { |
35 | 48 | "200": { "description": "image/svg+xml or image/png" }, |
36 | 49 | "400": { "description": "Validation error" }, |
|
41 | 54 | "/api/axes": { |
42 | 55 | "get": { "summary": "Canonical axes and pole labels", "responses": { "200": { "description": "Axis catalog" } } } |
43 | 56 | }, |
| 57 | + "/api/merch/prices": { |
| 58 | + "get": { |
| 59 | + "summary": "Merch GBP prices from catalog", |
| 60 | + "responses": { "200": { "description": "Price map keyed by product id" } } |
| 61 | + } |
| 62 | + }, |
| 63 | + "/api/checkout/session": { |
| 64 | + "post": { |
| 65 | + "summary": "Create Stripe Checkout session for merch order", |
| 66 | + "responses": { |
| 67 | + "200": { "description": "Checkout URL and order id" }, |
| 68 | + "400": { "description": "Validation error" }, |
| 69 | + "403": { "description": "CORS origin not allowed" }, |
| 70 | + "429": { "description": "Rate limited" }, |
| 71 | + "503": { "description": "Stripe not configured" } |
| 72 | + } |
| 73 | + } |
| 74 | + }, |
| 75 | + "/api/orders/{orderId}": { |
| 76 | + "get": { |
| 77 | + "summary": "Public order status by internal order id", |
| 78 | + "parameters": [{ "name": "orderId", "in": "path", "required": true, "schema": { "type": "string" } }], |
| 79 | + "responses": { "200": { "description": "Order status" }, "404": { "description": "Not found" } } |
| 80 | + } |
| 81 | + }, |
| 82 | + "/api/orders/session/{sessionId}": { |
| 83 | + "get": { |
| 84 | + "summary": "Public order status by Stripe Checkout session id", |
| 85 | + "parameters": [{ "name": "sessionId", "in": "path", "required": true, "schema": { "type": "string" } }], |
| 86 | + "responses": { "200": { "description": "Order status" }, "404": { "description": "Not found" } } |
| 87 | + } |
| 88 | + }, |
| 89 | + "/api/webhooks/stripe": { |
| 90 | + "post": { |
| 91 | + "summary": "Stripe webhook (checkout.session.completed)", |
| 92 | + "responses": { "200": { "description": "Acknowledged" }, "400": { "description": "Invalid signature" } } |
| 93 | + } |
| 94 | + }, |
44 | 95 | "/api/openapi.json": { |
45 | 96 | "get": { "summary": "OpenAPI document", "responses": { "200": { "description": "This document" } } } |
46 | 97 | } |
|
0 commit comments