API reference
Read the future v1 surface for meetings: the three endpoints, the headers we will require once the API-key program opens, and the lifecycle states each meeting walks through. Every example below is a curl-against-the-stub and the response is parsed by the same shared contract the handler returns.
Base URL
Required headers
| Header | Value | Note |
|---|---|---|
Authorization | Bearer <api-key> | Placeholder for the upcoming API-key program. The stub serves unauthenticated requests regardless of this header; production v1 will reject requests without a valid key. |
Content-Type | application/json | Required on POST endpoints; the stub will echo it back, document the v1 contract. |
/api/v1/meetingsAuth
Required. Signed-in callers only. The stub uses the deployed session cookie; future v1 will additionally require an API-key in `Authorization: Bearer <key>`.
Scheme: session
Request body
{
"title": "Tower 3 — tower crane pick",
"industry": "construction",
"job": "crane-lift",
"location": "Site B, Bay 4",
"crew": "Tower-3",
"hazards": ["fall from height", "suspended load"],
"controls": ["harness + tie-off", "tag-line on every pick"]
}Request fields
| Field | Type | Note |
|---|---|---|
title | string (1..140) | Free-text headline. |
industry | string (1..80) | e.g. 'construction'. |
job | string (1..80) | e.g. 'crane-lift' — the day's work. |
location | string (1..160) | On-site location label. |
crew | string (1..160) | Crew identifier. |
hazards | string[] (≥1) | Staged into briefJson.sections.hazards. |
controls | string[] (≥1) | Staged into briefJson.sections.controls. |
Response shape
{
"id": "cm123abc...",
"title": "Tower 3 — tower crane pick",
"industry": "construction",
"job": "crane-lift",
"createdAt": "2026-08-15T08:30:00.000Z",
"status": "PLANNED",
"meta": {
"apiVersion": "v1",
"documentationUrl": "/docs/api"
}
}| Field | Type | Note |
|---|---|---|
id | string | Server-assigned meeting id (cuid). |
title | string | null | Free-text headline; null when the meeting has no title yet. |
industry | string | null | optional |
job | string | null | optional |
createdAt | ISO-8601 string | required |
status | 'PLANNED' | 'IN_PROGRESS' | 'COMPLETE' | required |
meta.apiVersion | 'v1' | required |
meta.documentationUrl | '/docs/api' | Canonical link to the API reference for the current API version. |
/api/v1/meetingsAuth
Required. Signed-in callers only; the v1 surface is not the public history feed at /api/meetings (which the dashboard already consumes).
Scheme: session
Response shape
{
"data": [],
"meta": {
"apiVersion": "v1",
"documentationUrl": "/docs/api"
}
}| Field | Type | Note |
|---|---|---|
data | MeetingItem[] | Hydrated meeting rows; the stub returns an empty array. |
meta.apiVersion | 'v1' | required |
meta.documentationUrl | '/docs/api' | Canonical link to the API reference for the current API version. |
/api/v1/meetings/<meeting-id>/sign-inAuth
Required. Signed-in callers only. The parent meeting must already exist (typically produced by POST /meetings earlier in the workflow).
Scheme: session
Request body
{
"name": "Alex Rivera",
"employeeNumber": "B-0042",
"signatureSvg": "<svg viewBox=\"0 0 480 180\"><path d=\"M10 90 L470 90\"/></path></svg>",
"supervisorAckName": "Pat Chen"
}Response shape
{
"id": "cm123abc...",
"meetingId": "cm456def...",
"name": "Alex Rivera",
"employeeNumber": "B-0042",
"signatureSvg": "<svg viewBox=\"0 0 480 180\"><path d=\"M10 90 L470 90\"/></path></svg>",
"supervisorAckName": "Pat Chen",
"supervisorAckAt": "2026-08-15T08:42:00.000Z",
"createdAt": "2026-08-15T08:42:00.000Z",
"meta": {
"apiVersion": "v1",
"documentationUrl": "/docs/api"
}
}| Field | Type | Note |
|---|---|---|
id | string | required |
meetingId | string | required |
name | string | Free text; v1 will not enforce roster membership. |
employeeNumber | string | Unique per meeting — duplicates return 409. |
signatureSvg | string | Captured signature; an empty string is treated as unsigned. |
supervisorAckName | string | null | optional |
supervisorAckAt | ISO-8601 string | null | Sentinel for whether the supervisor has acknowledged the row. |
createdAt | ISO-8601 string | required |
meta.apiVersion | 'v1' | required |
meta.documentationUrl | '/docs/api' | required |
/api/meetings/<meeting-id>/attendAuth
Not required. Public endpoint. No API-key or session is enforced; submitter-side POST curls resolve unauthenticated. The seed rows used by the Try-it demo can be missing — a 404 is fire-once when the parent meeting id does not exist.
Scheme: public
Request body
{
"name": "Alex Rivera",
"trade": "Ironworker / CW-2871"
}Request fields
| Field | Type | Note |
|---|---|---|
name | string (1..120) | required |
trade | string (1..80) | Trade or role, e.g. 'Ironworker / CW-2871'. |
Response shape
{
"id": "cm123abc...",
"meetingId": "cm456def...",
"name": "Alex Rivera",
"trade": "Ironworker / CW-2871",
"createdAt": "2026-08-15T08:42:00.000Z",
"meta": {
"documentationUrl": "/docs/api"
}
}| Field | Type | Note |
|---|---|---|
id | string | required |
meetingId | string | required |
name | string | required |
trade | string | Stored under the existing `MeetingSignIn.employeeNumber` column. Duplicates per meeting return 409. |
createdAt | ISO-8601 string | required |
meta.documentationUrl | '/docs/api' | Canonical link to the API reference for the current publication. |
Live probe
/api/meetings/<id>/attend stub. The response for each renders in the panel below; nothing on this page initial-loads, the probes only fire when you press a Try button. The three v1 probes require sign-in (the v1 stubs are auth-gated); an anonymous caller receives a 401 on each. The attend probe is public and accepts any caller.GET /meetings
curl /api/v1/meetings// press Try it to capture a live response
POST /meetings
curl -X POST /api/v1/meetings// press Try it to capture a live response
POST /meetings/<meeting-id>/sign-in
curl -X POST /api/v1/meetings/<meeting-id>/sign-in// press Try it — POSTs to a deterministic placeholder id (cm123placeholderdocs000000); a not-found error is expected when no such row exists yet
POST /meetings/<meeting-id>/attend
curl -X POST /api/meetings/<meeting-id>/attend// press Try it — POSTs the sample { name, trade } body to a deterministic placeholder id (cm123placeholderdocs000000); a 404 is expected when no such row exists yetLifecycle states
| Value | Label | Description |
|---|---|---|
PLANNED | Planned | The meeting row exists but no Job has opened the brief; supervisors can still edit the title, industry, and crew before the lift. |
IN_PROGRESS | In progress | A Job is open against the meeting; the brief is locked, and the sign-in sheet is collecting signatures. |
COMPLETE | Complete | The Job has closed (with an optional note from the supervisor); the brief and sign-in PDF can both be exported from this state. |