{
  "components": {
    "securitySchemes": {
      "access_token": {
        "bearerFormat": "Opaque access token",
        "description": "A responder's own access token, from `POST /api/v1/auth/login` or\n`POST /api/v1/auth/refresh`. Opaque and database-backed, never a JWT, so\nrevoking one stops it on the next request — `docs/AUTHENTICATION.md` §6.\n\nIt lives 15 minutes. Most of `/api/v1` accepts one up to five minutes\npast expiry, because a phone waking to a page must be able to\nacknowledge before its refresh completes; the routes that change *who\ngets paged* do not, and say so in their description.\n",
        "scheme": "bearer",
        "type": "http"
      },
      "account_token": {
        "bearerFormat": "art_…",
        "description": "An account-level API token, the alternative to a sync integration key on\nLane B when one caller acts for several sources. Returned once at\ncreation; only its digest is stored. `docs/LANE_B_API.md` §3.\n",
        "scheme": "bearer",
        "type": "http"
      },
      "async_key": {
        "bearerFormat": "ark_async_…",
        "description": "An async integration key, held by a monitor firing events at Lane A\n(`POST /api/v2/enqueue`). Scoped to one source.\n\nAn `ark_sync_…` key is **refused** here, and there is no account-level\nAPI token on this lane at all: a token names its source per request, and\na firehose credential that could name any source would let every monitor\nraise events as every other one. `docs/LANE_A_API.md` §3.\n",
        "scheme": "bearer",
        "type": "http"
      },
      "sync_key": {
        "bearerFormat": "ark_sync_…",
        "description": "A sync integration key, held by a ticket system of record calling Lane B\n(`/api/v2/incidents`). Scoped to one source. An `ark_async_…` key is\nrefused here. `docs/LANE_B_API.md` §3.\n",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "AlertRoster is a call-out notification and escalation tool: an event becomes\nan incident, the incident pages the people a schedule says are on call, and\nit keeps paging until somebody acknowledges.\n\nThis document is generated from the application's own router, so every\nendpoint it serves appears here and nothing else does.\n\n## Two lanes, two kinds of caller\n\n`/api/v1` is authenticated as a **responder** holding an access token — it\nis what the iOS and desktop clients are written against, and what a person\nacting on their own behalf uses.\n\n`/api/v2` is authenticated as a **system**: an integration key or an\naccount-level API token, held by a monitor or a ticket system acting on\nbehalf of a ticket rather than a person. The two must not be reachable with\neach other's credentials, which is what the lane on the key is for.\n\n## Conventions\n\nRequests with a body send `Content-Type: application/json`; every response\nis JSON. Identifiers are UUIDs. Timestamps are ISO 8601 in UTC, to the\nsecond.\n\nFailures answer a machine-readable code rather than prose:\n`{\"error\": \"not_found\"}`, `{\"error\": \"invalid_credentials\"}`. A `422` adds a\nper-field `details` object: `{\"error\": \"invalid_request\", \"details\":\n{\"deadline_at\": [\"must be in the future\"]}}`.\n\nEvery transition is a `POST` naming what it does — `acknowledge`, `resolve`,\n`arm`, `satisfy` — rather than a `PATCH` carrying a state. A caller that\nnames the transition it wants cannot ask for one the transition table would\nrefuse.\n\n## Not in this document\n\nTwo WebSocket surfaces, because OpenAPI does not describe them: the\nincident channel at `/socket` (`docs/INCIDENT_CHANNEL.md`) carrying live\nincident state and presence, and the agent channel at `/agent`\n(`docs/AGENT_API.md`) carrying the command set for the on-prem local agent.\n",
    "license": {
      "name": "Proprietary"
    },
    "title": "AlertRoster API",
    "version": "0.1.129"
  },
  "openapi": "3.0.3",
  "paths": {
    "/api/v1/incidents/{id}/search/locate": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Queues a command the phone answers on its next wake. The device is never\ntold why — `docs/CHECKIN_API.md` §15 — and this route answers with the\ncommand rather than a position, because the fix has not happened yet.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "incident_locate",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command": {
                    "id": "77aa…",
                    "kind": "locate",
                    "status": "queued"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Command queued."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Ask the subject's device for a fresh fix",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v2/incidents/{id}": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "There is deliberately **no list route** on this lane: a ticket system\nholds the ids it created, and an account-wide list would make one source's\nkey a bulk reader of every incident in the tenant.",
        "operationId": "v2_incident_show",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "status": "triggered"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "sync_key": []
          },
          {
            "account_token": []
          }
        ],
        "summary": "Read an incident",
        "tags": [
          "lane-b"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Title and urgency — what the incident *says*, never what it *is*. The\nstatus moves only through the transitions below.",
        "operationId": "v2_incident_update",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "title": "Payment gateway timeouts (EU only)",
                "urgency": "low"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "title": "Payment gateway timeouts (EU only)"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "sync_key": []
          },
          {
            "account_token": []
          }
        ],
        "summary": "Revise what an incident says",
        "tags": [
          "lane-b"
        ]
      }
    },
    "/api/v1/receivers/{id}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Revokes its certificate. The device stops being able to connect immediately.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "receiver_delete",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Delete a receiver",
        "tags": [
          "receivers"
        ]
      }
    },
    "/api/v1/checkins/location": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "A client asks this before every capture, to know whether to attach a\nposition at all — which is why it is on the hot half with the transitions\nrather than behind a fresh token.",
        "operationId": "checkin_location_status",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "location_opt_in": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Whether you have opted in to location",
        "tags": [
          "checkins"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Withdrawing also purges what was already captured, and is deliberately\n**not** gated on the account feature flag: a flag may stop somebody\ncollecting more, it may not trap them into keeping what is there.\n`docs/POSITIONING_AND_CLAIMS.md` §3.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_location_opt_in",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "opt_in": true
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "location_opt_in": true
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Grant or withdraw location consent",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/checkins/{id}/details": {
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "A sentence and a pin are both answers, and they are independent: send\neither, both, or neither. Read it back on the check-in object rather than\nhere — `docs/CHECKIN_API.md` §16.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_details",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "destination_latitude": 47.7423,
                "destination_longitude": -121.9857,
                "destination_text": "the ridge above Duvall",
                "wearing": "red jacket, blue rucksack"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "details": {
                    "captured_at": null,
                    "destination": {
                      "latitude": 47.7423,
                      "longitude": -121.9857,
                      "text": "the ridge above Duvall"
                    },
                    "origin": null,
                    "wearing": "red jacket, blue rucksack"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Set what you are wearing and where you are going, on one check-in",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/incidents/{id}/acknowledge": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The tap that stops a roster being paged, so it is on the hot path: an\naccess token up to five minutes past expiry is accepted here, because a\nresponder whose token lapsed while the phone slept still has to be able\nto answer. A `POST` naming the transition rather than a `PATCH` carrying\na status — `docs/INCIDENT_API.md` §1.",
        "operationId": "incident_acknowledge",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "status": "acknowledged"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Acknowledge — stop the paging",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Rotates the family: the refresh token sent is spent and a new pair comes\nback. Re-using a spent refresh token revokes the whole family, because a\nreplayed one means either a bug or a stolen credential and there is no\nway to tell them apart — `docs/AUTHENTICATION.md` §6.",
        "operationId": "auth_refresh",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "refresh_token": "…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "access_token": "…",
                  "expires_in": 900,
                  "refresh_token": "…"
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          }
        },
        "security": [],
        "summary": "Exchange a refresh token for a new pair",
        "tags": [
          "auth"
        ]
      }
    },
    "/api/v1/devices": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "One `POST` both creates and updates. A client re-registers on every\nlaunch and cannot know which it is doing, so there is deliberately no\nseparate update route. `platform` is `ios`, `android` or `desktop`; the\nfirst two carry a push token — an APNs device token or an FCM\nregistration token, validated separately and never interchangeable — and\nonly `ios` carries a `push_environment`. `docs/DEVICE_API.md` §3.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "device_create",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "app_version": "1.4.0",
                "device_identifier": "1A2B-3C4D",
                "platform": "ios",
                "push_token": "…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "device": {
                    "device_identifier": "1A2B-3C4D",
                    "id": "c81d…",
                    "platform": "ios"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Registered, whether this created the device or updated it."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Register — or re-register — this device for push",
        "tags": [
          "devices"
        ]
      }
    },
    "/api/v1/users/me": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "The account holder deletes themselves; nobody deletes anybody else here.\nWhat survives is what an incident history has to keep, and\n`docs/AUTHENTICATION.md` says which.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "user_delete",
        "parameters": [],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Delete your own account",
        "tags": [
          "users"
        ]
      }
    },
    "/api/v1/checkins/{id}/cancel": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The \"never mind\" for a timer armed by mistake, and the off switch for a\ndaily. Idempotent, and gated on the code where `extend` deliberately is\nnot: cancelling takes the safety net down for good.",
        "operationId": "checkin_cancel",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "id": "5f0f…",
                    "state": "idle"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Stand down without satisfying",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/checkins/commands": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "What the *subject's* phone is told, and the only shape it is ever told it\nin: a command id, a kind, and a deadline. No incident, no responder, no\nreason — a duress activation may be being watched over the subject's\nshoulder. `docs/CHECKIN_API.md` §15.",
        "operationId": "checkin_commands",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "commands": [
                    {
                      "command_id": "77aa…",
                      "expires_at": "2026-09-06T17:12:11Z",
                      "kind": "locate"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Commands waiting for this device",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/schedules/{id}/overrides": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "\"Bea is covering Ada from six until midnight.\" An override beats the\nlayers underneath it for its window and nothing else.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_create_override",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "ends_at": "2026-09-07T00:00:00Z",
                "starts_at": "2026-09-06T18:00:00Z",
                "user_id": "9a2b…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "override": {
                    "ends_at": "2026-09-07T00:00:00Z",
                    "id": "88cd…",
                    "starts_at": "2026-09-06T18:00:00Z",
                    "user_id": "9a2b…"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Created."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Override the rota for a window",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/layers/{id}/members": {
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "The whole list, not a delta: order is the rotation, and a partial write\nwould make \"who is next\" depend on the order the writes arrived in.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "layer_set_members",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "user_ids": [
                  "9a2b…",
                  "9a2c…"
                ]
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "layer": {
                    "id": "aa11…",
                    "member_ids": [
                      "9a2b…",
                      "9a2c…"
                    ]
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Set who is in a layer's rotation, and in what order",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/duress_code": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Leaves the ordinary check-in code alone.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_delete_duress_code",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "code_set": true,
                  "duress_code_set": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Clear your duress code",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/devices/{device_identifier}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Removes a delivery target and nothing else — it can never mint anything,\nwhich is why it sits with the stale-grace routes rather than behind a\nfresh token. A client logs out by deregistering *then* revoking\n(`docs/DEVICE_API.md` §8), and a phone whose token lapsed must not get a\n`401` on the first step and a `204` on the second.",
        "operationId": "device_delete",
        "parameters": [
          {
            "description": "The client-chosen stable identifier for the device, from registration.",
            "in": "path",
            "name": "device_identifier",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deregistered."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Deregister this device",
        "tags": [
          "devices"
        ]
      }
    },
    "/api/v2/incidents/{id}/resolve": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Closes the incident when the system of record closes the ticket.",
        "operationId": "v2_incident_resolve",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "status": "resolved"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "sync_key": []
          },
          {
            "account_token": []
          }
        ],
        "summary": "Resolve on behalf of the ticket",
        "tags": [
          "lane-b"
        ]
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Exchanges the emailed `token` — or the `code` and `email` pair — for an\naccess token and a refresh token. The link is single-use, and `GET`ting\nit in a browser does not spend it, so a mail scanner cannot burn it\nbefore the recipient clicks.",
        "operationId": "auth_login",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "token": "Xy7…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "access_token": "…",
                  "account": {
                    "id": "14a1…",
                    "name": "Cloud Bedrock",
                    "slug": "cloud-bedrock"
                  },
                  "expires_in": 900,
                  "refresh_token": "…",
                  "user": {
                    "email": "ada@example.com",
                    "id": "9a2b…",
                    "name": "Ada Walker",
                    "role": "responder"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          }
        },
        "security": [],
        "summary": "Spend a magic link or a login code",
        "tags": [
          "auth"
        ]
      }
    },
    "/api/v1/incidents/{id}/resolve": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Closes the incident. Resolving an already-resolved incident is not an error.",
        "operationId": "incident_resolve",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "status": "resolved"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Resolve",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v2/incidents/{id}/reassign": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Moves the page to `user_id`. The incident stays open.",
        "operationId": "v2_incident_reassign",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "user_id": "9a2b…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "assigned_user_id": "9a2b…",
                    "id": "4c1f…"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "sync_key": []
          },
          {
            "account_token": []
          }
        ],
        "summary": "Reassign on behalf of the ticket",
        "tags": [
          "lane-b"
        ]
      }
    },
    "/api/v1/schedules/{id}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Sources pointing at it fall back to the loud default: a miss pages every\nresponder in the account.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_delete",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Delete a schedule",
        "tags": [
          "schedules"
        ]
      },
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "The schedule with its layers.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_show",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "schedule": {
                    "id": "7714…",
                    "layers": [],
                    "name": "Primary on-call"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Read one schedule",
        "tags": [
          "schedules"
        ]
      },
      "patch": {
        "callbacks": {},
        "deprecated": false,
        "description": "Changing the zone re-computes who is on call from the next boundary.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_update",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "name": "Primary on-call (US)"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "schedule": {
                    "id": "7714…",
                    "name": "Primary on-call (US)"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Rename a schedule or move its time zone",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v2/enqueue": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The async lane: the caller is a monitor with nowhere to put an answer, so\nwhat comes back is a **receipt for a durable write** and never the state\nof an incident. Everything that decides what the event means — dedup,\nwhether it opens an incident, who it pages — happens in a job the same\ntransaction enqueued.\n\n`event_action` is required and **never defaulted**: a caller that meant\nto resolve and mistyped the field would otherwise raise a fresh incident,\nwhich is the loudest possible way to be wrong about a payload. It is\n`trigger`, `acknowledge` or `resolve`, and `payload` is required on a\n`trigger`. `docs/LANE_A_API.md` §5.",
        "operationId": "v2_enqueue_create",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "dedup_key": "db-primary-down",
                "event_action": "trigger",
                "payload": {
                  "custom_details": {
                    "checks_failed": 3,
                    "region": "iad"
                  },
                  "severity": "critical",
                  "source": "db-primary.iad",
                  "summary": "Primary database is not responding"
                }
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "alert_id": "dd44…",
                  "dedup_key": "db-primary-down",
                  "status": "accepted"
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Accepted and durably written. The receipt is not an incident."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "async_key": []
          }
        ],
        "summary": "Fire an event at the firehose",
        "tags": [
          "lane-a"
        ]
      }
    },
    "/api/v1/incidents/{id}/silence": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Stops the sound without acknowledging: the incident is still open and\nstill somebody's problem. The two are separate on purpose — silencing a\nphone in a meeting must not tell a roster that the page has been answered.",
        "operationId": "incident_silence",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "status": "triggered"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Silence this incident's noise on this device",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v1/users": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Who can be paged, and who a schedule or a reassignment can name.",
        "operationId": "user_index",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "users": [
                    {
                      "email": "ada@example.com",
                      "id": "9a2b…",
                      "name": "Ada Walker"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "List the responders in the account",
        "tags": [
          "users"
        ]
      }
    },
    "/api/v1/incidents/{id}": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "The same object the list renders — `docs/INCIDENT_API.md` §3 defines it once.",
        "operationId": "incident_show",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "emergency": true,
                    "id": "4c1f…",
                    "status": "triggered"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Read one incident",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v1/checkins/images": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Its own capability rather than part of the description, because the\nprivacy policy offers \"photographs and images\" separately.",
        "operationId": "checkin_images_consent_status",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "images_opt_in": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Whether you have opted in to photographs",
        "tags": [
          "checkins"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Withdrawing deletes the stored images.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_images_consent",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "opt_in": true
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "images_opt_in": true
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Grant or withdraw photograph consent",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/schedules/{schedule_id}/layers": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Layers stack: the last one that covers an instant wins.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "layer_index",
        "parameters": [
          {
            "description": "The schedule's identifier.",
            "in": "path",
            "name": "schedule_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "layers": [
                    {
                      "id": "aa11…",
                      "name": "Weekdays",
                      "position": 1
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "List a schedule's layers",
        "tags": [
          "schedules"
        ]
      },
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "A rotation over a set of members, with a restriction on when it applies.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "layer_create",
        "parameters": [
          {
            "description": "The schedule's identifier.",
            "in": "path",
            "name": "schedule_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "handoff_at": "09:00:00",
                "name": "Weekdays",
                "rotation": "weekly"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "layer": {
                    "id": "aa11…",
                    "name": "Weekdays"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Created."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Add a layer",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/overrides/{id}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "The rota underneath it applies again from the moment this returns.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "override_delete",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Remove an override",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/profile/photo": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The first of three calls: the server chooses the key and signs a `PUT`,\nthe device uploads straight to the bucket, and a third call makes the\nserver look at what actually arrived. Nothing renders until then, because\na presigned `PUT` is a licence to write arbitrary bytes.\n`docs/CHECKIN_API.md` §17.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_request_photo",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "byte_size": 184320,
                "content_type": "image/jpeg",
                "kind": "person",
                "taken_at": "2026-09-01"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "photo": {
                    "age_days": 5,
                    "id": "cc33…",
                    "kind": "person",
                    "taken_at": "2026-09-01",
                    "url": null
                  },
                  "upload_expires_at": "2026-09-06T17:12:11Z",
                  "upload_url": "https://…"
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Signed. Upload to `upload_url`, then confirm."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Mint a presigned upload for a photograph",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/handoffs/{id}/accept": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "From this moment the escalation path resolves to you for the handoff's window.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "handoff_accept",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "handoff": {
                    "id": "99ef…",
                    "status": "accepted"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Take the pager",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/incidents/{id}/reassign": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Moves the page to `user_id`, who is notified. The incident stays open —\nreassigning is not acknowledging on somebody else's behalf.",
        "operationId": "incident_reassign",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "user_id": "9a2b…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "assigned_user_id": "9a2b…",
                    "id": "4c1f…",
                    "status": "triggered"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Hand the incident to somebody else",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v1/checkins/{id}/arm": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Sets the deadline the miss is measured against. Optionally carries a\n`location` and a `details` object in one call, so a phone starting a walk\nmakes one request rather than three. Neither can fail the transition.",
        "operationId": "checkin_arm",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "deadline_at": "2026-09-06T18:15:00Z",
                "details": {
                  "destination_text": "the ridge",
                  "wearing": "red jacket"
                }
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "deadline_at": "2026-09-06T18:15:00Z",
                    "id": "5f0f…",
                    "state": "armed"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Arm — start the clock",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/checkins/profile": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "The half that does not change per walk: the vehicle, and the dated\nphotographs. `null` when you have typed nothing. `docs/CHECKIN_API.md` §16.",
        "operationId": "checkin_profile",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "profile": {
                    "photo": null,
                    "vehicle": {
                      "colour": "grey",
                      "make": "Subaru",
                      "model": "Outback",
                      "plate": "8XYZ123",
                      "year": 2019
                    },
                    "vehicle_photo": null
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Your reusable search description",
        "tags": [
          "checkins"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Refused with `409 consent_missing` without `:details` consent — a\n**refusal**, deliberately unlike the transitions: somebody filling in a\nform has asked a question and is owed an answer. The plate is encrypted\nat rest and nothing can query on it.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_profile",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "vehicle_make": "Subaru",
                "vehicle_model": "Outback",
                "vehicle_plate": "8XYZ123"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "profile": {
                    "vehicle": {
                      "make": "Subaru",
                      "model": "Outback"
                    }
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Set your reusable search description",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/handoffs/{id}/decline": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The offer closes and the rota is unchanged. The offerer is told.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "handoff_decline",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "handoff": {
                    "id": "99ef…",
                    "status": "declined"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Refuse the pager",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/{id}/satisfy": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "A timer goes idle; a daily rolls to its next occurrence. Send `code` when\nthe check-in requires one. Nothing in the response distinguishes a duress\nsatisfy from an ordinary one, and that is the design — `docs/CHECKIN_API.md`\n§12.",
        "operationId": "checkin_satisfy",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "code": "142857"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "deadline_at": null,
                    "id": "5f0f…",
                    "state": "idle"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "The one tap: \"I'm here\"",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/incidents/{id}/search/beacon": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The loudest thing this product can do to somebody's phone, so it is gated\non the subject's beacon consent and, on a duress activation, on an\nexplicit `confirm_duress: true` — only a literal `true`, so a client that\nsent the string `\"false\"` cannot light the phone of somebody under\ncoercion.\n\n`mode` is `steady`, `strobe` or `off`, and names the state rather than\ncarrying a boolean: \"off\" is a third thing rather than the absence of the\nother two. `docs/INCIDENT_API.md` §13.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "incident_beacon",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "confirm_duress": true,
                "mode": "strobe"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {
                  "command": {
                    "id": "77ab…",
                    "kind": "beacon_strobe",
                    "status": "queued"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Command queued."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Light the subject's torch and sound their phone",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v1/checkins": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Oldest first, and only ever your own. Each carries its `details` — what\nyou said you were wearing and where you said you were going — so the\nscreen renders from one read. `docs/CHECKIN_API.md` §3.",
        "operationId": "checkin_index",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkins": [
                    {
                      "deadline_at": "2026-09-06T18:15:00Z",
                      "details": null,
                      "id": "5f0f…",
                      "kind": "timer",
                      "label": "Evening walk",
                      "require_code": false,
                      "state": "armed"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "List your own check-ins",
        "tags": [
          "checkins"
        ]
      },
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "A `timer` is the ad-hoc \"expect me by 6:15\"; a `daily` recurs at\n`local_time` in `time_zone`. Each check-in mints its own source, and\n`escalation_schedule_id` on that source decides who a miss pages.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_create",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "kind": "timer",
                "label": "Evening walk",
                "reminder_lead_seconds": 900
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "id": "5f0f…",
                    "label": "Evening walk",
                    "state": "idle"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Created."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Create a check-in",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/schedules/{id}/on_call": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Resolves the layers, the overrides and the handoffs into a single answer.\nThis is the question the escalation path asks, exposed so a client can ask\nit too — `docs/SCHEDULE_API.md` §4.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_on_call",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "The instant to resolve at, ISO 8601. Defaults to now.",
            "in": "query",
            "name": "at",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "at": "2026-09-06T16:00:00Z",
                  "on_call": {
                    "user_id": "9a2b…",
                    "via": {
                      "position": 1,
                      "type": "layer"
                    }
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Who is on call right now",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/profile/photo/{id}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Removes the object and the row.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_delete_photo",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Delete a photograph",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/auth/logout": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Authenticated with the access token whose family it revokes, and a stale\none is accepted: revocation is never something to refuse. A client logs\nout by deregistering its device first and revoking second, so a phone\nwhose token lapsed does not end up signed out and still a push target.",
        "operationId": "auth_logout",
        "parameters": [],
        "responses": {
          "204": {
            "description": "Revoked."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Revoke this token family",
        "tags": [
          "auth"
        ]
      }
    },
    "/api/v1/receivers": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Hardware that lights, sounds, or relays a page. Their state and their enrolment.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "receiver_index",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "receivers": [
                    {
                      "certificate_expires_at": "2027-09-06T17:02:11Z",
                      "enrolled_at": "2026-09-06T17:02:11Z",
                      "hardware_id": "24:6f:28:aa:bb:cc",
                      "id": "bb22…",
                      "last_seen_at": "2026-09-06T17:40:00Z",
                      "model": "m5stack-basic",
                      "name": "Bay 3 beacon",
                      "scope": "account"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "List the account's receivers",
        "tags": [
          "receivers"
        ]
      },
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The claim is the one-time credential the device spends at\n`POST /receivers/enroll`, along with the `account_id` it belongs to. It is\nreturned once — `docs/RECEIVER_API.md` §3.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "receiver_create",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "hardware_id": "24:6f:28:aa:bb:cc",
                "model": "m5stack-basic",
                "name": "Bay 3 beacon"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "account_id": "14a1…",
                  "claim_expires_at": "2026-09-07T17:02:11Z",
                  "claim_token": "…",
                  "receiver": {
                    "id": "bb22…",
                    "model": "m5stack-basic",
                    "name": "Bay 3 beacon"
                  },
                  "receiver_host": "receivers.alertroster.com",
                  "user_id": "9a2b…"
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Created; the claim is in the response and will not be shown again."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Create a receiver and mint its claim",
        "tags": [
          "receivers"
        ]
      }
    },
    "/api/v1/schedules/{id}/roster": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "The same resolution as `on_call`, computed forward over a window so a\nclient can draw a rota rather than ask repeatedly.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_roster",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Start of the window, ISO 8601. Defaults to now.",
            "in": "query",
            "name": "from",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "End of the window, ISO 8601. Defaults to seven days after `from`, and must be after it.",
            "in": "query",
            "name": "to",
            "required": false,
            "schema": {
              "format": "date-time",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "from": "2026-09-06T16:00:00Z",
                  "segments": [
                    {
                      "ends_at": "2026-09-07T16:00:00Z",
                      "on_call": {
                        "user_id": "9a2b…",
                        "via": {
                          "position": 1,
                          "type": "layer"
                        }
                      },
                      "starts_at": "2026-09-06T16:00:00Z"
                    }
                  ],
                  "to": "2026-09-13T16:00:00Z"
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "The look-ahead: who is on call, and when, over a window",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/{id}/extend": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "`expected_deadline_at`, when sent, must match the row — which is what\nmakes a lock-screen \"+15 minutes\" safe against a double tap and against\nextending a deadline a daily roll has already replaced.",
        "operationId": "checkin_extend",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "by_seconds": 900,
                "expected_deadline_at": "2026-09-06T18:15:00Z"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "deadline_at": "2026-09-06T18:30:00Z",
                    "id": "5f0f…",
                    "state": "armed"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Push the deadline out",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/receivers/catalogue": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "What a provisioning screen offers, and what firmware each model expects.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "receiver_catalogue",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "receivers": [
                    {
                      "chip": "ESP32",
                      "firmware": null,
                      "id": "m5stack-basic",
                      "name": "M5Stack Basic",
                      "status": "tested"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "The receiver models this account can enrol",
        "tags": [
          "receivers"
        ]
      }
    },
    "/api/v1/incidents/{id}/search": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Everything a responder looking for somebody can see: the captured trail,\nthe commands asked of the device, whether a fresh fix or the beacon is\navailable, and what the subject looks like. `docs/INCIDENT_API.md` §13.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "incident_search",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "search": {
                    "beacon": {
                      "available": false,
                      "reason": "not_opted_in",
                      "state": "off"
                    },
                    "checkin_id": "5f0f…",
                    "commands": [],
                    "locate": {
                      "available": true,
                      "reason": null
                    },
                    "positions": [],
                    "subject": null,
                    "subject_user_id": "9a2b…"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "The search panel for a missed check-in",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v2/incidents/{id}/acknowledge": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Stops the paging. A `POST` naming the transition, for the reason `/api/v1`'s is.",
        "operationId": "v2_incident_acknowledge",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "id": "4c1f…",
                    "status": "acknowledged"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "sync_key": []
          },
          {
            "account_token": []
          }
        ],
        "summary": "Acknowledge on behalf of the ticket",
        "tags": [
          "lane-b"
        ]
      }
    },
    "/api/v1/checkins/beacon": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "A client asks before it offers the capability at all.",
        "operationId": "checkin_beacon_status",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "beacon_opt_in": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Whether you have opted in to the beacon",
        "tags": [
          "checkins"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Withdrawing extinguishes a torch that is burning right now, which is why\nthe revoke is ungated on the same terms as location's.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_beacon_opt_in",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "opt_in": true
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "beacon_opt_in": true
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Grant or withdraw beacon consent",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/schedules/{id}/handoffs": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "An offer, not a fact: the recipient accepts or declines, and the pager\ndoes not move until they do. `docs/SCHEDULE_API.md` §6.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_create_handoff",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "ends_at": "2026-09-07T00:00:00Z",
                "starts_at": "2026-09-06T18:00:00Z",
                "to_user_id": "9a2b…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "handoff": {
                    "id": "99ef…",
                    "status": "pending"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Offered."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Offer the pager to somebody",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/receivers/enroll": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "**Unauthenticated by construction**: the claim in the body *is* the\ncredential, which is why this route carries no `Authorization` header and\nis metered per client IP like the other unauthenticated sign-in routes.\nThe device sends a CSR and gets back a certificate it then uses for mTLS.\n`docs/RECEIVER_API.md` §4.",
        "operationId": "receiver_enroll",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "account_id": "14a1…",
                "claim_token": "…",
                "csr": "-----BEGIN CERTIFICATE REQUEST-----\n…"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "ca_certificate": "-----BEGIN CERTIFICATE-----\n…",
                  "certificate": "-----BEGIN CERTIFICATE-----\n…",
                  "certificate_expires_at": "2027-09-06T17:02:11Z",
                  "receiver": {
                    "enrolled_at": "2026-09-06T17:02:11Z",
                    "id": "bb22…",
                    "name": "Bay 3 beacon"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Enrolled; the certificate and the CA that signed it are in the response."
          }
        },
        "security": [],
        "summary": "Spend a claim for a client certificate",
        "tags": [
          "receivers"
        ]
      }
    },
    "/api/v1/handoffs/{id}/cancel": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Only the offerer can cancel, and only while the offer is still open.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "handoff_cancel",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "handoff": {
                    "id": "99ef…",
                    "status": "cancelled"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Withdraw an offer you made",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v2/incidents": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The sync lane: the caller is a ticket system of record and gets the\nincident back, because it has somewhere to put it. Idempotent on\n`dedup_key` — the same key answers with the same incident rather than\nopening a second one.",
        "operationId": "v2_incident_create",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "dedup_key": "INC-4471",
                "title": "Payment gateway timeouts",
                "urgency": "high"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "incident": {
                    "dedup_key": "INC-4471",
                    "id": "4c1f…",
                    "status": "triggered"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Created, or the existing incident for this `dedup_key`."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "sync_key": []
          },
          {
            "account_token": []
          }
        ],
        "summary": "Open an incident, synchronously",
        "tags": [
          "lane-b"
        ]
      }
    },
    "/api/v1/schedules": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "Every on-call schedule in the account.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_index",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "schedules": [
                    {
                      "id": "7714…",
                      "name": "Primary on-call",
                      "time_zone": "America/Denver"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "List schedules",
        "tags": [
          "schedules"
        ]
      },
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "A schedule carries the time zone its rotations are computed in.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "schedule_create",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "name": "Primary on-call",
                "time_zone": "America/Denver"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "schedule": {
                    "id": "7714…",
                    "name": "Primary on-call"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Created."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Create a schedule",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/layers/{id}/restrictions": {
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "The windows within a week the layer covers — \"weekdays, nine to six\".\nThe whole set, for `members`' reason.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "layer_set_restrictions",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "restrictions": [
                  {
                    "day": "monday",
                    "from": "09:00:00",
                    "until": "18:00:00"
                  }
                ]
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "layer": {
                    "id": "aa11…"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Set when a layer applies",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/commands/{id}/ack": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "A `POST` naming the answer rather than a `PATCH` on the command: a device\nreports what happened, it does not edit a row. `outcome` is one of `ok`,\n`unsupported`, `denied` or `unavailable`.\n\nAccepted on a stale token, because a phone woken by a silent push has\nwhatever token it woke with, and a refresh in the middle of a search is a\nround trip nobody can afford. The answer is the same three-key device\npayload every command surface uses — no incident, no responder, no reason.",
        "operationId": "checkin_ack_command",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "outcome": "ok"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "command": {
                    "command_id": "77aa…",
                    "expires_at": "2026-09-06T17:12:11Z",
                    "kind": "locate"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Report what happened to a command",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/layers/{id}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "The layers beneath it apply where it used to.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "layer_delete",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Delete a layer",
        "tags": [
          "schedules"
        ]
      },
      "patch": {
        "callbacks": {},
        "deprecated": false,
        "description": "Its name, its rotation, or where it sits in the stack.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "layer_update",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "name": "Weekdays (early)"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "layer": {
                    "id": "aa11…",
                    "name": "Weekdays (early)"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Reconfigure a layer",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/checkins/{id}": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Its source is left alone — it may carry incident history.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_delete",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Delete a check-in",
        "tags": [
          "checkins"
        ]
      },
      "patch": {
        "callbacks": {},
        "deprecated": false,
        "description": "Label, reminder lead, a daily's zone or time, and the escalation\nschedule. `kind` is immutable and the armed state moves only through the\ntransitions.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_update",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "label": "Evening walk with the dog"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "id": "5f0f…",
                    "label": "Evening walk with the dog"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Reconfigure a check-in",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/handoffs": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "What somebody has offered you, and what you have offered and not heard\nback on. Narrow with `status`.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "handoff_index",
        "parameters": [
          {
            "description": "One of `pending`, `accepted`, `declined` or `cancelled`.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "enum": [
                "pending",
                "accepted",
                "declined",
                "cancelled"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "handoffs": [
                    {
                      "id": "99ef…",
                      "status": "pending",
                      "to_user_id": "9a2b…"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Handoffs waiting on you",
        "tags": [
          "schedules"
        ]
      }
    },
    "/api/v1/incidents": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "What a responder's list screen is built from. `docs/INCIDENT_API.md` §2\nstates the latency budget this route is held to, because the list is what\na phone opens to while a page is still sounding.",
        "operationId": "incident_index",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "incidents": [
                    {
                      "emergency": true,
                      "id": "4c1f…",
                      "priority": "emergency",
                      "status": "triggered",
                      "title": "api-gateway 5xx above threshold",
                      "triggered_at": "2026-09-06T17:02:11Z",
                      "urgency": "high"
                    }
                  ]
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "List incidents",
        "tags": [
          "incidents"
        ]
      }
    },
    "/api/v1/auth/request_link": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Emails a sign-in link and a short login code to `email`. Answers `202`\nwhether or not the address belongs to anybody: the response must not be a\nway to ask which email addresses have accounts.",
        "operationId": "auth_request_link",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "email": "ada@example.com"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "example": {},
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Accepted. Sent if the address is known; the response is the same either way."
          }
        },
        "security": [],
        "summary": "Request a magic link",
        "tags": [
          "auth"
        ]
      }
    },
    "/api/v1/checkins/details": {
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "How a client learns whether to bother offering the form at all.",
        "operationId": "checkin_details_consent_status",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "details_opt_in": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Whether you have opted in to a search description",
        "tags": [
          "checkins"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Withdrawing deletes what was already stored — the description, the\nvehicle, and the photographs. Ungated on the account flag for the reason\nlocation's revoke is.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_details_consent",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "opt_in": true
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "details_opt_in": true
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Grant or withdraw search-description consent",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/checkins/profile/photo/{id}/confirm": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "The server `HEAD`s the object and believes what it finds rather than what\nthe upload claimed. Only after this does the photograph get a URL — and\nit is handed out with its date and never without it, because a six-month-old\nphotograph presented as current sends people looking for somebody in a\ncoat they no longer own.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_confirm_photo",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "photo": {
                    "age_days": 5,
                    "id": "cc33…",
                    "kind": "person",
                    "taken_at": "2026-09-01",
                    "url": "https://…"
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Confirm an uploaded photograph",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/checkins/{id}/require_code": {
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Refused with `409 no_code_set` if the caller has no check-in code yet: a\nflag that could be turned on without one would lock somebody out of their\nown check-in.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_require_code",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "require_code": true
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "checkin": {
                    "id": "5f0f…",
                    "require_code": true
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Require a code to satisfy or cancel this check-in",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/checkins/code": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "Any check-in that required it stops requiring it.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_delete_code",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "code_set": false,
                  "duress_code_set": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Clear your check-in code",
        "tags": [
          "checkins"
        ]
      },
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "The only thing any surface ever says about either code. Neither is\nrendered anywhere, and `docs/CHECKIN_API.md` §11 states that as a\ncontract rather than a current fact.",
        "operationId": "checkin_code_status",
        "parameters": [],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "code_set": true,
                  "duress_code_set": false
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Whether a check-in code and a duress code are set",
        "tags": [
          "checkins"
        ]
      },
      "put": {
        "callbacks": {},
        "deprecated": false,
        "description": "Optionally sets a duress code in the same call — both travel through one\nchangeset because the rule that matters most about them, that they\ndiffer, can only be checked with both plaintexts in hand.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "checkin_put_code",
        "parameters": [],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "code": "142857",
                "duress_code": "271828"
              },
              "schema": {
                "additionalProperties": true,
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "code_set": true,
                  "duress_code_set": true
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Set or replace your check-in code",
        "tags": [
          "checkins"
        ]
      }
    },
    "/api/v1/incidents/{id}/report": {
      "delete": {
        "callbacks": {},
        "deprecated": false,
        "description": "The link stops answering on the next request. `204` whether or not one\nwas live — somebody saying \"take that page down\" needs the page down, not\na `404` about a link that was already gone. `docs/INCIDENT_API.md` §14.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "incident_delete_report",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Withdrawn."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Withdraw the report link",
        "tags": [
          "incidents"
        ]
      },
      "get": {
        "callbacks": {},
        "deprecated": false,
        "description": "`{\"report\": null}` when nothing has been shared. `view_count` and\n`last_viewed_at` answer the question a roster member actually has while a\nsearch is running — has anybody opened this — without reading the\ntimeline. `docs/INCIDENT_API.md` §14.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "incident_report",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "report": {
                    "expires_at": "2026-09-14T18:14:02Z",
                    "id": "b41c…",
                    "url": "https://alertroster.com/r/…",
                    "view_count": 3
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Success."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "The keyed link to this incident's responder report",
        "tags": [
          "incidents"
        ]
      },
      "post": {
        "callbacks": {},
        "deprecated": false,
        "description": "Mints the capability URL a roster member hands to a search team, and\nreturns the one that already exists rather than a second — there is one\nlive link per incident, so sharing twice cannot invalidate a QR code\nalready printed and carried. `201` on a fresh mint, `200` on the link\nthat was already there.\n\n**The response body is a credential.** Anyone holding that URL can read\nthe subject's photograph, description and captured positions with no\nlogin, which is why this route demands a current access token and why the\nlink is revocable, expiring and logged. `docs/INCIDENT_API.md` §14.\n\n**Requires a current access token.** The five-minute grace the rest of `/api/v1` allows does not apply here: this route changes who gets paged, and nobody needs to do that in the five minutes before a refresh completes. A lapsed token answers `401`; refresh and retry.",
        "operationId": "incident_create_report",
        "parameters": [
          {
            "description": "The resource's identifier.",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "example": {
                  "report": {
                    "expires_at": "2026-09-14T18:14:02Z",
                    "id": "b41c…",
                    "url": "https://alertroster.com/r/…",
                    "view_count": 0
                  }
                },
                "schema": {
                  "additionalProperties": true,
                  "type": "object"
                }
              }
            },
            "description": "Shared."
          },
          "401": {
            "description": "Missing, malformed, or expired credential."
          }
        },
        "security": [
          {
            "access_token": []
          }
        ],
        "summary": "Share a missing-person report with responders outside the roster",
        "tags": [
          "incidents"
        ]
      }
    }
  },
  "security": [],
  "servers": [
    {
      "description": "This server",
      "url": "/",
      "variables": {}
    },
    {
      "url": "https://alertroster.com",
      "variables": {}
    }
  ],
  "tags": [
    {
      "description": "Signing in and staying signed in. See `docs/AUTHENTICATION.md` in the repository.",
      "name": "auth"
    },
    {
      "description": "Registering a phone as a push target. See `docs/DEVICE_API.md` in the repository.",
      "name": "devices"
    },
    {
      "description": "The page itself: read it, acknowledge, resolve, reassign. See `docs/INCIDENT_API.md` in the repository.",
      "name": "incidents"
    },
    {
      "description": "A heartbeat for a person — arm, extend, satisfy, cancel. See `docs/CHECKIN_API.md` in the repository.",
      "name": "checkins"
    },
    {
      "description": "On-call schedules, who is on call, handoffs and overrides. See `docs/SCHEDULE_API.md` in the repository.",
      "name": "schedules"
    },
    {
      "description": "Hardware receivers: claim, enrol, and the certificate that follows. See `docs/RECEIVER_API.md` in the repository.",
      "name": "receivers"
    },
    {
      "description": "The responders in an account. See `docs/AUTHENTICATION.md` in the repository.",
      "name": "users"
    },
    {
      "description": "The async firehose a monitor fires events at. See `docs/LANE_A_API.md` in the repository.",
      "name": "lane-a"
    },
    {
      "description": "The synchronous surface a ticket system of record calls. See `docs/LANE_B_API.md` in the repository.",
      "name": "lane-b"
    }
  ]
}