{
  "openapi": "3.1.0",
  "info": {
    "title": "HRC Ledger API",
    "version": "v1",
    "description": "The HRC Ledger API gives a healthcare investment banker's own code what HRC Ledger holds: healthcare organizations and public contracts, your saved Lists, action plans, drafts and conversations, and the HRC Ledger assistant.\n\n**Authenticate** with an API key in one header: `Authorization: Bearer hck_live_...`. A key works on any plan; each key carries the scopes it was made with.\n\n**One envelope** on every route: `{ ok: true, data, page?, total? }`, or `{ ok: false, error: { code, message, ...details } }`. Every response carries an `X-Request-Id` header; quote it when you ask us about a call.\n\n**Versioning is in the path** (`/api/v1`): a change that removes or retypes a field in `data` ships at a new path; adding a field does not.\n\n**Guides** — getting started, keys and scopes, errors, pagination and versioning, and the changelog — are at https://docs.hrcledger.com/developer/.",
    "contact": {
      "name": "HRC Ledger",
      "url": "https://hrcledger.com/contact",
      "email": "contact@societyhealth.co"
    },
    "license": {
      "name": "HRC Ledger terms",
      "url": "https://hrcledger.com/terms"
    }
  },
  "externalDocs": {
    "description": "Getting started",
    "url": "https://docs.hrcledger.com/developer/"
  },
  "tags": [
    {
      "name": "contracts",
      "description": "Public healthcare contracts and solicitations: search them and read one."
    },
    {
      "name": "organizations",
      "description": "Hospitals, health systems and other provider organizations: search the market."
    },
    {
      "name": "lists",
      "description": "Lists of organizations you save: list, read with rows, create, add and remove rows, rename, archive, export as CSV."
    },
    {
      "name": "actions",
      "description": "Action plans and their steps: your steps across every plan in one call, a step's status, and plans to read, create, edit and archive."
    },
    {
      "name": "drafts",
      "description": "Drafts you or the assistant wrote: list, read, the approved ones with their text, save, edit as your own text, archive."
    },
    {
      "name": "reviews",
      "description": "Approve a draft or plan version, as the key's owner, with the approval scope for its kind. An assistant's proposal is never decided by key."
    },
    {
      "name": "conversations",
      "description": "Your conversations with the assistant: list, read with every turn, its citations and the work it saved, rename, delete."
    },
    {
      "name": "memory",
      "description": "What HRC Ledger knows about your firm: the confirmed entries the assistant is given, with where each came from."
    },
    {
      "name": "agent",
      "description": "Ask the HRC Ledger assistant a question and get its answer, with the records it cites."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Read",
      "tags": [
        "contracts",
        "organizations"
      ]
    },
    {
      "name": "Artifacts",
      "tags": [
        "lists",
        "actions",
        "drafts",
        "reviews",
        "conversations",
        "memory"
      ]
    },
    {
      "name": "The agent",
      "tags": [
        "agent"
      ]
    }
  ],
  "servers": [
    {
      "url": "https://hrcledger.com"
    }
  ],
  "security": [
    {
      "bearerKey": []
    }
  ],
  "paths": {
    "/api/v1/contracts": {
      "get": {
        "operationId": "listContracts",
        "tags": [
          "contracts"
        ],
        "summary": "Search contracts",
        "description": "Use this to find contracts and solicitations by keyword, place, buyer, code, value or due date. Returns one page of contracts with the true `total` across every page. Uncapped for every key; your plan only sets how far back the archive reaches.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "jurisdiction",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "buyerType",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "setAside",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "opportunityKind",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "personas",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "buyerClass",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "naics",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "psc",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "recordType",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closing_soon",
                "closed"
              ]
            }
          },
          {
            "name": "minValue",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "maxValue",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "dueBefore",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "dueAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "postedAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "firstSeenAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "window",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "commercialCategory",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includePastDue",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeArchived",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "relevance",
                "fit",
                "recent",
                "deadline",
                "value_desc",
                "value_asc"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The requested page, with the true total across all pages.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": [
                    {
                      "slug": "oh-mercy-ehr-2026",
                      "source": "sam",
                      "externalId": "36C25026Q0001",
                      "title": "Electronic health record replacement",
                      "description": "Replace the inpatient EHR across three campuses.",
                      "buyerName": "Mercy Health",
                      "buyerType": "health_system",
                      "jurisdiction": "OH",
                      "agency": "Department of Veterans Affairs",
                      "naics": "541512",
                      "psc": "DA01",
                      "valueEstimate": 4500000,
                      "postedDate": "2026-09-01",
                      "questionsDueDate": "2026-09-20",
                      "responseDueDate": "2026-10-30",
                      "awardDate": "2026-12-15",
                      "performanceStart": "2027-01-01",
                      "performanceEnd": "2029-12-31",
                      "setAside": "SBA",
                      "url": "https://sam.gov/opp/36C25026Q0001/view"
                    }
                  ],
                  "page": 1,
                  "total": 1
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicContract"
                      }
                    },
                    "page": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/contracts/{slug}": {
      "get": {
        "operationId": "getContract",
        "tags": [
          "contracts"
        ],
        "summary": "Read one contract",
        "description": "Use this when you already have a contract's `slug` (from a search or a citation). Returns that one contract, or `404 not_found` when no contract has the slug.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The contract.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "slug": "oh-mercy-ehr-2026",
                    "source": "sam",
                    "externalId": "36C25026Q0001",
                    "title": "Electronic health record replacement",
                    "description": "Replace the inpatient EHR across three campuses.",
                    "buyerName": "Mercy Health",
                    "buyerType": "health_system",
                    "jurisdiction": "OH",
                    "agency": "Department of Veterans Affairs",
                    "naics": "541512",
                    "psc": "DA01",
                    "valueEstimate": 4500000,
                    "postedDate": "2026-09-01",
                    "questionsDueDate": "2026-09-20",
                    "responseDueDate": "2026-10-30",
                    "awardDate": "2026-12-15",
                    "performanceStart": "2027-01-01",
                    "performanceEnd": "2029-12-31",
                    "setAside": "SBA",
                    "url": "https://sam.gov/opp/36C25026Q0001/view"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicContract"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/market/orgs": {
      "get": {
        "operationId": "listOrgs",
        "tags": [
          "organizations"
        ],
        "summary": "Search organizations",
        "description": "Use this to find hospitals, health systems and other providers by segment, state, metro, size or name. Returns one page of organizations, each with its CCN, NPI and EIN where we hold them, and the true `total`. Uncapped for every key.",
        "parameters": [
          {
            "name": "segment",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "cbsa",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "has_aco_participation",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "minBeds",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "maxBeds",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "beds_desc",
                "locations_desc",
                "name"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The requested page, with the true total across all pages.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": [
                    {
                      "slug": "mercy-health",
                      "name": "Mercy Health",
                      "segment": "health_system",
                      "state": "OH",
                      "locationCount": 12,
                      "staffedBeds": 3400,
                      "ccn": "360001",
                      "npi": "1234567893",
                      "ein": "341234567"
                    }
                  ],
                  "page": 1,
                  "total": 1
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicOrg"
                      }
                    },
                    "page": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "absence": {
                      "type": "object",
                      "description": "Set when an empty answer is our gap, not a finding of none (the ACO filter while no ACO participation is held).",
                      "properties": {
                        "reason": {
                          "const": "not_held"
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/ask": {
      "post": {
        "operationId": "ask",
        "tags": [
          "agent"
        ],
        "summary": "Ask the assistant a question",
        "description": "Use this to ask the HRC Ledger assistant one question and get its answer, the records it cites and what it read. Requires the `agent:ask` scope, which is separate from the read scopes because asking spends money. It does not stream, does not write and does not read the web. A run that stopped at a ceiling is a 200 carrying `status: \"partial\"` and a `stopped_reason` — an incomplete answer the caller can tell is incomplete, not an error. Bounded to 200 runs per key per UTC day.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "question": "Which Ohio hospitals changed EHR vendor this year?",
                "contract": "general"
              },
              "schema": {
                "$ref": "#/components/schemas/AskRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The run's answer. `status` may be `partial` or `failed`.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "run": {
                      "id": "Ab3-_cD9efGhIjKlMnOpQ",
                      "url": "https://hrcledger.com/runs/Ab3-_cD9efGhIjKlMnOpQ",
                      "status": "complete",
                      "contract": "general",
                      "stopped_reason": null,
                      "partial_note": null
                    },
                    "conversation": {
                      "id": "Zx9-_aB8cdEfGhIjKlMnO",
                      "url": "https://hrcledger.com/ask/Zx9-_aB8cdEfGhIjKlMnO",
                      "turn": 1
                    },
                    "answer": "Two Ohio hospitals posted an EHR replacement this year.",
                    "citations": [
                      {
                        "claim": "Two Ohio hospitals posted an EHR replacement this year.",
                        "record": {
                          "type": "contract",
                          "key": "oh-mercy-ehr-2026"
                        },
                        "url": "https://hrcledger.com/contracts/oh-mercy-ehr-2026",
                        "absence": null
                      }
                    ],
                    "rows": [
                      {
                        "type": "contract",
                        "key": "oh-mercy-ehr-2026",
                        "row": {
                          "title": "Electronic health record replacement"
                        }
                      }
                    ],
                    "coverage": {
                      "views": [
                        {
                          "view": "agent.contracts",
                          "rows_returned": 2
                        }
                      ],
                      "steps": 3,
                      "note": "What this answer is built on: query: 2 rows.",
                      "unreadable": 0
                    },
                    "usage": {
                      "cost_cents": 4,
                      "input_tokens": 12000,
                      "output_tokens": 400,
                      "cached_tokens": 9000
                    },
                    "feedback": {
                      "url": "/api/agent/feedback",
                      "run": "Ab3-_cD9efGhIjKlMnOpQ",
                      "controls": [
                        "rating",
                        "used"
                      ]
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/AskData"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "409": {
            "$ref": "#/components/responses/Paused"
          },
          "422": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/lists": {
      "get": {
        "operationId": "listLists",
        "tags": [
          "lists"
        ],
        "summary": "List your Lists",
        "description": "Your saved Lists of organizations, newest change first, without their rows. Use this when you need a List's id, or want to see which Lists exist before reading one. Newest change first, 25 to a page by default. Following is not listed here. `total` is null: this read does not count.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "purpose",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "general",
                "targets",
                "audience"
              ]
            }
          },
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "items": [
                      {
                        "id": "Lst8kQ2mZp4xV7nR1tYw",
                        "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                        "name": "Virginia systems",
                        "purpose": "general",
                        "archived": false,
                        "revisionNo": 2,
                        "updatedAt": "2026-10-16T14:02:11.000Z"
                      }
                    ],
                    "nextCursor": null,
                    "total": null
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "items",
                        "nextCursor",
                        "total"
                      ],
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicList"
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` for the next page; null on the last."
                        },
                        "total": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Every match, counted; null where the read does not count."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "operationId": "createList",
        "tags": [
          "lists"
        ],
        "summary": "Make a List",
        "description": "Make a new List, optionally with organizations on it. Send an Idempotency-Key so a retry makes one List, not two. Use this when someone asks to save a set of organizations. Answers `201` with the List. The same `Idempotency-Key` and body again answers `200` with the same id; another body under that key is `409 idempotency_conflict`. Rows added here read \"by API key\" in the app.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "name": "Virginia systems",
                "purpose": "targets",
                "rows": [
                  41,
                  57
                ]
              },
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "purpose": {
                    "default": "general",
                    "type": "string",
                    "enum": [
                      "general",
                      "targets",
                      "audience"
                    ]
                  },
                  "rows": {
                    "minItems": 1,
                    "maxItems": 10000,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0
                    }
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A retry: the same `Idempotency-Key` and body as a `201` before it; the same id.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Lst8kQ2mZp4xV7nR1tYw",
                    "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                    "name": "Virginia systems",
                    "purpose": "general",
                    "archived": false,
                    "revisionNo": 2,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicList"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Made; a retry with the same key and body answers `200` with the same id.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Lst8kQ2mZp4xV7nR1tYw",
                    "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                    "name": "Virginia systems",
                    "purpose": "general",
                    "archived": false,
                    "revisionNo": 2,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicList"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/lists/{id}": {
      "get": {
        "operationId": "readList",
        "tags": [
          "lists"
        ],
        "summary": "Read a List and a page of its rows",
        "description": "One List and a page of its rows: each organization's name, address and when it was added. Use this when you have a List's id and need the organizations on it. Rows are in the order they were added. An unknown id and another account's List are the same `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "list": {
                      "id": "Lst8kQ2mZp4xV7nR1tYw",
                      "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                      "name": "Virginia systems",
                      "purpose": "general",
                      "archived": false,
                      "revisionNo": 2,
                      "updatedAt": "2026-10-16T14:02:11.000Z"
                    },
                    "rows": {
                      "items": [
                        {
                          "rowId": 4101,
                          "kind": "organization",
                          "key": "41",
                          "name": "Inova Health System",
                          "organizationId": 41,
                          "url": "https://hrcledger.com/organizations/inova-health-system",
                          "note": "Expanding cardiology",
                          "priority": 2,
                          "addedVia": "api_key",
                          "addedAt": "2026-10-16T14:02:11.000Z"
                        }
                      ],
                      "nextCursor": null,
                      "total": 1
                    }
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "list",
                        "rows"
                      ],
                      "properties": {
                        "list": {
                          "$ref": "#/components/schemas/PublicList"
                        },
                        "rows": {
                          "type": "object",
                          "required": [
                            "items",
                            "nextCursor",
                            "total"
                          ],
                          "properties": {
                            "items": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/PublicListRow"
                              }
                            },
                            "nextCursor": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Pass as `cursor` for the next page; null on the last."
                            },
                            "total": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "description": "Every match, counted; null where the read does not count."
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "patch": {
        "operationId": "renameList",
        "tags": [
          "lists"
        ],
        "summary": "Rename a List",
        "description": "Give a List a new name. Nothing else about it changes. Use this when someone asks to rename a List. Changes the name and nothing else, as one new version.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "name": "Virginia health systems"
              },
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Lst8kQ2mZp4xV7nR1tYw",
                    "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                    "name": "Virginia systems",
                    "purpose": "general",
                    "archived": false,
                    "revisionNo": 2,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicList"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/lists/{id}/rows": {
      "post": {
        "operationId": "changeListRows",
        "tags": [
          "lists"
        ],
        "summary": "Add or remove organizations on a List",
        "description": "Add organizations to a List, take them off, or both, by their ids. Use this when someone asks to change which organizations are on a List. Send `add`, `remove` or both; all of it is one new version. An organization already on the List is counted, not added twice; one that is not on it cannot be removed (`422 unknown_row`). Adding needs no version; a removal is checked against the version current when it arrives.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "add": [
                  41,
                  57
                ],
                "remove": [
                  12
                ]
              },
              "schema": {
                "type": "object",
                "properties": {
                  "add": {
                    "minItems": 1,
                    "maxItems": 10000,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0
                    }
                  },
                  "remove": {
                    "minItems": 1,
                    "maxItems": 10000,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "exclusiveMinimum": 0
                    }
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Lst8kQ2mZp4xV7nR1tYw",
                    "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                    "name": "Virginia systems",
                    "purpose": "general",
                    "archived": false,
                    "revisionNo": 2,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicList"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/lists/{id}/archive": {
      "post": {
        "operationId": "archiveList",
        "tags": [
          "lists"
        ],
        "summary": "Archive a List",
        "description": "Archive a List, which is how a List is deleted. It leaves every list view; the app can restore it. Use this when someone asks to delete or archive a List. Archiving is how a List is deleted; the owner may restore it in the app. Only the owner may archive (`403 owner_only`).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Lst8kQ2mZp4xV7nR1tYw",
                    "url": "https://hrcledger.com/lists/items/Lst8kQ2mZp4xV7nR1tYw",
                    "name": "Virginia systems",
                    "purpose": "general",
                    "archived": true,
                    "revisionNo": 2,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicList"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/lists/{id}/export.csv": {
      "get": {
        "operationId": "exportList",
        "tags": [
          "lists"
        ],
        "summary": "Download a List as CSV",
        "description": "A List's rows as a CSV file, the same file the app downloads. Use this when someone wants the whole List in a spreadsheet or another tool. The same file the app downloads: one row per organization, with its note and priority.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The CSV file.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                },
                "example": "Name,Note,Priority,Why now,Fits\r\nInova Health System,Expanding cardiology,2,,\r\n"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/actions/steps": {
      "get": {
        "operationId": "mySteps",
        "tags": [
          "actions"
        ],
        "summary": "Your steps across every plan",
        "description": "Steps across all your plans in one page, with the total: filter by status, due date and who owns them. Use this when someone asks what is due, late or blocked, without reading each plan. One page with the counted `total`, soonest due first and undated last. `dueBefore` and `dueAfter` are inclusive; a step with no due date matches neither. `assignee=me` (the default) is steps assigned to you; `any` is every step of a plan you can read.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "todo",
                  "in_progress",
                  "blocked",
                  "done",
                  "cancelled"
                ]
              }
            },
            "style": "form",
            "explode": true
          },
          {
            "name": "dueBefore",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "dueAfter",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "assignee",
            "in": "query",
            "required": false,
            "schema": {
              "default": "me",
              "type": "string",
              "enum": [
                "me",
                "any"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "items": [
                      {
                        "planId": "Pln5tH8jKw2qR6mX9vBz",
                        "planTitle": "Win Inova",
                        "planUrl": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                        "stepId": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assigneeUserId": 7,
                        "dueDate": "2026-10-21",
                        "revisionNo": 3
                      }
                    ],
                    "nextCursor": null,
                    "total": 1
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "items",
                        "nextCursor",
                        "total"
                      ],
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicStepRow"
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` for the next page; null on the last."
                        },
                        "total": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Every match, counted; null where the read does not count."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/actions/plans": {
      "get": {
        "operationId": "listPlans",
        "tags": [
          "actions"
        ],
        "summary": "List your action plans",
        "description": "Your action plans, newest change first, without their steps. Use this when you need a plan's id, or want to see which plans exist. Newest change first, without steps. `total` is null: this read does not count.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "items": [
                      {
                        "id": "Pln5tH8jKw2qR6mX9vBz",
                        "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                        "title": "Win Inova",
                        "objective": "Win the Inova imaging contract",
                        "archived": false,
                        "revisionNo": 3,
                        "updatedAt": "2026-10-16T14:02:11.000Z"
                      }
                    ],
                    "nextCursor": null,
                    "total": null
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "items",
                        "nextCursor",
                        "total"
                      ],
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicPlanSummary"
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` for the next page; null on the last."
                        },
                        "total": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Every match, counted; null where the read does not count."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "operationId": "createPlan",
        "tags": [
          "actions"
        ],
        "summary": "Make an action plan",
        "description": "Make a new action plan with its steps. Send an Idempotency-Key so a retry makes one plan, not two. Use this when someone asks to plan the work for an account or a pursuit. Answers `201` with the plan; the same `Idempotency-Key` and body again answers `200` with the same id.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "title": "Win Inova",
                "objective": "Win the Inova imaging contract",
                "purpose": "pursuit",
                "steps": [
                  {
                    "title": "Call the CFO",
                    "dueDate": "2026-10-21",
                    "assigneeUserId": 7
                  },
                  {
                    "title": "Send the security review"
                  }
                ]
              },
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "objective": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "purpose": {
                    "default": "general",
                    "type": "string",
                    "enum": [
                      "general",
                      "pursuit"
                    ]
                  },
                  "steps": {
                    "default": [],
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200
                        },
                        "dueDate": {
                          "type": "string",
                          "format": "date"
                        },
                        "assigneeUserId": {
                          "type": "integer",
                          "exclusiveMinimum": 0
                        }
                      },
                      "required": [
                        "title"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "title",
                  "objective"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A retry: the same `Idempotency-Key` and body as a `201` before it; the same id.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Pln5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                    "title": "Win Inova",
                    "objective": "Win the Inova imaging contract",
                    "archived": false,
                    "steps": [
                      {
                        "id": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assignee": {
                          "userId": 7,
                          "label": null
                        },
                        "dueDate": "2026-10-21",
                        "blockedReason": null
                      },
                      {
                        "id": "t_Hj7kL9mN",
                        "title": "Send the security review",
                        "status": "blocked",
                        "assignee": {
                          "userId": null,
                          "label": "Dana at Inova"
                        },
                        "dueDate": null,
                        "blockedReason": "Waiting on their legal team"
                      }
                    ],
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicPlan"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Made; a retry with the same key and body answers `200` with the same id.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Pln5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                    "title": "Win Inova",
                    "objective": "Win the Inova imaging contract",
                    "archived": false,
                    "steps": [
                      {
                        "id": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assignee": {
                          "userId": 7,
                          "label": null
                        },
                        "dueDate": "2026-10-21",
                        "blockedReason": null
                      },
                      {
                        "id": "t_Hj7kL9mN",
                        "title": "Send the security review",
                        "status": "blocked",
                        "assignee": {
                          "userId": null,
                          "label": "Dana at Inova"
                        },
                        "dueDate": null,
                        "blockedReason": "Waiting on their legal team"
                      }
                    ],
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicPlan"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/actions/plans/{id}": {
      "get": {
        "operationId": "readPlan",
        "tags": [
          "actions"
        ],
        "summary": "Read an action plan",
        "description": "One action plan with every step: its status, owner, due date and why it is blocked. Use this when you have a plan's id and need its steps. Every step, in order, with its status, owner, due date and why it is blocked.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Pln5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                    "title": "Win Inova",
                    "objective": "Win the Inova imaging contract",
                    "archived": false,
                    "steps": [
                      {
                        "id": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assignee": {
                          "userId": 7,
                          "label": null
                        },
                        "dueDate": "2026-10-21",
                        "blockedReason": null
                      },
                      {
                        "id": "t_Hj7kL9mN",
                        "title": "Send the security review",
                        "status": "blocked",
                        "assignee": {
                          "userId": null,
                          "label": "Dana at Inova"
                        },
                        "dueDate": null,
                        "blockedReason": "Waiting on their legal team"
                      }
                    ],
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicPlan"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "patch": {
        "operationId": "editPlan",
        "tags": [
          "actions"
        ],
        "summary": "Change an action plan",
        "description": "Change a plan: add, edit, reorder or remove steps, or rename it, in one version. Send the version you read; a newer one is a conflict carrying it. Use this when someone asks to change a plan's steps. `ops` are the plan's own operations, applied as one new version: `add_step`, `update_step`, `remove_step`, `move_step`, `set_step_status` and `set_field` (`title`, `objective`). `expectedRevisionNo` is required for a plan; a newer version is `409 revision_conflict` carrying it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "expectedRevisionNo": 3,
                "ops": [
                  {
                    "op": "update_step",
                    "stepId": "t_Ab3dE5fG",
                    "dueDate": "2026-10-23"
                  }
                ]
              },
              "schema": {
                "type": "object",
                "properties": {
                  "ops": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": {}
                    }
                  },
                  "expectedRevisionNo": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  }
                },
                "required": [
                  "ops",
                  "expectedRevisionNo"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Pln5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                    "title": "Win Inova",
                    "objective": "Win the Inova imaging contract",
                    "archived": false,
                    "steps": [
                      {
                        "id": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assignee": {
                          "userId": 7,
                          "label": null
                        },
                        "dueDate": "2026-10-21",
                        "blockedReason": null
                      },
                      {
                        "id": "t_Hj7kL9mN",
                        "title": "Send the security review",
                        "status": "blocked",
                        "assignee": {
                          "userId": null,
                          "label": "Dana at Inova"
                        },
                        "dueDate": null,
                        "blockedReason": "Waiting on their legal team"
                      }
                    ],
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicPlan"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/actions/plans/{id}/steps/{stepId}/status": {
      "post": {
        "operationId": "setStepStatus",
        "tags": [
          "actions"
        ],
        "summary": "Move a step to a new status",
        "description": "Move one step to a new status, such as done or blocked (blocked needs a reason). No version id is needed; it refuses only if that step changed first. Use this when someone finishes or is stuck on a step. No version is sent: a change someone else saved first is kept, and this one is applied over it, unless they changed this step, which is `409 step_changed`. `blocked` needs `blockedReason`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "stepId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "status": "blocked",
                "blockedReason": "Waiting on their legal team"
              },
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "todo",
                      "in_progress",
                      "blocked",
                      "done",
                      "cancelled"
                    ]
                  },
                  "blockedReason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Pln5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                    "title": "Win Inova",
                    "objective": "Win the Inova imaging contract",
                    "archived": false,
                    "steps": [
                      {
                        "id": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assignee": {
                          "userId": 7,
                          "label": null
                        },
                        "dueDate": "2026-10-21",
                        "blockedReason": null
                      },
                      {
                        "id": "t_Hj7kL9mN",
                        "title": "Send the security review",
                        "status": "blocked",
                        "assignee": {
                          "userId": null,
                          "label": "Dana at Inova"
                        },
                        "dueDate": null,
                        "blockedReason": "Waiting on their legal team"
                      }
                    ],
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicPlan"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/actions/plans/{id}/archive": {
      "post": {
        "operationId": "archivePlan",
        "tags": [
          "actions"
        ],
        "summary": "Archive an action plan",
        "description": "Archive an action plan, which is how a plan is deleted; its steps leave every step list. Use this when someone asks to delete or archive a plan. Archiving is how a plan is deleted; its steps leave every step list at once.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Pln5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/actions/items/Pln5tH8jKw2qR6mX9vBz",
                    "title": "Win Inova",
                    "objective": "Win the Inova imaging contract",
                    "archived": true,
                    "steps": [
                      {
                        "id": "t_Ab3dE5fG",
                        "title": "Call the CFO",
                        "status": "in_progress",
                        "assignee": {
                          "userId": 7,
                          "label": null
                        },
                        "dueDate": "2026-10-21",
                        "blockedReason": null
                      },
                      {
                        "id": "t_Hj7kL9mN",
                        "title": "Send the security review",
                        "status": "blocked",
                        "assignee": {
                          "userId": null,
                          "label": "Dana at Inova"
                        },
                        "dueDate": null,
                        "blockedReason": "Waiting on their legal team"
                      }
                    ],
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicPlan"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/drafts": {
      "get": {
        "operationId": "listDrafts",
        "tags": [
          "drafts"
        ],
        "summary": "List your drafts",
        "description": "Your drafts, newest change first, without their text. Use this when you need a draft's id, or want to see which drafts exist or are approved. Newest change first, without their text. `approved=true` keeps only approved drafts, `approved=false` only the rest. `total` is null: this read does not count.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "approved",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "items": [
                      {
                        "id": "Drf5tH8jKw2qR6mX9vBz",
                        "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                        "title": "Imaging at Inova",
                        "purpose": "email",
                        "audience": "Inova's CIO",
                        "evidence": [
                          {
                            "type": "organization",
                            "key": "41",
                            "url": "https://hrcledger.com/orgs/inova"
                          }
                        ],
                        "approval": {
                          "revisionNo": 3,
                          "at": "2026-10-16T14:02:11.000Z"
                        },
                        "archived": false,
                        "revisionNo": 3,
                        "updatedAt": "2026-10-16T14:02:11.000Z"
                      }
                    ],
                    "nextCursor": null,
                    "total": null
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "items",
                        "nextCursor",
                        "total"
                      ],
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicDraftSummary"
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` for the next page; null on the last."
                        },
                        "total": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Every match, counted; null where the read does not count."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "post": {
        "operationId": "createDraft",
        "tags": [
          "drafts"
        ],
        "summary": "Save a draft",
        "description": "Save a draft someone wrote, such as an email: its subject and body. It is recorded as their own text. Send an Idempotency-Key so a retry saves one draft. Use this when someone asks to keep a draft in HRC Ledger. The `subject` is saved as the draft's title and the `body` as its one section. It is recorded as the key holder's own text with the key, never as written by the assistant. Answers `201` with the draft; the same `Idempotency-Key` and body again answers `200` with the same id.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "subject": "Imaging at Inova",
                "purpose": "email",
                "audience": "Inova's CIO",
                "body": "We help imaging teams cut wait times."
              },
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "purpose": {
                    "type": "string",
                    "enum": [
                      "email",
                      "ad",
                      "note",
                      "call_opener",
                      "brief",
                      "assessment",
                      "proposal",
                      "thesis",
                      "general"
                    ]
                  },
                  "audience": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20000
                  }
                },
                "required": [
                  "subject",
                  "purpose",
                  "body"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A retry: the same `Idempotency-Key` and body as a `201` before it; the same id.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Drf5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                    "title": "Imaging at Inova",
                    "purpose": "email",
                    "audience": "Inova's CIO",
                    "sections": [
                      {
                        "id": "s_Ab3dE5fG",
                        "heading": null,
                        "text": "We help imaging teams cut wait times."
                      }
                    ],
                    "subject": "Imaging at Inova",
                    "body": "We help imaging teams cut wait times.",
                    "evidence": [],
                    "approval": null,
                    "archived": false,
                    "revisionNo": 1,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicDraft"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Made; a retry with the same key and body answers `200` with the same id.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Drf5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                    "title": "Imaging at Inova",
                    "purpose": "email",
                    "audience": "Inova's CIO",
                    "sections": [
                      {
                        "id": "s_Ab3dE5fG",
                        "heading": null,
                        "text": "We help imaging teams cut wait times."
                      }
                    ],
                    "subject": "Imaging at Inova",
                    "body": "We help imaging teams cut wait times.",
                    "evidence": [],
                    "approval": null,
                    "archived": false,
                    "revisionNo": 1,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicDraft"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/drafts/approved": {
      "get": {
        "operationId": "listApprovedDrafts",
        "tags": [
          "drafts"
        ],
        "summary": "List approved drafts with their text",
        "description": "Approved drafts with their full text, ready to send or import. Use this when moving approved emails, notes or briefs into another tool. Newest change first. Each `subject` and `body` is exactly what the app's Copy and \"Open in email\" give: a record link in the text is written as its name and address, or its name alone where you may not open it. A draft edited after its approval leaves this list until it is approved again. `total` is null: this read does not count.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "items": [
                      {
                        "id": "Drf5tH8jKw2qR6mX9vBz",
                        "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                        "title": "Imaging at Inova",
                        "purpose": "email",
                        "audience": "Inova's CIO",
                        "sections": [
                          {
                            "id": "s_Ab3dE5fG",
                            "heading": "Why now",
                            "text": "Inova posted an imaging contract on [SAM.gov](ledger:contract:va-imaging-2026)."
                          },
                          {
                            "id": "s_Hj7kL9mN",
                            "heading": null,
                            "text": "Could we talk next week?\n\nBest, Alex"
                          }
                        ],
                        "subject": "Imaging at Inova",
                        "body": "Why now\n\nInova posted an imaging contract on [SAM.gov](https://hrcledger.com/contracts/va-imaging-2026).\n\nCould we talk next week?\n\nBest, Alex",
                        "evidence": [
                          {
                            "type": "organization",
                            "key": "41",
                            "url": "https://hrcledger.com/orgs/inova"
                          }
                        ],
                        "approval": {
                          "revisionNo": 3,
                          "at": "2026-10-16T14:02:11.000Z"
                        },
                        "archived": false,
                        "revisionNo": 3,
                        "updatedAt": "2026-10-16T14:02:11.000Z"
                      }
                    ],
                    "nextCursor": null,
                    "total": null
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "items",
                        "nextCursor",
                        "total"
                      ],
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicDraft"
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` for the next page; null on the last."
                        },
                        "total": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Every match, counted; null where the read does not count."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/drafts/{id}": {
      "get": {
        "operationId": "readDraft",
        "tags": [
          "drafts"
        ],
        "summary": "Read a draft",
        "description": "One draft with its text, its evidence and whether it is approved. Use this when you have a draft's id and need what it says. `sections` hold the stored text, record links as written, which is what an edit sends back; `body` is the text as the app's Copy gives it. `approval` is null unless this version is approved.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Drf5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                    "title": "Imaging at Inova",
                    "purpose": "email",
                    "audience": "Inova's CIO",
                    "sections": [
                      {
                        "id": "s_Ab3dE5fG",
                        "heading": "Why now",
                        "text": "Inova posted an imaging contract on [SAM.gov](ledger:contract:va-imaging-2026)."
                      },
                      {
                        "id": "s_Hj7kL9mN",
                        "heading": null,
                        "text": "Could we talk next week?\n\nBest, Alex"
                      }
                    ],
                    "subject": "Imaging at Inova",
                    "body": "Why now\n\nInova posted an imaging contract on [SAM.gov](https://hrcledger.com/contracts/va-imaging-2026).\n\nCould we talk next week?\n\nBest, Alex",
                    "evidence": [
                      {
                        "type": "organization",
                        "key": "41",
                        "url": "https://hrcledger.com/orgs/inova"
                      }
                    ],
                    "approval": {
                      "revisionNo": 3,
                      "at": "2026-10-16T14:02:11.000Z"
                    },
                    "archived": false,
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicDraft"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "patch": {
        "operationId": "editDraft",
        "tags": [
          "drafts"
        ],
        "summary": "Change a draft",
        "description": "Change a draft's text or fields in one version. Send the version you read; a newer one is a conflict carrying it. Use this when someone asks to edit a saved draft. `ops` are the draft's own operations, applied as one new version: `replace_text`, `rewrite`, `add_section`, `update_section`, `remove_section`, `move_section` and `set_field` (`title`, `purpose`, `audience`). `expectedRevisionNo` is required; a newer version is `409 revision_conflict` carrying it. The version is the key holder's own text, recorded with the key and never as written by the assistant, and it is not run through the assistant's drafting checks. A change takes an approved draft back out of review.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "expectedRevisionNo": 3,
                "ops": [
                  {
                    "op": "update_section",
                    "sectionId": "s_Hj7kL9mN",
                    "text": "Could we talk Thursday?\n\nBest, Alex"
                  }
                ]
              },
              "schema": {
                "type": "object",
                "properties": {
                  "ops": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    }
                  },
                  "expectedRevisionNo": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  }
                },
                "required": [
                  "ops",
                  "expectedRevisionNo"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Drf5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                    "title": "Imaging at Inova",
                    "purpose": "email",
                    "audience": "Inova's CIO",
                    "sections": [
                      {
                        "id": "s_Ab3dE5fG",
                        "heading": "Why now",
                        "text": "Inova posted an imaging contract on [SAM.gov](ledger:contract:va-imaging-2026)."
                      },
                      {
                        "id": "s_Hj7kL9mN",
                        "heading": null,
                        "text": "Could we talk next week?\n\nBest, Alex"
                      }
                    ],
                    "subject": "Imaging at Inova",
                    "body": "Why now\n\nInova posted an imaging contract on [SAM.gov](https://hrcledger.com/contracts/va-imaging-2026).\n\nCould we talk next week?\n\nBest, Alex",
                    "evidence": [
                      {
                        "type": "organization",
                        "key": "41",
                        "url": "https://hrcledger.com/orgs/inova"
                      }
                    ],
                    "approval": null,
                    "archived": false,
                    "revisionNo": 4,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicDraft"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/drafts/{id}/archive": {
      "post": {
        "operationId": "archiveDraft",
        "tags": [
          "drafts"
        ],
        "summary": "Archive a draft",
        "description": "Archive a draft, which is how a draft is deleted. Use this when someone asks to delete or archive a draft. Archiving is how a draft is deleted; it leaves every draft list, and the app can restore it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Drf5tH8jKw2qR6mX9vBz",
                    "url": "https://hrcledger.com/drafts/items/Drf5tH8jKw2qR6mX9vBz",
                    "title": "Imaging at Inova",
                    "purpose": "email",
                    "audience": "Inova's CIO",
                    "sections": [
                      {
                        "id": "s_Ab3dE5fG",
                        "heading": "Why now",
                        "text": "Inova posted an imaging contract on [SAM.gov](ledger:contract:va-imaging-2026)."
                      },
                      {
                        "id": "s_Hj7kL9mN",
                        "heading": null,
                        "text": "Could we talk next week?\n\nBest, Alex"
                      }
                    ],
                    "subject": "Imaging at Inova",
                    "body": "Why now\n\nInova posted an imaging contract on [SAM.gov](https://hrcledger.com/contracts/va-imaging-2026).\n\nCould we talk next week?\n\nBest, Alex",
                    "evidence": [
                      {
                        "type": "organization",
                        "key": "41",
                        "url": "https://hrcledger.com/orgs/inova"
                      }
                    ],
                    "approval": {
                      "revisionNo": 3,
                      "at": "2026-10-16T14:02:11.000Z"
                    },
                    "archived": true,
                    "revisionNo": 3,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicDraft"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/conversations": {
      "get": {
        "operationId": "listConversations",
        "tags": [
          "conversations"
        ],
        "summary": "List your conversations",
        "description": "Your conversations with the assistant, newest first, without their turns. Use this when you need a conversation's id, or want to find an earlier answer. Newest activity first, without their turns. Only your own conversations, never a teammate's; a deleted one is not listed. `total` is null: this read does not count.",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "items": [
                      {
                        "id": "Cnv7pQ2rS4tU6vW8xY0z",
                        "url": "https://hrcledger.com/ask/Cnv7pQ2rS4tU6vW8xY0z",
                        "title": "Ohio EHR changes",
                        "turnCount": 2,
                        "awaitingAnswer": false,
                        "updatedAt": "2026-10-16T14:02:11.000Z"
                      }
                    ],
                    "nextCursor": null,
                    "total": null
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "items",
                        "nextCursor",
                        "total"
                      ],
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicConversationSummary"
                          }
                        },
                        "nextCursor": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Pass as `cursor` for the next page; null on the last."
                        },
                        "total": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "description": "Every match, counted; null where the read does not count."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/conversations/{id}": {
      "get": {
        "operationId": "readConversation",
        "tags": [
          "conversations"
        ],
        "summary": "Read a conversation",
        "description": "One conversation with its turns: each question, answer, the records it cited and the work it saved. Use this when you need what the assistant already said. `turns` is a page, oldest first, with `total` counting every turn; `cursor` and `limit` page it. Each answer's citations carry the address you may open, or null; `artifacts` are what that turn saved that you may open. Another person's conversation, a deleted one and an unknown id are all `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Cnv7pQ2rS4tU6vW8xY0z",
                    "url": "https://hrcledger.com/ask/Cnv7pQ2rS4tU6vW8xY0z",
                    "title": "Ohio EHR changes",
                    "turns": {
                      "items": [
                        {
                          "turn": 1,
                          "runId": "run1aB3dE5fGhJ7kL9mNp",
                          "status": "complete",
                          "question": "Which Ohio hospitals changed EHR vendor this year?",
                          "answer": "Two did: Inova and Mercy Health.",
                          "citations": [
                            {
                              "type": "organization",
                              "key": "41",
                              "url": "https://hrcledger.com/orgs/inova"
                            }
                          ],
                          "artifacts": [],
                          "createdAt": "2026-10-16T13:58:02.000Z"
                        },
                        {
                          "turn": 2,
                          "runId": "run2aB3dE5fGhJ7kL9mNp",
                          "status": "complete",
                          "question": "Save them as a List.",
                          "answer": "Saved them as the List Ohio EHR changes.",
                          "citations": [
                            {
                              "type": "organization",
                              "key": "41",
                              "url": "https://hrcledger.com/orgs/inova"
                            }
                          ],
                          "artifacts": [
                            {
                              "kind": "list",
                              "id": "Lst2mN4pQ6rS8tU0vW2x",
                              "url": "https://hrcledger.com/lists/items/Lst2mN4pQ6rS8tU0vW2x"
                            }
                          ],
                          "createdAt": "2026-10-16T14:02:11.000Z"
                        }
                      ],
                      "nextCursor": null,
                      "total": 2
                    },
                    "createdAt": "2026-10-16T13:58:02.000Z",
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicConversation"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "patch": {
        "operationId": "renameConversation",
        "tags": [
          "conversations"
        ],
        "summary": "Rename a conversation",
        "description": "Give a conversation a new title, or null to go back to its first question. Use this when someone asks to rename a conversation. The same rename the app makes: at most 80 characters, trimmed; `null` goes back to the first question. Only your own conversation.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "title": "Ohio EHR changes"
              },
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 80
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "title"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Cnv7pQ2rS4tU6vW8xY0z",
                    "url": "https://hrcledger.com/ask/Cnv7pQ2rS4tU6vW8xY0z",
                    "title": "Ohio EHR changes",
                    "turnCount": 2,
                    "awaitingAnswer": false,
                    "updatedAt": "2026-10-16T14:02:11.000Z"
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicConversationSummary"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteConversation",
        "tags": [
          "conversations"
        ],
        "summary": "Delete a conversation",
        "description": "Delete a conversation, as the app does: it leaves your list and its address stops opening. It answers 204 with no body, and deleting it twice is fine. Use this when someone asks to delete a conversation. The same delete the app makes: an answer still being written in it is stopped first, the conversation leaves your list, and its address answers `404` from then on. The Lists and drafts it saved stay. Deleting it again answers `204` too. Only your own conversation.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted, or already deleted. No body."
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/memory": {
      "get": {
        "operationId": "readMemory",
        "tags": [
          "memory"
        ],
        "summary": "Read what HRC Ledger knows about your company",
        "description": "What HRC Ledger knows about your company: the confirmed entries, each with where it came from and whether it was said or inferred, at most 200, with the total. Use this when you need the customer's ideal prospects, exclusions or tone. The entries the assistant is given, each in words: `basis` says whether someone said it or HRC Ledger inferred it, `source` where it came from, `updatedAt` when. An entry waiting for a person to confirm it never appears. A company with nothing confirmed yet has no entries. `total` counts every confirmed entry, so fewer `entries` than `total` means the read was cut at 200.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Done.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "entries": [
                      {
                        "id": "Mem4kL6mN8pQ0rS2tU4v",
                        "kind": "offer",
                        "about": "What you sell",
                        "basis": "stated",
                        "says": "Revenue cycle audits for community hospitals",
                        "source": {
                          "kind": "person",
                          "label": null
                        },
                        "updatedAt": "2026-10-16T14:02:11.000Z"
                      }
                    ],
                    "total": 1
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "entries",
                        "total"
                      ],
                      "properties": {
                        "entries": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PublicMemoryEntry"
                          }
                        },
                        "total": {
                          "type": "integer",
                          "description": "Every confirmed entry, counted; more than `entries` holds when the read was cut."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidQuery"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    },
    "/api/v1/reviews/{artifactId}/approve": {
      "post": {
        "operationId": "approveReview",
        "tags": [
          "reviews"
        ],
        "summary": "Approve a draft or plan version",
        "description": "Approve the version of a draft or plan you read, as the key's owner: a draft needs `drafts:approve` and a plan needs `actions:approve`. The approval covers that version's text only and its history reads \"via API key\". Send `revisionNo` as the version you read; a newer one is `409 revision_conflict` carrying it. It never decides a change the assistant proposed: that address answers `403 person_required`, whatever the key's scopes.",
        "parameters": [
          {
            "name": "artifactId",
            "in": "path",
            "required": true,
            "description": "The draft's or plan's id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1 to 128 characters. A retry with the same key and body returns the first result; the same key with another body is `409`.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "revisionNo": 3
              },
              "schema": {
                "type": "object",
                "properties": {
                  "revisionNo": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "revisionNo"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approved.",
            "content": {
              "application/json": {
                "example": {
                  "ok": true,
                  "data": {
                    "id": "Drf8pQ2rT4vW6xY9zA1b",
                    "kind": "draft",
                    "url": "https://hrcledger.com/drafts/items/Drf8pQ2rT4vW6xY9zA1b",
                    "revisionNo": 3
                  }
                },
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/PublicApproval"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/ApproveForbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/WriteRefused"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/Unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key, `hck_live_...`. Scopes are per key: `contracts:read`, `market:read`, `agent:ask`."
      }
    },
    "responses": {
      "Unauthenticated": {
        "description": "`missing_or_malformed_key` — no `Authorization` header, or one that is not `Bearer <key>`; a valid key sent any other way lands here. `invalid_key` — a well-formed key we do not hold, or a revoked one. The message names which.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "InsufficientScope": {
        "description": "The key lacks the scope this route requires; `error.scope` names it. Code: `insufficient_scope`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such record. Code: `not_found`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "InvalidQuery": {
        "description": "The query string did not parse; `error.message` carries the issues. Code: `invalid_query`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "InvalidRequest": {
        "description": "The body failed validation, including an unknown `skill` and any unknown field. Code: `invalid_request`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "Paused": {
        "description": "Automated model work is paused. The system is healthy and deliberately stopped, and nothing was spent. Code: `paused`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "RateLimited": {
        "description": "A ceiling was reached: the per-minute request limit (`rate_limited`), the per-key day ceiling of 200 runs (`rate_limited`, with `error.limit` and `error.resets_in_seconds`), or the product's own daily model budget (`budget_exhausted`). `Retry-After` carries the seconds.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "Unavailable": {
        "description": "Fails closed, nothing spent: no database (`database_unavailable`) or no usable model provider (`model_unavailable`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "Conflict": {
        "description": "`idempotency_conflict` — this `Idempotency-Key` was used for a different request; send a new key. `revision_conflict` — someone saved a newer version; `error.current.revisionNo` names it. `step_changed` — someone changed that step first; `error.current.revisionNo` names the version that holds it.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "Forbidden": {
        "description": "`insufficient_scope` — the key lacks this route's scope; `error.scope` names it. `owner_only` — only the owner can archive. `archived` — restore it in the app before changing it.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "WriteRefused": {
        "description": "`invalid_request` — the body is not JSON, breaks the schema, or names an unknown field (a tier or an account included). Or the change cannot apply: `invalid_content` (with `error.opIndex`), `expected_revision_required`, `unknown_organization`, `unknown_row`, `unknown_step`, `unknown_assignee`, `invalid_transition`, `blocked_reason_required`, `list_full`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      },
      "ApproveForbidden": {
        "description": "`person_required` — the address is a change the assistant proposed; a person decides it in the app, whatever the key's scopes. `insufficient_scope` — a draft needs `drafts:approve` and a plan `actions:approve`; `error.scope` names the one missing. `archived` — restore it in the app before approving it.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorEnvelope"
            }
          }
        }
      }
    },
    "schemas": {
      "ApiErrorEnvelope": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "const": false
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "scope": {
                "type": "string"
              },
              "limit": {
                "type": "integer"
              },
              "resets_in_seconds": {
                "type": "integer"
              },
              "current": {
                "type": "object",
                "required": [
                  "revisionNo"
                ],
                "properties": {
                  "revisionNo": {
                    "type": "integer"
                  }
                },
                "description": "On `revision_conflict` and `step_changed`: the version that is current now. Read it, then try again."
              },
              "opIndex": {
                "type": "integer",
                "description": "On a refused change: which item of `ops` it is about, counted from 0."
              }
            }
          }
        }
      },
      "PublicContract": {
        "type": "object",
        "required": [
          "slug",
          "source",
          "externalId",
          "title",
          "description",
          "buyerName",
          "buyerType",
          "jurisdiction",
          "agency",
          "naics",
          "psc",
          "valueEstimate",
          "postedDate",
          "questionsDueDate",
          "responseDueDate",
          "awardDate",
          "performanceStart",
          "performanceEnd",
          "setAside",
          "url"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "externalId": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "buyerName": {
            "type": [
              "string",
              "null"
            ]
          },
          "buyerType": {
            "type": [
              "string",
              "null"
            ]
          },
          "jurisdiction": {
            "type": [
              "string",
              "null"
            ]
          },
          "agency": {
            "type": [
              "string",
              "null"
            ]
          },
          "naics": {
            "type": [
              "string",
              "null"
            ]
          },
          "psc": {
            "type": [
              "string",
              "null"
            ]
          },
          "valueEstimate": {
            "type": [
              "number",
              "null"
            ]
          },
          "postedDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "questionsDueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "responseDueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "awardDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "performanceStart": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "performanceEnd": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "setAside": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PublicOrg": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "segment",
          "state",
          "locationCount",
          "staffedBeds",
          "ccn",
          "npi",
          "ein"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "segment": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          },
          "locationCount": {
            "type": [
              "integer",
              "null"
            ]
          },
          "staffedBeds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ccn": {
            "type": [
              "string",
              "null"
            ]
          },
          "npi": {
            "type": [
              "string",
              "null"
            ]
          },
          "ein": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AskRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "question"
        ],
        "properties": {
          "question": {
            "type": "string",
            "minLength": 8,
            "maxLength": 20000,
            "description": "Trimmed before the bounds are applied. The same bounds the web surface enforces."
          },
          "contract": {
            "type": "string",
            "enum": [
              "list",
              "draft",
              "actions",
              "general"
            ],
            "description": "Optional. The output contract the answer must take. Omitted resolves to general on the server and is never inferred from the question. An unknown value is a 422 naming the four, never a silent fallback."
          },
          "skill": {
            "type": "string",
            "enum": [
              "draft",
              "target_list",
              "audience",
              "answer",
              "general"
            ],
            "description": "Deprecated, read for one release and only when contract is omitted: target_list and audience decode as list, answer as general, draft and general as themselves. Send contract instead. An unknown value is a 422."
          },
          "prior_run_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 24,
            "description": "Optional. A prior run's public_id, when this question answers that run's clarifying question. Resolved with the caller's own key as viewer, so a public_id belonging to another account is a 404 not_found."
          },
          "conversation": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{20,24}$",
            "description": "Optional. The conversation to append this question to, as returned in data.conversation.id. Omitted opens a new conversation. Resolved against the key's own account, so a conversation belonging to another account is a 404 not_found. The body never carries message content: the prior turns are rebuilt server-side, and a long thread is trimmed by the replay depth cap documented in docs/API.md."
          },
          "time_zone": {
            "type": "string",
            "example": "America/Chicago",
            "description": "Optional. The asker's IANA time zone, which dates the run so relative dates such as last week resolve in the asker's calendar. An invalid value is never a 422: it is read as unknown, and the run assumes US Eastern (America/New_York) and says so. A zone saved on the key's account outranks this field, which is then only a fallback."
          }
        }
      },
      "AskData": {
        "type": "object",
        "required": [
          "run",
          "conversation",
          "answer",
          "citations",
          "rows",
          "coverage",
          "usage",
          "feedback"
        ],
        "properties": {
          "run": {
            "type": "object",
            "required": [
              "id",
              "url",
              "status",
              "contract",
              "stopped_reason",
              "partial_note"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "description": "Absolute. The same run, openable by a person."
              },
              "status": {
                "type": "string",
                "enum": [
                  "complete",
                  "partial",
                  "failed"
                ]
              },
              "contract": {
                "type": "string",
                "enum": [
                  "list",
                  "draft",
                  "actions",
                  "general"
                ],
                "description": "The output contract that was in force, resolved on the server."
              },
              "stopped_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  null,
                  "step_ceiling",
                  "cost_ceiling",
                  "wall_clock",
                  "budget",
                  "paused",
                  "error",
                  "unsupported_citation",
                  "unsupported_outcome",
                  "output_cap",
                  "call_timeout",
                  "no_answer",
                  "no_progress",
                  "stopped_by_person",
                  "disconnected"
                ]
              },
              "partial_note": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The sentence a partial run carries. Null on a complete run."
              }
            }
          },
          "conversation": {
            "type": "object",
            "required": [
              "id",
              "url",
              "turn"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Send this back as the request's conversation to ask a follow-up in the same thread."
              },
              "url": {
                "type": "string",
                "description": "Absolute. The same thread, readable by a person."
              },
              "turn": {
                "type": "integer",
                "description": "This run's ordinal in the thread. A new conversation opens at 1."
              }
            }
          },
          "answer": {
            "type": [
              "string",
              "null"
            ]
          },
          "citations": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "claim",
                "record",
                "url",
                "absence"
              ],
              "properties": {
                "claim": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The sentence the record supports, derived from the answer text."
                },
                "record": {
                  "type": "object",
                  "required": [
                    "type",
                    "key"
                  ],
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "contract",
                        "organization",
                        "person",
                        "document"
                      ]
                    },
                    "key": {
                      "type": "string"
                    }
                  }
                },
                "url": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "absence": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    null,
                    "not_checked",
                    "not_held",
                    "unreadable",
                    "not_published",
                    "none_found"
                  ],
                  "description": "Why `url` is null: `not_held` means we looked and hold no such record; `not_checked` means this handle has no public lookup. Null when the record resolved."
                }
              }
            }
          },
          "rows": {
            "type": "array",
            "description": "The rows this run recorded, in order. Empty means the ledger holds no rows for the run, never that no records were read — what a run read is `coverage`.",
            "items": {
              "type": "object",
              "required": [
                "type",
                "key",
                "row"
              ],
              "properties": {
                "type": {
                  "type": "string"
                },
                "key": {
                  "type": "string"
                },
                "row": {
                  "type": "object"
                }
              }
            }
          },
          "coverage": {
            "type": "object",
            "required": [
              "views",
              "steps",
              "note",
              "unreadable"
            ],
            "properties": {
              "views": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "view",
                    "rows_returned"
                  ],
                  "properties": {
                    "view": {
                      "type": "string"
                    },
                    "rows_returned": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  }
                }
              },
              "steps": {
                "type": "integer"
              },
              "note": {
                "type": "string",
                "description": "Emitted by code, not by the model."
              },
              "unreadable": {
                "type": "integer",
                "description": "Reads that failed or were refused. Non-zero means the answer is built on less."
              }
            }
          },
          "usage": {
            "type": "object",
            "required": [
              "cost_cents",
              "input_tokens",
              "output_tokens",
              "cached_tokens"
            ],
            "properties": {
              "cost_cents": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Null is not yet known or under a cent. Never 0 for work that was billed."
              },
              "input_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "output_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "cached_tokens": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Null means the provider said nothing about the cache, which is not a reported zero."
              }
            }
          },
          "feedback": {
            "type": "object",
            "description": "Where to send the two feedback controls for this run (036-FR-020). The same signal the web transcript and the Slack reply carry; a machine presses it by POSTing to url. It carries no signal of its own — nothing has been pressed when this response is composed.",
            "required": [
              "url",
              "run",
              "controls"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "Relative path. POST { run, rating?, used? }; a body stating neither rating nor used is refused, and an unknown field (including a shape) is refused rather than stripped."
              },
              "run": {
                "type": "string",
                "description": "The run a press is recorded against — the same token as run.id."
              },
              "controls": {
                "type": "array",
                "description": "The two independent signals a press may state. Useful and acted-on are two facts, not one.",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PublicList": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "archived": {
            "type": "boolean"
          },
          "revisionNo": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "name",
          "purpose",
          "archived",
          "revisionNo",
          "updatedAt"
        ]
      },
      "PublicListRow": {
        "type": "object",
        "properties": {
          "rowId": {
            "type": "integer"
          },
          "kind": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "organizationId": {
            "type": [
              "integer",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "integer",
              "null"
            ]
          },
          "addedVia": {
            "type": [
              "string",
              "null"
            ]
          },
          "addedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "rowId",
          "kind",
          "key",
          "name",
          "organizationId",
          "url",
          "note",
          "priority",
          "addedVia",
          "addedAt"
        ]
      },
      "PlanStep": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "todo",
              "in_progress",
              "blocked",
              "done",
              "cancelled"
            ]
          },
          "assignee": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "userId": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "userId",
              "label"
            ],
            "additionalProperties": false
          },
          "dueDate": {
            "type": [
              "string",
              "null"
            ]
          },
          "blockedReason": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "status",
          "assignee",
          "dueDate",
          "blockedReason"
        ]
      },
      "PublicPlan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "objective": {
            "type": "string"
          },
          "archived": {
            "type": "boolean"
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlanStep"
            }
          },
          "revisionNo": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "objective",
          "archived",
          "steps",
          "revisionNo",
          "updatedAt"
        ]
      },
      "PublicPlanSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "objective": {
            "type": "string"
          },
          "archived": {
            "type": "boolean"
          },
          "revisionNo": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "objective",
          "archived",
          "revisionNo",
          "updatedAt"
        ]
      },
      "PublicStepRow": {
        "type": "object",
        "properties": {
          "planId": {
            "type": "string"
          },
          "planTitle": {
            "type": "string"
          },
          "planUrl": {
            "type": "string"
          },
          "stepId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "todo",
              "in_progress",
              "blocked",
              "done",
              "cancelled"
            ]
          },
          "assigneeUserId": {
            "type": [
              "integer",
              "null"
            ]
          },
          "dueDate": {
            "type": [
              "string",
              "null"
            ]
          },
          "revisionNo": {
            "type": "integer"
          }
        },
        "required": [
          "planId",
          "planTitle",
          "planUrl",
          "stepId",
          "title",
          "status",
          "assigneeUserId",
          "dueDate",
          "revisionNo"
        ]
      },
      "DraftSection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "heading": {
            "type": [
              "string",
              "null"
            ]
          },
          "text": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "heading",
          "text"
        ]
      },
      "RecordReference": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The address you may open, or null where you may not."
          }
        },
        "required": [
          "type",
          "key",
          "url"
        ]
      },
      "PublicDraft": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "audience": {
            "type": [
              "string",
              "null"
            ]
          },
          "sections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DraftSection"
            }
          },
          "subject": {
            "type": "string",
            "description": "The draft's title, as the app's \"Open in email\" uses it."
          },
          "body": {
            "type": "string",
            "description": "The sections as plain text, exactly what the app's Copy gives."
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecordReference"
            }
          },
          "approval": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "revisionNo": {
                "type": "integer"
              },
              "at": {
                "type": "string"
              }
            },
            "required": [
              "revisionNo",
              "at"
            ],
            "additionalProperties": false
          },
          "archived": {
            "type": "boolean"
          },
          "revisionNo": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "purpose",
          "audience",
          "sections",
          "subject",
          "body",
          "evidence",
          "approval",
          "archived",
          "revisionNo",
          "updatedAt"
        ]
      },
      "PublicDraftSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "audience": {
            "type": [
              "string",
              "null"
            ]
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecordReference"
            }
          },
          "approval": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "revisionNo": {
                "type": "integer"
              },
              "at": {
                "type": "string"
              }
            },
            "required": [
              "revisionNo",
              "at"
            ],
            "additionalProperties": false
          },
          "archived": {
            "type": "boolean"
          },
          "revisionNo": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "purpose",
          "audience",
          "evidence",
          "approval",
          "archived",
          "revisionNo",
          "updatedAt"
        ]
      },
      "PublicConversationSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "turnCount": {
            "type": "integer"
          },
          "awaitingAnswer": {
            "type": "boolean",
            "description": "True when the assistant's last turn asked you a question."
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "turnCount",
          "awaitingAnswer",
          "updatedAt"
        ]
      },
      "ConversationTurn": {
        "type": "object",
        "properties": {
          "turn": {
            "type": "integer"
          },
          "runId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "question": {
            "type": "string"
          },
          "answer": {
            "type": [
              "string",
              "null"
            ]
          },
          "citations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecordReference"
            }
          },
          "artifacts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string"
                },
                "id": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                }
              },
              "required": [
                "kind",
                "id",
                "url"
              ],
              "additionalProperties": false
            }
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "turn",
          "runId",
          "status",
          "question",
          "answer",
          "citations",
          "artifacts",
          "createdAt"
        ]
      },
      "PublicConversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "turns": {
            "type": "object",
            "required": [
              "items",
              "nextCursor",
              "total"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ConversationTurn"
                }
              },
              "nextCursor": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Pass as `cursor` for the next page; null on the last."
              },
              "total": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Every match, counted; null where the read does not count."
              }
            }
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "url",
          "title",
          "turns",
          "createdAt",
          "updatedAt"
        ]
      },
      "PublicMemoryEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "type": "string"
          },
          "about": {
            "type": "string"
          },
          "basis": {
            "type": "string",
            "enum": [
              "stated",
              "inferred"
            ]
          },
          "says": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string"
              },
              "label": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "kind",
              "label"
            ],
            "additionalProperties": false
          },
          "updatedAt": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "kind",
          "about",
          "basis",
          "says",
          "source",
          "updatedAt"
        ]
      },
      "PublicApproval": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "draft",
              "actions"
            ]
          },
          "url": {
            "type": "string"
          },
          "revisionNo": {
            "type": "integer"
          }
        },
        "required": [
          "id",
          "kind",
          "url",
          "revisionNo"
        ]
      }
    }
  }
}