{"openapi":"3.1.1","info":{"title":"Thermal Platform API","version":"v1","x-contract-revision":"2026-09-19","description":"The Thermal Platform API. Generated from the operation descriptors in apps/web/src/lib/api; hand-editing this document is not a supported path. Every operation is an allowlisted registry action reachable only through the resolved principal context. See the [API changelog](/docs/reference/api-changelog) for contract updates."},"servers":[{"url":"/api/v1","description":"Production, canonical host."}],"paths":{"/agreements":{"get":{"operationId":"agreement.list","summary":"List service agreements for a customer","description":"Agreements by customer — the coverage context a technician needs before quoting work on site.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"customerId","in":"query","required":true,"description":"The customer whose agreements to return.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size. The maximum is a contract limit and is validated, not clamped silently (http-contract.md § Pagination).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque keyset cursor from a previous page's nextCursor. There is no offset pagination on spine reads, so a concurrent write cannot shift a page boundary.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A cursor-paginated page of service agreements.","properties":{"items":{"type":"array","items":{"type":"object","description":"One service agreement.","properties":{"id":{"type":"string","format":"uuid"},"customerId":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true},"status":{"type":"string"},"startDate":{"type":"string","format":"date","nullable":true},"endDate":{"type":"string","format":"date","nullable":true}},"required":["id","customerId","name","status","startDate","endDate"],"additionalProperties":false}},"nextCursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next page, or null when no more rows exist."},"limit":{"type":"integer","description":"The page size actually applied."}},"required":["items","nextCursor","limit"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"agreements","x-thermal-pagination":{"style":"cursor","defaultPageSize":25,"maxPageSize":100,"sortKeys":["startDate","id"]},"x-thermal-examples":[{"name":"agreements-for-customer","request":{"customerId":"00000000-0000-4000-8000-000000000003","limit":25}}]}},"/agreements/{id}/proposed-renewals":{"post":{"operationId":"agreement.propose_renewal","summary":"Execute an approved renewal-with-escalation suggestion","description":"Runs the shared `renewAgreement` core with the optional flat escalator a person approved, matching the `agreement.propose_renewal` registry action. Its eligibility is re-checked at APPLY time: an agreement on auto-renew, or one no longer due for renewal or expired, returns `renewed: false` with a reason rather than fighting the agreements-sweep cron. Classed `high` for the same reason `agreement.renew` is — it performs that same term extension plus a price change — so it is never one-phase. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The renewal outcome, including the reason when nothing was renewed.","properties":{"id":{"type":"string","format":"uuid"},"renewed":{"type":"boolean"},"reason":{"type":"string","nullable":true,"description":"Why the renewal did not run (`not_renewable`, `not_found`, …). Null when it did."},"fromExpiry":{"type":"string","nullable":true},"toExpiry":{"type":"string","nullable":true},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string","nullable":true},"priorPriceCents":{"type":"integer","nullable":true},"newPriceCents":{"type":"integer","nullable":true},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","renewed","reason","fromExpiry","toExpiry","fromStatus","toStatus","priorPriceCents","newPriceCents","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"apply an approved 5% escalation","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1","escalatorBps":500}}]}},"/agreements/{id}/proposed-renewals/approve":{"post":{"operationId":"agreement.propose_renewal.approve","summary":"Execute an approved renewal-with-escalation suggestion — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The renewal outcome, including the reason when nothing was renewed.","properties":{"id":{"type":"string","format":"uuid"},"renewed":{"type":"boolean"},"reason":{"type":"string","nullable":true,"description":"Why the renewal did not run (`not_renewable`, `not_found`, …). Null when it did."},"fromExpiry":{"type":"string","nullable":true},"toExpiry":{"type":"string","nullable":true},"fromStatus":{"type":"string","nullable":true},"toStatus":{"type":"string","nullable":true},"priorPriceCents":{"type":"integer","nullable":true},"newPriceCents":{"type":"integer","nullable":true},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","renewed","reason","fromExpiry","toExpiry","fromStatus","toStatus","priorPriceCents","newPriceCents","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"apply an approved 5% escalation","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1","escalatorBps":500}}]}},"/agreements/{id}/proposed-renewals/preview":{"post":{"operationId":"agreement.propose_renewal.preview","summary":"Execute an approved renewal-with-escalation suggestion — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"apply an approved 5% escalation","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1","escalatorBps":500}}]}},"/agreements/{id}/reminders":{"post":{"operationId":"agreement.send_reminder","summary":"Re-notify the customer about a renewal-risk agreement","description":"Records a `reminder_sent` activity row and sends the renewal reminder for an agreement whose status is `due_for_renewal` or `expired` — the same eligibility the `agreement.send_reminder` registry action applies, re-checked at APPLY time so an agreement renewed between preview and apply is an honest `sent: false` no-op. Irreversible (the customer receives it) and therefore classed `high`. The agreement row itself is never updated, so no row version is bound or returned. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"Whether a reminder was actually sent for this agreement.","properties":{"id":{"type":"string","format":"uuid"},"sent":{"type":"boolean","description":"False when the agreement was no longer renewal-risk — an honest no-op, not a failure."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","sent","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"remind on an expiring agreement","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1"}}]}},"/agreements/{id}/reminders/approve":{"post":{"operationId":"agreement.send_reminder.approve","summary":"Re-notify the customer about a renewal-risk agreement — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"Whether a reminder was actually sent for this agreement.","properties":{"id":{"type":"string","format":"uuid"},"sent":{"type":"boolean","description":"False when the agreement was no longer renewal-risk — an honest no-op, not a failure."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","sent","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"remind on an expiring agreement","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1"}}]}},"/agreements/{id}/reminders/preview":{"post":{"operationId":"agreement.send_reminder.preview","summary":"Re-notify the customer about a renewal-risk agreement — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"remind on an expiring agreement","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1"}}]}},"/agreements/{id}/renewals":{"post":{"operationId":"agreement.renew","summary":"Renew a service agreement for one more term","description":"Runs `renewAgreementCore` — the same one-cycle term extension and status reset the `agreement.renew` registry action performs, including its renewal-ledger row and rate-card escalation precedence. Classed `high` by DECLARED policy (its side effect is an ordinary `write`, floor `medium`), so it is never one-phase: preview binds the agreement's current row version and the apply presents that proposal with a `--reason`. An agreement whose status cannot be renewed, or that was already renewed today, is a `409` and changes nothing. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The agreement's term and status before and after the renewal.","properties":{"id":{"type":"string","format":"uuid"},"fromExpiry":{"type":"string","nullable":true,"description":"The expiry date the term held before."},"toExpiry":{"type":"string","description":"The expiry date it holds after."},"fromStatus":{"type":"string"},"toStatus":{"type":"string"},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","fromExpiry","toExpiry","fromStatus","toStatus","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"renew an agreement due for renewal","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1"}}]}},"/agreements/{id}/renewals/approve":{"post":{"operationId":"agreement.renew.approve","summary":"Renew a service agreement for one more term — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The agreement's term and status before and after the renewal.","properties":{"id":{"type":"string","format":"uuid"},"fromExpiry":{"type":"string","nullable":true,"description":"The expiry date the term held before."},"toExpiry":{"type":"string","description":"The expiry date it holds after."},"fromStatus":{"type":"string"},"toStatus":{"type":"string"},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","fromExpiry","toExpiry","fromStatus","toStatus","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"renew an agreement due for renewal","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1"}}]}},"/agreements/{id}/renewals/preview":{"post":{"operationId":"agreement.renew.preview","summary":"Renew a service agreement for one more term — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"agreements","x-thermal-target-table":"service_agreements","x-thermal-examples":[{"name":"renew an agreement due for renewal","request":{"id":"1b7c9d2e-3f40-4a51-8b62-7c83d94e05f1"}}]}},"/appointments/{id}/arrive":{"post":{"operationId":"appointment.mark_arrived","summary":"Mark the technician's visit arrived","description":"Marks only the caller's own en-route visit arrived. The first arrival time, visit event and work-order rollup are recorded together. An idempotency-key replay keeps the first stamp. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["arrived"]},"arrivedAt":{"type":"string","format":"date-time"},"workOrderStatus":{"type":"string"},"rowVersion":{"type":"integer","nullable":true},"replayed":{"type":"boolean"}},"required":["id","workOrderId","status","arrivedAt","workOrderStatus","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"arrive at the assigned visit","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/appointments/{id}/arrive/approve":{"post":{"operationId":"appointment.mark_arrived.approve","summary":"Mark the technician's visit arrived — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["arrived"]},"arrivedAt":{"type":"string","format":"date-time"},"workOrderStatus":{"type":"string"},"rowVersion":{"type":"integer","nullable":true},"replayed":{"type":"boolean"}},"required":["id","workOrderId","status","arrivedAt","workOrderStatus","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"arrive at the assigned visit","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/appointments/{id}/arrive/preview":{"post":{"operationId":"appointment.mark_arrived.preview","summary":"Mark the technician's visit arrived — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"arrive at the assigned visit","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/available":{"get":{"operationId":"technician.available_jobs","summary":"List unassigned available jobs in the calling technician's branch","description":"Unassigned, still-open appointments in the calling technician's branch — the list `/tech/available` renders, wrapped from `fetchAvailableJobs` verbatim. Branch scoping flows through the parent work order (ADR-0001 Decision 7 RLS), never through a caller-supplied filter. `hasPendingClaim` marks an appointment the caller already asked dispatch to confirm.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's branch-scoped list of claimable appointments.","properties":{"timeZone":{"type":"string","description":"The organization's IANA timezone used to render each scheduled instant."},"jobs":{"type":"array","items":{"type":"object","description":"One unassigned, still-open appointment in the caller's branch, as `/tech/available` lists it.","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"status":{"type":"string"},"scheduledStart":{"type":"string","format":"date-time","nullable":true},"number":{"type":"integer","nullable":true},"priority":{"type":"string"},"summary":{"type":"string","nullable":true},"equipment":{"type":"object","nullable":true,"description":"The installed equipment on the job's work order, when one is linked.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","nullable":true},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true}},"required":["id","type","make","model","serial"],"additionalProperties":false},"serviceSite":{"type":"object","nullable":true,"description":"The job's service site and its customer, when one is linked.","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","nullable":true},"addressLine1":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"zip":{"type":"string","nullable":true},"customerName":{"type":"string","nullable":true}},"required":["id","label","addressLine1","city","state","zip","customerName"],"additionalProperties":false},"bookedCents":{"type":"integer","description":"Sum of the job's line-item totals, as the list card shows it."},"hasPendingClaim":{"type":"boolean","description":"True when the calling technician already has a pending claim request for this appointment."}},"required":["id","workOrderId","status","scheduledStart","number","priority","summary","equipment","serviceSite","bookedCents","hasPendingClaim"],"additionalProperties":false}}},"required":["timeZone","jobs"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-schedule","x-thermal-examples":[{"name":"branch-available","request":{}}]}},"/available-appointments/{id}/claim":{"post":{"operationId":"appointment.request_claim","summary":"Request a claim on an available appointment","description":"A technician asks for an unassigned visit. Inserts a pending claim request only — it never assigns the appointment; dispatch confirmation is a separate, human step. Idempotent per (appointment, technician): an existing pending claim is reused. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The technician's pending claim REQUEST on an available appointment. The appointment itself is untouched — dispatch's Confirm is the only path that assigns it.","properties":{"claimId":{"type":"string","format":"uuid"},"appointmentId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"],"description":"Always `pending`. This operation can produce no other claim status."},"alreadyPending":{"type":"boolean","description":"True when this technician already had a pending claim on the appointment and it was reused, so no second row was written. Distinct from `replayed`, which is the idempotency key's own short-circuit."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["claimId","appointmentId","workOrderId","status","alreadyPending","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"appointment_claims","x-thermal-examples":[{"name":"claim an available visit","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/available-appointments/{id}/claim/approve":{"post":{"operationId":"appointment.request_claim.approve","summary":"Request a claim on an available appointment — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The technician's pending claim REQUEST on an available appointment. The appointment itself is untouched — dispatch's Confirm is the only path that assigns it.","properties":{"claimId":{"type":"string","format":"uuid"},"appointmentId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending"],"description":"Always `pending`. This operation can produce no other claim status."},"alreadyPending":{"type":"boolean","description":"True when this technician already had a pending claim on the appointment and it was reused, so no second row was written. Distinct from `replayed`, which is the idempotency key's own short-circuit."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["claimId","appointmentId","workOrderId","status","alreadyPending","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"appointment_claims","x-thermal-examples":[{"name":"claim an available visit","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/available-appointments/{id}/claim/preview":{"post":{"operationId":"appointment.request_claim.preview","summary":"Request a claim on an available appointment — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"appointment_claims","x-thermal-examples":[{"name":"claim an available visit","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/batch":{"post":{"operationId":"batch.apply_batch","summary":"Apply many rows of one governed write in one call","description":"Applies up to 500 rows of ONE registered write operation in a single request. Each item reserves one unit in the org, principal and write-class rate-limit budgets before any item runs; the current write-class budget is 60 units per minute. A refused batch charges nothing, and unused reservations for items that never start are returned. Each item runs through the same boundary a single write does — authorization and ownership for that item's own target, validation, risk classification, its own idempotency record and transaction, and its own activity-ledger row — and reports its own result, so one invalid item never aborts the others. Batch is apply-only: an item that needs a proposal (risk at or above the preview threshold) is refused per item with proposal_required, and an irreversible operation cannot be batched. More than 500 items is a single 400 and nothing is applied. The response is 200 whenever the batch was admitted; read `failed` and each result's `ok`/`status`, and retry only the failures with the same idempotencyKeys. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"operationId":{"type":"string","description":"The registered write operation every item applies."},"items":{"type":"array","description":"1 to 500 items; more is a single 400 and nothing is applied.","items":{"type":"object","properties":{"input":{"type":"object","description":"The operation's own input, path parameters included.","additionalProperties":true},"idempotencyKey":{"type":"string","description":"This item's idempotency key."},"reason":{"type":"string","description":"This item's reason; defaults to X-Thermal-Reason."}},"required":["input"],"additionalProperties":false}}},"required":["operationId","items"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"One result per item, in request order.","properties":{"operationId":{"type":"string"},"requestId":{"type":"string"},"causationId":{"type":"string","format":"uuid","description":"Shared by every activity-ledger row this call wrote."},"total":{"type":"integer"},"succeeded":{"type":"integer"},"failed":{"type":"integer"},"notAttempted":{"type":"integer","description":"Of `failed`, the items never started (time budget or a server fault). Safe to resubmit."},"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","description":"The item's position in the request."},"ok":{"type":"boolean","description":"True for a 2xx."},"status":{"type":"integer","description":"The status this item would have returned as a single write request."},"requestId":{"type":"string","nullable":true},"body":{"type":"object","description":"The operation's own success body, or its error envelope.","additionalProperties":true}},"required":["index","ok","status","requestId","body"],"additionalProperties":false}}},"required":["operationId","requestId","causationId","total","succeeded","failed","notAttempted","results"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"platform","x-thermal-target-table":"per-item: the batched operation's own target table","x-thermal-examples":[{"name":"two status changes in one call","request":{"operationId":"work_order.update_status","items":[{"input":{"id":"33333333-3333-4333-8333-333333333333","status":"en_route","expectedRowVersion":3},"idempotencyKey":"sync-2026-09-24-0001"},{"input":{"id":"44444444-4444-4444-8444-444444444444","status":"in_progress","expectedRowVersion":7},"idempotencyKey":"sync-2026-09-24-0002"}]}}]}},"/branches/{branchId}/dispatch/auto-assign":{"post":{"operationId":"dispatch.auto_assign","summary":"Apply Suggested technician assignments for a branch-day","description":"Runs the `dispatch.auto_assign` registry action for one branch and one day: each unassigned open job is packed into a real open slot in the gaining technician's working hours. The undo replay the office UI uses is NOT exposed here — a revert is a separate reviewed act, and this contract's input has no field for one. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"What one auto-assign pass committed for the branch-day.","properties":{"id":{"type":"string","format":"uuid","description":"The branch the pass ran for."},"assigned":{"type":"integer","minimum":0},"skipped":{"type":"array","description":"Jobs the pass deliberately left alone, each with the reason it was skipped.","items":{"type":"object","properties":{"jobId":{"type":"string"},"reason":{"type":"string"}},"required":["jobId","reason"],"additionalProperties":false}},"runId":{"type":"string","nullable":true,"description":"The dispatch training-ledger run id, or null when the ledger write itself failed."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","assigned","skipped","runId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"auto-assign tomorrow's unassigned jobs","request":{"targetDateISO":"2026-09-25","timezone":"America/Chicago"}}]}},"/branches/{branchId}/dispatch/auto-assign/approve":{"post":{"operationId":"dispatch.auto_assign.approve","summary":"Apply Suggested technician assignments for a branch-day — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"What one auto-assign pass committed for the branch-day.","properties":{"id":{"type":"string","format":"uuid","description":"The branch the pass ran for."},"assigned":{"type":"integer","minimum":0},"skipped":{"type":"array","description":"Jobs the pass deliberately left alone, each with the reason it was skipped.","items":{"type":"object","properties":{"jobId":{"type":"string"},"reason":{"type":"string"}},"required":["jobId","reason"],"additionalProperties":false}},"runId":{"type":"string","nullable":true,"description":"The dispatch training-ledger run id, or null when the ledger write itself failed."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","assigned","skipped","runId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"auto-assign tomorrow's unassigned jobs","request":{"targetDateISO":"2026-09-25","timezone":"America/Chicago"}}]}},"/branches/{branchId}/dispatch/auto-assign/preview":{"post":{"operationId":"dispatch.auto_assign.preview","summary":"Apply Suggested technician assignments for a branch-day — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"auto-assign tomorrow's unassigned jobs","request":{"targetDateISO":"2026-09-25","timezone":"America/Chicago"}}]}},"/branches/{branchId}/dispatch/pm-schedule-optimization":{"post":{"operationId":"pm_schedule.propose_optimization","summary":"Apply an optimized preventive-maintenance batch plan","description":"Runs the `pm_schedule.propose_optimization` registry action: each named visit is re-checked as still open, and the survivors are applied through the same `dispatch.apply_route_plan` door daily dispatch uses. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"What survived re-validation and was applied from a staged PM-batch plan.","properties":{"id":{"type":"string","format":"uuid","description":"The branch the plan was applied in."},"applied":{"type":"integer","minimum":0},"workOrderCount":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0,"description":"Named visits no longer open at apply time — completed, canceled or hand-rescheduled between propose and approve."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","applied","workOrderCount","skipped","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"apply a PM batch","request":{"assignments":[{"appointmentId":"88888888-8888-4888-8888-888888888888","technicianId":"77777777-7777-4777-8777-777777777777","routeSequence":1,"scheduledStart":"2026-09-25T15:00:00.000Z"}]}}]}},"/branches/{branchId}/dispatch/pm-schedule-optimization/approve":{"post":{"operationId":"pm_schedule.propose_optimization.approve","summary":"Apply an optimized preventive-maintenance batch plan — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"What survived re-validation and was applied from a staged PM-batch plan.","properties":{"id":{"type":"string","format":"uuid","description":"The branch the plan was applied in."},"applied":{"type":"integer","minimum":0},"workOrderCount":{"type":"integer","minimum":0},"skipped":{"type":"integer","minimum":0,"description":"Named visits no longer open at apply time — completed, canceled or hand-rescheduled between propose and approve."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","applied","workOrderCount","skipped","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"apply a PM batch","request":{"assignments":[{"appointmentId":"88888888-8888-4888-8888-888888888888","technicianId":"77777777-7777-4777-8777-777777777777","routeSequence":1,"scheduledStart":"2026-09-25T15:00:00.000Z"}]}}]}},"/branches/{branchId}/dispatch/pm-schedule-optimization/preview":{"post":{"operationId":"pm_schedule.propose_optimization.preview","summary":"Apply an optimized preventive-maintenance batch plan — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"apply a PM batch","request":{"assignments":[{"appointmentId":"88888888-8888-4888-8888-888888888888","technicianId":"77777777-7777-4777-8777-777777777777","routeSequence":1,"scheduledStart":"2026-09-25T15:00:00.000Z"}]}}]}},"/branches/{branchId}/dispatch/route-plan":{"post":{"operationId":"dispatch.apply_route_plan","summary":"Apply an optimized day plan across a branch's appointments","description":"Runs the `dispatch.apply_route_plan` registry action: assignment, sequence and start time across many appointments in one transaction, with each affected work order's status recomputed. Every named appointment must belong to the branch in the path; a plan naming one outside it is refused whole, never partially applied. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"What one route-plan apply committed, with its same-day disclosure counts.","properties":{"id":{"type":"string","format":"uuid","description":"The branch the plan was applied in."},"applied":{"type":"integer","minimum":0},"workOrderCount":{"type":"integer","minimum":0},"customerUpdatesQueued":{"type":"integer","minimum":0,"description":"Outbox rows inserted for customers. Queued — nothing has sent yet."},"technicianUpdatesQueued":{"type":"integer","minimum":0},"visitsWithoutCustomerChannel":{"type":"integer","minimum":0},"leftUnderway":{"type":"integer","minimum":0,"description":"Visits left exactly as they are because they are already underway."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","applied","workOrderCount","customerUpdatesQueued","technicianUpdatesQueued","visitsWithoutCustomerChannel","leftUnderway","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"apply a two-stop plan","request":{"assignments":[{"appointmentId":"88888888-8888-4888-8888-888888888888","technicianId":"77777777-7777-4777-8777-777777777777","routeSequence":1,"scheduledStart":"2026-09-25T15:00:00.000Z"}]}}]}},"/branches/{branchId}/dispatch/route-plan/approve":{"post":{"operationId":"dispatch.apply_route_plan.approve","summary":"Apply an optimized day plan across a branch's appointments — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"What one route-plan apply committed, with its same-day disclosure counts.","properties":{"id":{"type":"string","format":"uuid","description":"The branch the plan was applied in."},"applied":{"type":"integer","minimum":0},"workOrderCount":{"type":"integer","minimum":0},"customerUpdatesQueued":{"type":"integer","minimum":0,"description":"Outbox rows inserted for customers. Queued — nothing has sent yet."},"technicianUpdatesQueued":{"type":"integer","minimum":0},"visitsWithoutCustomerChannel":{"type":"integer","minimum":0},"leftUnderway":{"type":"integer","minimum":0,"description":"Visits left exactly as they are because they are already underway."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","applied","workOrderCount","customerUpdatesQueued","technicianUpdatesQueued","visitsWithoutCustomerChannel","leftUnderway","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"apply a two-stop plan","request":{"assignments":[{"appointmentId":"88888888-8888-4888-8888-888888888888","technicianId":"77777777-7777-4777-8777-777777777777","routeSequence":1,"scheduledStart":"2026-09-25T15:00:00.000Z"}]}}]}},"/branches/{branchId}/dispatch/route-plan/preview":{"post":{"operationId":"dispatch.apply_route_plan.preview","summary":"Apply an optimized day plan across a branch's appointments — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"branchId","in":"path","required":true,"description":"The branchId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"apply a two-stop plan","request":{"assignments":[{"appointmentId":"88888888-8888-4888-8888-888888888888","technicianId":"77777777-7777-4777-8777-777777777777","routeSequence":1,"scheduledStart":"2026-09-25T15:00:00.000Z"}]}}]}},"/commissions":{"get":{"operationId":"commission.list","summary":"Get the calling technician's own commission ledger and YTD totals","description":"The calling technician's own commission-ledger rows plus year-to-date Earned/Paid/Pending totals — the read `tech/commissions/page.tsx` renders. Own-record only: there is no id/filter parameter, because this operation can never return another technician's ledger. The `rows` list is bounded to the current calendar year (a documented bound, not cursor pagination — D3's pagination style does not apply to a single always-own-record object); the YTD totals are computed over the caller's FULL ledger, matching the page exactly. A caller not linked to a staff record gets the same denial the page's `tryGetCurrentUser()` check returns, never an empty-but-authorized 200.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's own bounded commission-ledger rows and full-ledger YTD totals.","properties":{"rows":{"type":"array","items":{"type":"object","description":"One commission-ledger row, exactly as `commissions/page.tsx` shows it.","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid","nullable":true},"workOrderNumber":{"type":"integer","nullable":true},"workOrderSummary":{"type":"string","nullable":true},"rateTypeSnapshot":{"type":"string"},"rateSnapshot":{"type":"integer"},"baseCents":{"type":"integer"},"earnedCents":{"type":"integer"},"earnedAt":{"type":"string","format":"date-time"},"paidAt":{"type":"string","format":"date-time","nullable":true},"status":{"type":"string","enum":["pending","paid","void"]}},"required":["id","workOrderId","workOrderNumber","workOrderSummary","rateTypeSnapshot","rateSnapshot","baseCents","earnedCents","earnedAt","paidAt","status"],"additionalProperties":false}},"ytdEarnedCents":{"type":"integer"},"ytdPaidCents":{"type":"integer"},"pendingCents":{"type":"integer"}},"required":["rows","ytdEarnedCents","ytdPaidCents","pendingCents"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":true,"x-thermal-side-effect":"read","x-thermal-area":"field-earnings","x-thermal-examples":[{"name":"own-commissions","request":{}}]}},"/customers":{"post":{"operationId":"customer.create","summary":"Create a customer account","description":"Runs `createCustomerCore` in the caller's own organization and branch scope — the same writer the `customer.create` registry action and the office New Customer screen use, including the primary-contact row it creates alongside the account. The account is created in the CALLER's org and branch; neither can be named in the request, which is why the body carries no organization or branch field at all. Classed `medium`, so a one-phase apply is legal; a preview still mints a proposal bound to the exact name, phone and email, and applying that proposal is honoured. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The customer account this request created.","properties":{"id":{"type":"string","format":"uuid","description":"The `customers` row id."},"primaryContactId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: the row did not exist when this request was authorized, so there was no version to guard."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","primaryContactId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"customers","x-thermal-target-table":"customers","x-thermal-examples":[{"name":"create a commercial account","request":{"name":"Ridgeline Property Group","phone":"+15035550142"}}]}},"/customers/approve":{"post":{"operationId":"customer.create.approve","summary":"Create a customer account — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The customer account this request created.","properties":{"id":{"type":"string","format":"uuid","description":"The `customers` row id."},"primaryContactId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: the row did not exist when this request was authorized, so there was no version to guard."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","primaryContactId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"customers","x-thermal-target-table":"customers","x-thermal-examples":[{"name":"create a commercial account","request":{"name":"Ridgeline Property Group","phone":"+15035550142"}}]}},"/customers/preview":{"post":{"operationId":"customer.create.preview","summary":"Create a customer account — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"customers","x-thermal-target-table":"customers","x-thermal-examples":[{"name":"create a commercial account","request":{"name":"Ridgeline Property Group","phone":"+15035550142"}}]}},"/equipment":{"get":{"operationId":"equipment.list","summary":"List installed equipment at a service site","description":"Equipment by site — the spine's first-class equipment object, scoped to one service site the caller can reach.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"serviceSiteId","in":"query","required":true,"description":"The service site whose installed equipment to return.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size. The maximum is a contract limit and is validated, not clamped silently (http-contract.md § Pagination).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque keyset cursor from a previous page's nextCursor. There is no offset pagination on spine reads, so a concurrent write cannot shift a page boundary.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A cursor-paginated page of installed equipment.","properties":{"items":{"type":"array","items":{"type":"object","description":"One piece of installed equipment. Equipment is a first-class spine object, never a job attribute.","properties":{"id":{"type":"string","format":"uuid"},"serviceSiteId":{"type":"string","format":"uuid"},"type":{"type":"string","nullable":true},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true}},"required":["id","serviceSiteId","type","make","model","serial"],"additionalProperties":false}},"nextCursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next page, or null when no more rows exist."},"limit":{"type":"integer","description":"The page size actually applied."}},"required":["items","nextCursor","limit"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"equipment","x-thermal-pagination":{"style":"cursor","defaultPageSize":25,"maxPageSize":100,"sortKeys":["serial","id"]},"x-thermal-examples":[{"name":"equipment-at-site","request":{"serviceSiteId":"00000000-0000-4000-8000-000000000002","limit":25}}]}},"/equipment/{id}/epa-appliance-class":{"post":{"operationId":"equipment.set_epa_appliance_class","summary":"Set an equipment unit's EPA 608 appliance class","description":"Corrects the EPA 608 / AIM Act appliance class on a unit attached to the technician's assigned job. The class decides which federal leak-rate threshold (10/20/30%) the unit is judged against, so it is a compliance input rather than a display field. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The equipment's EPA appliance class after the governed write.","properties":{"id":{"type":"string","format":"uuid","description":"The equipment the class was set on."},"epaApplianceClass":{"type":"string","enum":["comfort_cooling","commercial_refrigeration","industrial_process_refrigeration","unknown"]},"workOrderId":{"type":"string","format":"uuid"},"rowVersion":{"type":"null","description":"Always null. `equipment_hvac_details` carries no server-owned row_version column, so this operation declares `rowVersionStrategy: \"none\"` and opts out of the lost-update guard by name rather than by omission."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","epaApplianceClass","workOrderId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment_hvac_details","x-thermal-examples":[{"name":"correct an unknown class in the field","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333","epaApplianceClass":"comfort_cooling"}}]}},"/equipment/{id}/epa-appliance-class/approve":{"post":{"operationId":"equipment.set_epa_appliance_class.approve","summary":"Set an equipment unit's EPA 608 appliance class — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The equipment's EPA appliance class after the governed write.","properties":{"id":{"type":"string","format":"uuid","description":"The equipment the class was set on."},"epaApplianceClass":{"type":"string","enum":["comfort_cooling","commercial_refrigeration","industrial_process_refrigeration","unknown"]},"workOrderId":{"type":"string","format":"uuid"},"rowVersion":{"type":"null","description":"Always null. `equipment_hvac_details` carries no server-owned row_version column, so this operation declares `rowVersionStrategy: \"none\"` and opts out of the lost-update guard by name rather than by omission."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","epaApplianceClass","workOrderId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment_hvac_details","x-thermal-examples":[{"name":"correct an unknown class in the field","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333","epaApplianceClass":"comfort_cooling"}}]}},"/equipment/{id}/epa-appliance-class/preview":{"post":{"operationId":"equipment.set_epa_appliance_class.preview","summary":"Set an equipment unit's EPA 608 appliance class — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment_hvac_details","x-thermal-examples":[{"name":"correct an unknown class in the field","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333","epaApplianceClass":"comfort_cooling"}}]}},"/equipment/{id}/refrigerant-transactions":{"post":{"operationId":"equipment.add_refrigerant_transaction","summary":"Log an EPA-608 refrigerant transaction against a unit","description":"Appends a §82.166 servicing record — charge, recovery, top-up or disposal — to the refrigerant ledger for a unit attached to the technician's assigned job. The servicing technician and their certification number are taken from the authenticated caller and are not accepted as input. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The EPA-608 §82.166 ledger entry this write appended.","properties":{"id":{"type":"string","format":"uuid","description":"The equipment the entry was logged against — the addressed resource."},"transactionId":{"type":"string","nullable":true,"description":"The refrigerant_transactions row this write created, when it could be identified unambiguously; null otherwise. The record is always created — this field is a convenience reference, never the proof that it was."},"txnType":{"type":"string","enum":["charge","recovery","top_up","disposal"]},"quantityOz":{"type":"integer"},"workOrderId":{"type":"string","format":"uuid"},"rowVersion":{"type":"null","description":"Always null. `refrigerant_transactions` is append-only and carries no row_version column, so this operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second row was appended."}},"required":["id","transactionId","txnType","quantityOz","workOrderId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"refrigerant_transactions","x-thermal-examples":[{"name":"log a 32 oz charge with no leak found","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333","txnType":"charge","quantityOz":32,"leakFound":"no"}}]}},"/equipment/{id}/refrigerant-transactions/approve":{"post":{"operationId":"equipment.add_refrigerant_transaction.approve","summary":"Log an EPA-608 refrigerant transaction against a unit — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The EPA-608 §82.166 ledger entry this write appended.","properties":{"id":{"type":"string","format":"uuid","description":"The equipment the entry was logged against — the addressed resource."},"transactionId":{"type":"string","nullable":true,"description":"The refrigerant_transactions row this write created, when it could be identified unambiguously; null otherwise. The record is always created — this field is a convenience reference, never the proof that it was."},"txnType":{"type":"string","enum":["charge","recovery","top_up","disposal"]},"quantityOz":{"type":"integer"},"workOrderId":{"type":"string","format":"uuid"},"rowVersion":{"type":"null","description":"Always null. `refrigerant_transactions` is append-only and carries no row_version column, so this operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second row was appended."}},"required":["id","transactionId","txnType","quantityOz","workOrderId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"refrigerant_transactions","x-thermal-examples":[{"name":"log a 32 oz charge with no leak found","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333","txnType":"charge","quantityOz":32,"leakFound":"no"}}]}},"/equipment/{id}/refrigerant-transactions/preview":{"post":{"operationId":"equipment.add_refrigerant_transaction.preview","summary":"Log an EPA-608 refrigerant transaction against a unit — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"refrigerant_transactions","x-thermal-examples":[{"name":"log a 32 oz charge with no leak found","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333","txnType":"charge","quantityOz":32,"leakFound":"no"}}]}},"/field-purchases/{offlineId}":{"post":{"operationId":"field_purchase.submit","summary":"Submit a queued field purchase","description":"The terminal write of the field-purchase entry flow, and STEP 3 of the two-step direct-upload contract. `offlineId` is the client-chosen idempotency identity of the purchase itself, independent of `Idempotency-Key`: an offline id that already has a row returns that row's id with `created: false` and writes no second purchase, however many times it is sent and whatever key each attempt carries. To attach a receipt, first call `POST /field-purchases/{offlineId}/receipt-upload` (step 1), PUT the bytes to the `target.pathname` it returns using `target.clientToken` (step 2), then send `receiptUpload: { fileName, contentType, sizeBytes, pathname }` here — the same declaration as step 1 plus that pathname. The server re-verifies the stored object server-side (tenancy-bound prefix, existence, content type, byte length, magic-number signature) before the row is written; a failed verification writes NO purchase and deletes the upload. A work order the caller holds no live appointment on, or one in another organization, is reported as `404`. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"offlineId","in":"path","required":true,"description":"The offlineId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The field purchase this offline id owns, after the governed write.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_purchases` row id."},"offlineId":{"type":"string"},"created":{"type":"boolean","description":"False when this offline id already had a row and the existing one was returned unchanged. A duplicate submit is never a second purchase."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: `field_purchases` carries no server-owned row version."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","offlineId","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"field_purchases","x-thermal-examples":[{"name":"submit a queued purchase with a verified receipt","request":{"offlineId":"fp-2026-09-20-0001","workOrderId":"33333333-3333-4333-8333-333333333333","vendorName":"Ferguson","purchaseDate":"2026-09-20","subtotalCents":12000,"taxCents":1020,"freightCents":0,"totalCents":13020,"lines":[{"description":"Contactor, 40A","quantity":1,"unitCostCents":12000}],"receiptUpload":{"fileName":"receipt.jpg","contentType":"image/jpeg","sizeBytes":182311,"pathname":"field-purchases/11111111-1111-4111-8111-111111111111/fp-2026-09-20-0001/44444444-4444-4444-8444-444444444444.jpg"}}}]}},"/field-purchases/{offlineId}/approve":{"post":{"operationId":"field_purchase.submit.approve","summary":"Submit a queued field purchase — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"offlineId","in":"path","required":true,"description":"The offlineId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The field purchase this offline id owns, after the governed write.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_purchases` row id."},"offlineId":{"type":"string"},"created":{"type":"boolean","description":"False when this offline id already had a row and the existing one was returned unchanged. A duplicate submit is never a second purchase."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: `field_purchases` carries no server-owned row version."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","offlineId","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"field_purchases","x-thermal-examples":[{"name":"submit a queued purchase with a verified receipt","request":{"offlineId":"fp-2026-09-20-0001","workOrderId":"33333333-3333-4333-8333-333333333333","vendorName":"Ferguson","purchaseDate":"2026-09-20","subtotalCents":12000,"taxCents":1020,"freightCents":0,"totalCents":13020,"lines":[{"description":"Contactor, 40A","quantity":1,"unitCostCents":12000}],"receiptUpload":{"fileName":"receipt.jpg","contentType":"image/jpeg","sizeBytes":182311,"pathname":"field-purchases/11111111-1111-4111-8111-111111111111/fp-2026-09-20-0001/44444444-4444-4444-8444-444444444444.jpg"}}}]}},"/field-purchases/{offlineId}/preview":{"post":{"operationId":"field_purchase.submit.preview","summary":"Submit a queued field purchase — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"offlineId","in":"path","required":true,"description":"The offlineId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"field_purchases","x-thermal-examples":[{"name":"submit a queued purchase with a verified receipt","request":{"offlineId":"fp-2026-09-20-0001","workOrderId":"33333333-3333-4333-8333-333333333333","vendorName":"Ferguson","purchaseDate":"2026-09-20","subtotalCents":12000,"taxCents":1020,"freightCents":0,"totalCents":13020,"lines":[{"description":"Contactor, 40A","quantity":1,"unitCostCents":12000}],"receiptUpload":{"fileName":"receipt.jpg","contentType":"image/jpeg","sizeBytes":182311,"pathname":"field-purchases/11111111-1111-4111-8111-111111111111/fp-2026-09-20-0001/44444444-4444-4444-8444-444444444444.jpg"}}}]}},"/field-purchases/{offlineId}/receipt-upload":{"post":{"operationId":"field_purchase.prepare_receipt_upload","summary":"Prepare a field-purchase receipt upload","description":"STEP 1 OF THE TWO-STEP DIRECT-UPLOAD CONTRACT. Send the file's declaration only — `{ fileName, contentType, sizeBytes }` — never its bytes. The response's `target` is an exact-path, single-file, size-capped storage capability: PUT the bytes straight to the storage host at `target.pathname` using `target.clientToken` (STEP 2, no Thermal endpoint involved), then present that same `pathname` back on `POST /field-purchases/{offlineId}` as `receiptUpload: { fileName, contentType, sizeBytes, pathname }` (STEP 3 — the complete step is FOLDED INTO the terminal write, there is no third endpoint). `target.pathname` is server-chosen and tenancy-bound (`field-purchases/{organizationId}/{offlineId}/{uuid}.{ext}`), so a caller cannot aim an upload at another tenant's prefix, and the terminal write re-verifies the stored object's content type, byte length and magic-number signature against the declaration before any row is written. This step writes nothing to the spine. Retrying with the same `Idempotency-Key` replays the SAME capability rather than minting a second one; a 403 from the storage PUT means the capability expired — call this again and PUT again. An offline id this caller may not act for is reported as `404`, never as `403`. An organization whose Platform API governed-write dial is `suggest` or `off` is refused here as well as on the terminal write: minting a redeemable storage capability is an act, not a look at one. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"offlineId","in":"path","required":true,"description":"The offlineId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The storage capability step 1 of the direct-upload contract mints.","properties":{"id":{"type":"string","description":"The offline id this capability is bound to — echoed so a client can match a reply to a queued entry."},"target":{"type":"object","description":"An exact-path, single-file, size-capped storage capability. PUT the bytes to `pathname` with `clientToken`, then present `pathname` back on the terminal write.","properties":{"pathname":{"type":"string","description":"Server-chosen and tenancy-bound: `field-purchases/{organizationId}/{offlineId}/{uuid}.{ext}`. A caller cannot choose it."},"clientToken":{"type":"string","description":"Short-lived bearer for the storage PUT. Never reuse it for a different pathname."},"access":{"type":"string","enum":["public","private"]}},"required":["pathname","clientToken","access"],"additionalProperties":false},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: preparing an upload writes no versioned spine row."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result — the SAME capability, not a second one."}},"required":["id","target","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"field_purchases","x-thermal-examples":[{"name":"prepare a JPEG receipt on an assigned work order","request":{"offlineId":"fp-2026-09-20-0001","workOrderId":"33333333-3333-4333-8333-333333333333","file":{"fileName":"receipt.jpg","contentType":"image/jpeg","sizeBytes":182311}}}]}},"/field-purchases/{offlineId}/receipt-upload/approve":{"post":{"operationId":"field_purchase.prepare_receipt_upload.approve","summary":"Prepare a field-purchase receipt upload — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"offlineId","in":"path","required":true,"description":"The offlineId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The storage capability step 1 of the direct-upload contract mints.","properties":{"id":{"type":"string","description":"The offline id this capability is bound to — echoed so a client can match a reply to a queued entry."},"target":{"type":"object","description":"An exact-path, single-file, size-capped storage capability. PUT the bytes to `pathname` with `clientToken`, then present `pathname` back on the terminal write.","properties":{"pathname":{"type":"string","description":"Server-chosen and tenancy-bound: `field-purchases/{organizationId}/{offlineId}/{uuid}.{ext}`. A caller cannot choose it."},"clientToken":{"type":"string","description":"Short-lived bearer for the storage PUT. Never reuse it for a different pathname."},"access":{"type":"string","enum":["public","private"]}},"required":["pathname","clientToken","access"],"additionalProperties":false},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: preparing an upload writes no versioned spine row."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result — the SAME capability, not a second one."}},"required":["id","target","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"field_purchases","x-thermal-examples":[{"name":"prepare a JPEG receipt on an assigned work order","request":{"offlineId":"fp-2026-09-20-0001","workOrderId":"33333333-3333-4333-8333-333333333333","file":{"fileName":"receipt.jpg","contentType":"image/jpeg","sizeBytes":182311}}}]}},"/field-purchases/{offlineId}/receipt-upload/preview":{"post":{"operationId":"field_purchase.prepare_receipt_upload.preview","summary":"Prepare a field-purchase receipt upload — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"offlineId","in":"path","required":true,"description":"The offlineId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"field_purchases","x-thermal-examples":[{"name":"prepare a JPEG receipt on an assigned work order","request":{"offlineId":"fp-2026-09-20-0001","workOrderId":"33333333-3333-4333-8333-333333333333","file":{"fileName":"receipt.jpg","contentType":"image/jpeg","sizeBytes":182311}}}]}},"/field/day":{"get":{"operationId":"technician.day","summary":"List the calling technician's work orders for today","description":"Today's work orders assigned to the calling technician, in the same page shape `work_order.list` returns, each item adding its service site's `customerName` and one-line `siteAddress` (null when the site or customer is deleted). `today` is resolved server-side from the organization's timezone, never from a client-supplied instant. Branch scope comes from the resolved context. Naming any technician other than the caller is refused with `403`.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"technicianId","in":"query","required":false,"description":"Optional. When present it must be the caller's own staff id; any other value is refused with `403`. It never selects whose day is read — the session does.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size. The maximum is a contract limit and is validated, not clamped silently (http-contract.md § Pagination).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque keyset cursor from a previous page's nextCursor. There is no offset pagination on spine reads, so a concurrent write cannot shift a page boundary.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A cursor-paginated page of work orders on the technician's day.","properties":{"organizationId":{"type":"string","format":"uuid","description":"The resolved internal organization UUID, never a Clerk organization id."},"timeZone":{"type":"string","description":"The organization's IANA timezone used to render each scheduled instant."},"viewerIsInternal":{"type":"boolean","description":"Optional. Whether the calling login is internal (Thermal staff or a test login), classified server-side from its verified sign-in addresses for product analytics. Omitted when the classification is unavailable; no address is ever returned."},"items":{"type":"array","items":{"type":"object","description":"A work order as the technician's day shows it: the `work_order.list` summary plus the site's customer name and one-line address.","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","description":"The spine row's current version (`_shared.ts`'s server-owned `row_version`, guarded by migration 0385's trigger). A client presents this back as `expectedRowVersion` on a governed write; a stale value is a 409, never a silent last-write-wins.","minimum":1},"number":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"summary":{"type":"string","nullable":true},"serviceSiteId":{"type":"string","format":"uuid","nullable":true},"scheduledStart":{"type":"string","format":"date-time","nullable":true},"scheduledEnd":{"type":"string","format":"date-time","nullable":true},"driveMinutes":{"type":"number","minimum":0,"description":"Stored optimiser drive minutes from the adjacent previous stop."},"leaveBy":{"type":"string","format":"date-time","description":"Promised window start minus the stored drive minutes; format in the response timeZone."},"etaAt":{"type":"string","format":"date-time","nullable":true},"etaSource":{"type":"string","enum":["computed","manual"],"nullable":true},"customerName":{"type":"string","nullable":true,"description":"The service site's customer name, or null when the site or its customer is deleted."},"siteAddress":{"type":"string","nullable":true,"description":"The service site's address on one line (`address line 1, city, state, zip`, blanks skipped), or null when the site is deleted or has no address."}},"required":["id","rowVersion","number","status","priority","summary","serviceSiteId","scheduledStart","scheduledEnd","customerName","siteAddress"],"additionalProperties":false}},"nextCursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next page, or null when no more rows exist."},"limit":{"type":"integer","description":"The page size actually applied."}},"required":["organizationId","timeZone","items","nextCursor","limit"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-schedule","x-thermal-pagination":{"style":"cursor","defaultPageSize":25,"maxPageSize":100,"sortKeys":["scheduledStart","id"]},"x-thermal-examples":[{"name":"my-day","request":{"limit":25}}]}},"/field/equipment/{id}":{"get":{"operationId":"field_equipment.get","summary":"Get one installed unit's detail for the technician app","description":"One unit's detail — type, make, model, serial, external id, install year, zone, HVAC details (tonnage, refrigerant, EPA appliance class), warranty status/dates/terms and the nameplate photo — the same fields `/tech/[id]`'s Equipment card renders for the linked unit. Wraps the page's equipment read verbatim; equipment is a spine root, so the resource is addressed by its own id and the technician's right to read it is derived from a live assignment.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The equipment id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"One installed unit as the technician's Equipment card renders it (`/tech/[id]`'s Equipment region).","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string","nullable":true},"type":{"type":"string"},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true},"installYear":{"type":"integer","nullable":true},"zone":{"type":"object","nullable":true,"description":"The unit's site-zone sub-location, or null when none is set.","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string"}},"required":["id","label"],"additionalProperties":false},"hvacDetails":{"type":"object","nullable":true,"description":"The unit's 1:1 HVAC-physics extension (`equipment_hvac_details`, migration 0123). Every live unit has one; null only if the paired row is unexpectedly absent.","properties":{"tonnageTenths":{"type":"integer","nullable":true,"description":"Cooling capacity in integer tenths (15 = 1.5 ton); null for non-cooling assets."},"refrigerant":{"type":"string"},"epaApplianceClass":{"type":"string","description":"The EPA-608/AIM appliance class — the same column `equipment.set_epa_appliance_class` writes (issue 3442)."}},"required":["tonnageTenths","refrigerant","epaApplianceClass"],"additionalProperties":false},"warrantyStatus":{"type":"string","enum":["active","expired","unknown"],"description":"`deriveWarrantyStatus`'s read-time result — the same badge the Equipment card shows, derived from the dates when present and the enum otherwise."},"warrantyStartDate":{"type":"string","format":"date","nullable":true},"warrantyExpiryDate":{"type":"string","format":"date","nullable":true},"warrantyTerms":{"type":"string","nullable":true},"nameplatePhotoUrl":{"type":"string","nullable":true}},"required":["id","externalId","type","make","model","serial","installYear","zone","hvacDetails","warrantyStatus","warrantyStartDate","warrantyExpiryDate","warrantyTerms","nameplatePhotoUrl"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"equipment-field","x-thermal-examples":[{"name":"one-unit","request":{"id":"00000000-0000-4000-8000-000000000020"}}]}},"/field/equipment/{id}/attachments":{"get":{"operationId":"field_equipment.attachments","summary":"List one unit's attachments","description":"Every `equipment_attachments` row on the unit — manuals, photos and links — newest first, exactly the list the Equipment card's attachments section reads. Same org/soft-delete scoping and same own-assignment rule as `field_equipment.get`.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The equipment id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The unit's attachment rows, newest first.","properties":{"attachments":{"type":"array","items":{"type":"object","description":"One `equipment_attachments` row as the Equipment card's attachments list shows it (newest first).","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string"},"url":{"type":"string"},"label":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","kind","url","label","createdAt"],"additionalProperties":false}}},"required":["attachments"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"equipment-field","x-thermal-examples":[{"name":"unit-attachments","request":{"id":"00000000-0000-4000-8000-000000000020"}}]}},"/field/equipment/{id}/readings":{"get":{"operationId":"field_equipment.readings","summary":"List one unit's diagnostic readings","description":"Every `equipment_readings` row on the unit, newest first — the reading rows behind the field diagnose beat's \"view readings\" surface, in the shape `ExistingReading` renders. Same org/soft-delete scoping and same own-assignment rule as `field_equipment.get`.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The equipment id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The unit's reading rows, newest first.","properties":{"readings":{"type":"array","items":{"type":"object","description":"One `equipment_readings` row as the diagnose beat renders it (`ExistingReading`).","properties":{"id":{"type":"string","format":"uuid"},"readingType":{"type":"string"},"valueNumber":{"type":"number","description":"The captured value; `equipment_readings.value_number` is numeric(12,4)."},"unit":{"type":"string"},"capturedAt":{"type":"string","format":"date-time"}},"required":["id","readingType","valueNumber","unit","capturedAt"],"additionalProperties":false}}},"required":["readings"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"equipment-field","x-thermal-examples":[{"name":"unit-readings","request":{"id":"00000000-0000-4000-8000-000000000020"}}]}},"/field/location":{"post":{"operationId":"field_location.report","summary":"Report the technician's position while their own visit is en route","description":"Technician session only. Accepted only for the caller's own visit while it is en route; any other visit answers 403 and writes nothing. recordedAt must be within the last 5 minutes and not in the future. One accepted ping per visit per 10 seconds; the excess answers 429.","security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"appointmentId":{"type":"string","format":"uuid"},"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"accuracy":{"type":"number","minimum":0,"nullable":true,"description":"Device accuracy radius in metres. Values above 10000 are stored as 10000."},"recordedAt":{"type":"string","format":"date-time","description":"The phone's fix time. Refused (400) when in the future or older than 5 minutes."}},"required":["appointmentId","latitude","longitude","recordedAt"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean"},"receivedAt":{"type":"string","format":"date-time"}},"required":["accepted","receivedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile"}},"/field/work-orders/{id}":{"get":{"operationId":"field_work_order.get","summary":"Get one assigned work order with its PM checklist for the caller","description":"The technician app's work-order detail surface: the spine context a technician needs (customer, service site, installed equipment, every non-cancelled appointment) plus the work order's PM checklist tasks ordered sortOrder asc, createdAt asc, its rental-movement fleet transitions newest-event first, its read-only status history (the work order's and the current visit's status transitions from the events ledger, newest first, at most 50), and the bill-to party. Org-scoped by the wrapped loader and assignment-gated for technicians: a technician reads only a work order they hold a non-canceled assigned appointment on; a non-technician role in the org may read any work order in the org.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"appointmentId","in":"query","required":false,"description":"The visit the technician opened. It wins only when it is live and assigned to the linked staff user; otherwise the server selects that user's latest live visit.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A work order with its customer, service site, equipment, appointments, PM checklist, rental-movement transitions, status history and bill-to party — the technician app's field detail surface.","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","description":"The spine row's current version (`_shared.ts`'s server-owned `row_version`, guarded by migration 0385's trigger). A client presents this back as `expectedRowVersion` on a governed write; a stale value is a 409, never a silent last-write-wins.","minimum":1},"number":{"type":"string","nullable":true},"status":{"type":"string"},"priority":{"type":"string"},"jobType":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"customer":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"serviceSite":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","nullable":true},"addressLine1":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"zip":{"type":"string","nullable":true},"geoLat":{"type":"number","nullable":true,"description":"The site's latitude, when geocoded."},"geoLng":{"type":"number","nullable":true,"description":"The site's longitude, when geocoded."}},"required":["id","label","addressLine1","city","state","zip","geoLat","geoLng"],"additionalProperties":false},"equipment":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","nullable":true},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true}},"required":["id","type","make","model","serial"],"additionalProperties":false},"appointments":{"type":"array","items":{"type":"object","description":"One visit on a work order. A work order can have several (ADR-0005), so this array never lies about a single-visit shape.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"assignedUserId":{"type":"string","format":"uuid","nullable":true},"etaAt":{"type":"string","format":"date-time","nullable":true},"etaSource":{"type":"string","enum":["computed","manual"],"nullable":true}},"required":["id","status","scheduledStart","scheduledEnd","assignedUserId","etaAt","etaSource"],"additionalProperties":false}},"updatedAt":{"type":"string","format":"date-time"},"holdingTag":{"type":"string","nullable":true},"holdingNote":{"type":"string","nullable":true},"holdPlacement":{"type":"object","nullable":true,"properties":{"placedAt":{"type":"string","format":"date-time"},"placedByName":{"type":"string","nullable":true}},"required":["placedAt","placedByName"],"additionalProperties":false},"currentAppointmentId":{"type":"string","format":"uuid","nullable":true,"description":"The requested live appointment when it belongs to the linked staff user, otherwise that user's open appointment selected by active status, earliest scheduled start, then id (or the first non-canceled appointment for a completed job). Derived server-side; never matched against a Clerk subject on the device."},"pricesHidden":{"type":"boolean","description":"True when technician sell prices are redacted; always supplied by the server."},"pricebookItems":{"type":"array","items":{"type":"object","description":"One active, non-deleted item in the caller's organization pricebook. Barcode is included so the native scanner can select from this already org-scoped catalog without a second untyped lookup.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"unitPriceCents":{"type":"integer","nullable":true},"barcode":{"type":"string","nullable":true}},"required":["id","name","unitPriceCents","barcode"],"additionalProperties":false},"description":"Active pricebook items in the caller's organization, ordered by category then name, for the follow-on parts request picker and barcode selection."},"readingTypes":{"type":"array","description":"The caller organization's active diagnostic reading types, with the exact label and unit the field capture UI displays.","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"unit":{"type":"string"}},"required":["key","label","unit"],"additionalProperties":false}},"draftedSummary":{"type":"string","description":"The deterministic wrap draft assembled from this job's summary, equipment and line items by the same presenter as the web work-beat route."},"photoCount":{"type":"integer","minimum":0,"description":"The work-order attachment count shown by the web wrap beat."},"tasks":{"type":"array","items":{"type":"object","description":"One PM checklist task on the work order, in the order the technician app renders it (sortOrder asc, createdAt asc).","properties":{"id":{"type":"string","format":"uuid"},"taskName":{"type":"string"},"isMandatory":{"type":"boolean"},"fieldType":{"type":"string"},"sortOrder":{"type":"integer"},"completedAt":{"type":"string","format":"date-time","nullable":true},"completedByUserId":{"type":"string","format":"uuid","nullable":true}},"required":["id","taskName","isMandatory","fieldType","sortOrder","completedAt","completedByUserId"],"additionalProperties":false}},"fleetTransitions":{"type":"array","items":{"type":"object","description":"One equipment fleet transition tied to this work order, newest event first. Empty for a non-rental job.","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["pickup","delivery","other"],"description":"The direction this row moves the unit, projected from `toState` exactly as the web screen classifies it (`page.tsx:880-891`): `pickup` when it lands the unit on `available`/`maintenance`, `delivery` when it puts it on `on_rent`/`on_lease`, otherwise `other`."},"fromState":{"type":"string"},"toState":{"type":"string"},"equipment":{"type":"object","nullable":true,"description":"The unit a fleet transition moved, when one is linked.","properties":{"id":{"type":"string","format":"uuid"},"externalId":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"type":{"type":"string","nullable":true}},"required":["id","externalId","serial","make","model","type"],"additionalProperties":false},"dueBackAt":{"type":"string","format":"date-time","nullable":true},"conditionNotes":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true}},"required":["id","kind","fromState","toState","equipment","dueBackAt","conditionNotes","notes"],"additionalProperties":false}},"statusHistory":{"type":"array","items":{"type":"object","description":"One read-only status transition from the events ledger: either the work order's own status change or the current visit's (appointment's) status advance/undo.","properties":{"id":{"type":"string","format":"uuid","description":"The ledger event id."},"scope":{"type":"string","enum":["work_order","appointment"],"description":"`work_order` for a work-order status change; `appointment` for a status advance or undo on the caller's current visit."},"action":{"type":"string","description":"The ledger action verbatim: `status_changed` or `completed` for the work order, `appointment_status_advanced` or `appointment_status_undone` for the visit."},"from":{"type":"string","nullable":true,"description":"The status before the transition, or null when the ledger row did not record one."},"to":{"type":"string","description":"The status after the transition."},"at":{"type":"string","format":"date-time","description":"When the transition was recorded (ISO 8601)."},"actorType":{"type":"string","enum":["user","agent","system","integration"],"description":"Who made the transition: a user, an agent, the system or an integration."}},"required":["id","scope","action","from","to","at","actorType"],"additionalProperties":false},"description":"Read-only status history from the events ledger: the work order's own status changes plus the caller's current visit's status advances and undos (never another visit's), newest first by ledger sequence, at most 50 entries. Empty when nothing is recorded. Optional in the schema so older clients and fixtures stay valid; the server always returns it (possibly empty)."},"billToCustomer":{"type":"object","nullable":true,"description":"The party receiving the invoice for this job (`work_orders.bill_to_customer_id`) when one is resolved, else null. Distinct from `customer` when a billing rule routes the invoice elsewhere (issue 3441's Renter (bill-to) row).","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"required":["id","rowVersion","number","status","priority","jobType","summary","completedAt","customer","serviceSite","equipment","appointments","updatedAt","currentAppointmentId","pricebookItems","readingTypes","draftedSummary","photoCount","tasks","fleetTransitions","billToCustomer"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/balance":{"get":{"operationId":"field_work_order.balance","summary":"Get one work order's balance for the technician app","description":"The money state the technician app's Collect surface reads for one work order: subtotal, tax, total, paid and outstanding balance, plus the settled/unsettled state. Composed from the same server-side primitives `/tech/[id]` renders and the payments recorded against the work order's invoices. Org-scoped by the wrapped loader and assignment-gated for technicians: a technician reads only a work order they hold a non-canceled assigned appointment on; a non-technician role in the org may read any work order in the org. The request carries no price, quantity or amount.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A work order's subtotal, tax, total, paid and outstanding balance.","properties":{"invoiceId":{"oneOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The sole live invoice billing only this work order; null when no unambiguous invoice exists."},"subtotalCents":{"type":"integer"},"taxCents":{"type":"integer"},"totalCents":{"type":"integer"},"paidCents":{"type":"integer"},"balanceDueCents":{"type":"integer"},"settled":{"type":"boolean"},"mode":{"type":"string","enum":["deposit","balance","none"],"description":"Which collection the server accepts right now (issue 5199): `deposit` before the job is completed, on the caller's own en_route / arrived / in_progress visit while the job's deposit cap has room; `balance` once the job is completed or invoiced and a balance is due; `none` otherwise. The Collect surface renders only this mode's actions."},"depositVisitId":{"type":"string","format":"uuid","nullable":true,"description":"Set only in `deposit` mode: the visit the deposit write (`takeFieldDeposit`) must name."},"depositRemainingCents":{"type":"integer","nullable":true,"description":"Set only in `deposit` mode: the most a deposit may be for right now — the job's current total less every deposit already taken on it."}},"required":["invoiceId","subtotalCents","taxCents","totalCents","paidCents","balanceDueCents","settled","mode","depositVisitId","depositRemainingCents"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-payments","x-thermal-examples":[{"name":"assigned-work-order","request":{"id":"00000000-0000-4000-8000-000000000003"}}]}},"/field/work-orders/{id}/briefing":{"get":{"operationId":"field_work_order.briefing","summary":"Get one work order's pre-visit briefing and suggested fix","description":"The pre-visit briefing bundle for the work order: its own snapshot fields (summary, description, priority, job type), the site's access notes, the customer's in-force agreement (active or due_for_renewal) and the linked unit's recent service history — the same inputs /tech/[id] feeds buildPreVisitBriefing — together with the history-derived suggested fix (or null in the no-pattern-yet branch). Assignment-gated for technicians exactly like field_work_order.get.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pre-visit briefing and the history-derived suggested fix.","properties":{"briefing":{"type":"object","description":"The pre-visit briefing bundle the technician's briefing region renders.","properties":{"job":{"type":"object","description":"The work order's own snapshot fields the briefing panel shows.","properties":{"summary":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"priority":{"type":"string"},"jobType":{"type":"string","nullable":true}},"required":["summary","description","priority","jobType"],"additionalProperties":false},"accessNotes":{"type":"string","nullable":true},"agreement":{"type":"object","nullable":true,"description":"The customer's in-force agreement as the briefing shows it, or null when none is in force.","properties":{"planName":{"type":"string"},"status":{"type":"string"},"isDueForRenewal":{"type":"boolean"},"includedServices":{"type":"string","nullable":true},"expiresOn":{"type":"string","nullable":true}},"required":["planName","status","isDueForRenewal","includedServices","expiresOn"],"additionalProperties":false},"history":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","description":"One past service call on the linked unit, as the briefing's history list renders it.","properties":{"id":{"type":"string","format":"uuid"},"performedOn":{"type":"string","format":"date"},"jobType":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true}},"required":["id","performedOn","jobType","summary"],"additionalProperties":false}},"isEmpty":{"type":"boolean"}},"required":["records","isEmpty"],"additionalProperties":false}},"required":["job","accessNotes","agreement","history"],"additionalProperties":false},"suggestedFix":{"type":"object","nullable":true,"description":"The suggested fix derived from the unit's service history, or null when no pattern was found.","properties":{"fixName":{"type":"string"},"reason":{"type":"string"},"confidence":{"type":"string","enum":["most likely","likely","possible"]}},"required":["fixName","reason","confidence"],"additionalProperties":false}},"required":["briefing","suggestedFix"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order-briefing","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/counter-po":{"post":{"operationId":"purchase_order.issue_counter","summary":"Get a PO number for the supply counter","description":"Issues a company-wide PO number for a job the technician has a live appointment on. Choose an existing vendor or a new vendor name. An optional estimate crossing the office approval rule leaves the PO pending approval, with its number still returned. Use the same client idempotencyKey across the phone web action and Platform API to recover the same PO. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendorId":{"type":"string","format":"uuid"},"vendorName":{"type":"string","minLength":1,"maxLength":200},"estimatedAmountCents":{"type":"integer","minimum":0,"maximum":2147483647},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"required":["idempotencyKey"],"additionalProperties":false,"oneOf":[{"required":["vendorId"]},{"required":["vendorName"]}]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"null"},"purchaseOrderId":{"type":"string","format":"uuid"},"number":{"type":"integer"},"vendorId":{"type":"string","format":"uuid"},"vendorName":{"type":"string"},"status":{"type":"string","enum":["ordered","pending_approval"]},"replayed":{"type":"boolean"}},"required":["id","rowVersion","purchaseOrderId","number","vendorId","vendorName","status","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"supply counter","request":{"id":"66666666-6666-4666-8666-666666666666","vendorName":"Ferguson","estimatedAmountCents":18500,"idempotencyKey":"counter-visit-1"}}]}},"/field/work-orders/{id}/counter-po/approve":{"post":{"operationId":"purchase_order.issue_counter.approve","summary":"Get a PO number for the supply counter — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendorId":{"type":"string","format":"uuid"},"vendorName":{"type":"string","minLength":1,"maxLength":200},"estimatedAmountCents":{"type":"integer","minimum":0,"maximum":2147483647},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"required":["idempotencyKey"],"additionalProperties":false,"oneOf":[{"required":["vendorId"]},{"required":["vendorName"]}]}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"null"},"purchaseOrderId":{"type":"string","format":"uuid"},"number":{"type":"integer"},"vendorId":{"type":"string","format":"uuid"},"vendorName":{"type":"string"},"status":{"type":"string","enum":["ordered","pending_approval"]},"replayed":{"type":"boolean"}},"required":["id","rowVersion","purchaseOrderId","number","vendorId","vendorName","status","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"supply counter","request":{"id":"66666666-6666-4666-8666-666666666666","vendorName":"Ferguson","estimatedAmountCents":18500,"idempotencyKey":"counter-visit-1"}}]}},"/field/work-orders/{id}/counter-po/preview":{"post":{"operationId":"purchase_order.issue_counter.preview","summary":"Get a PO number for the supply counter — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendorId":{"type":"string","format":"uuid"},"vendorName":{"type":"string","minLength":1,"maxLength":200},"estimatedAmountCents":{"type":"integer","minimum":0,"maximum":2147483647},"idempotencyKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"}},"required":["idempotencyKey"],"additionalProperties":false,"oneOf":[{"required":["vendorId"]},{"required":["vendorName"]}]}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-purchases","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"supply counter","request":{"id":"66666666-6666-4666-8666-666666666666","vendorName":"Ferguson","estimatedAmountCents":18500,"idempotencyKey":"counter-visit-1"}}]}},"/field/work-orders/{id}/coverage":{"get":{"operationId":"field_work_order.coverage","summary":"Get one work order's agreement coverage for the technician app","description":"The in-force service agreement for the work order's customer (status active or due_for_renewal, newest first, never soft-deleted) plus the linked unit's itemized coverage row. A due_for_renewal agreement is still in force and is returned with its own status for the screen to badge. `agreement` is null when the customer has no in-force agreement; `unitCoverage` is null when the job has no linked unit or no in-force agreement. Assignment-gated for technicians exactly like field_work_order.get.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's in-force agreement and the linked unit's coverage.","properties":{"agreement":{"type":"object","nullable":true,"description":"The customer's in-force agreement (status active or due_for_renewal, not soft-deleted, newest first) or null when none is in force.","properties":{"id":{"type":"string","format":"uuid"},"planName":{"type":"string","nullable":true},"status":{"type":"string"},"expiresOn":{"type":"string","format":"date","nullable":true},"responseWindowHours":{"type":"integer","nullable":true},"planTemplateName":{"type":"string","nullable":true}},"required":["id","planName","status","expiresOn","responseWindowHours","planTemplateName"],"additionalProperties":false},"unitCoverage":{"type":"object","nullable":true,"description":"The linked unit's itemized coverage on the in-force agreement, or null when the job has no linked unit or no in-force agreement.","properties":{"covers":{"type":"string","nullable":true},"resolvedSlaHours":{"type":"integer","nullable":true}},"required":["covers","resolvedSlaHours"],"additionalProperties":false}},"required":["agreement","unitCoverage"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order-coverage","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/inspection":{"get":{"operationId":"field_work_order.inspection","summary":"Get one work order's active inspection for the technician app","description":"The work order's active/most-recent non-deleted inspection — its id, status and template name — the same read /tech/[id]'s Inspection card renders. `active` is null when the work order has no inspection at all; the screen decides whether to render the Start vs Resume/View state. Assignment-gated for technicians exactly like field_work_order.get.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's active/most-recent inspection, or null.","properties":{"active":{"type":"object","nullable":true,"description":"The work order's active/most-recent inspection, or null when none exists. `templateName` is null only when the inspection's template relation is unexpectedly absent.","properties":{"id":{"type":"string","format":"uuid"},"templateName":{"type":"string","nullable":true},"status":{"type":"string"}},"required":["id","templateName","status"],"additionalProperties":false}},"required":["active"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order-inspection","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/inspection-detail":{"get":{"operationId":"field_work_order.inspection_detail","summary":"Get one work order's inspection and arrival-safety checklist detail","description":"The linked equipment and caller's current visit, most recent inspection with immutable response snapshots and deficiencies, active templates available to start, and the applicable arrival JHA with ordered questions and the visit-scoped latest submission. The read is not gated on work-order status and is assignment-gated exactly like field_work_order.get.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"equipmentId":{"type":"string","format":"uuid","nullable":true},"currentAppointment":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"}},"required":["id","status"],"additionalProperties":false},"inspection":{"type":"object","nullable":true,"description":"The most recent inspection run, with every response snapshot and deficiency.","properties":{"id":{"type":"string","format":"uuid"},"equipmentId":{"type":"string","format":"uuid"},"template":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"templateVersion":{"type":"integer"},"status":{"type":"string"},"startedAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"summary":{"type":"string","nullable":true},"signatureSrc":{"type":"string","nullable":true},"shareToken":{"type":"string","nullable":true},"responses":{"type":"array","items":{"type":"object","description":"One inspection response, including the immutable execution snapshot copied from its template item.","properties":{"id":{"type":"string","format":"uuid"},"templateItemId":{"type":"string","format":"uuid","nullable":true},"sectionLabel":{"type":"string"},"sortOrder":{"type":"integer"},"label":{"type":"string"},"fieldType":{"type":"string"},"unit":{"type":"string","nullable":true},"isMandatory":{"type":"boolean"},"passRule":{"type":"object","nullable":true,"properties":{"min":{"type":"number"},"max":{"type":"number"},"target":{"type":"number"},"nameplateField":{"type":"string"}},"additionalProperties":false},"visibleWhen":{"type":"object","nullable":true,"properties":{"itemRef":{"type":"string"},"operator":{"type":"string","enum":["answered","equals","pass","fail"]},"value":{"type":"string"}},"required":["itemRef","operator"],"additionalProperties":false,"description":"Shows the item only while this rule is met; null when the item always shows."},"enabledWhen":{"type":"object","nullable":true,"properties":{"itemRef":{"type":"string"},"operator":{"type":"string","enum":["answered","equals","pass","fail"]},"value":{"type":"string"}},"required":["itemRef","operator"],"additionalProperties":false,"description":"Locks the item until this rule is met; null when the item is never locked."},"severity":{"type":"string"},"selectOptions":{"type":"array","nullable":true,"items":{"type":"string"}},"readingType":{"type":"string","nullable":true},"recommendationTemplate":{"type":"string","nullable":true},"defaultPricebookCode":{"type":"string","nullable":true},"complianceTier":{"type":"string","nullable":true},"complianceCorrectionHours":{"type":"integer","nullable":true},"complianceNotificationRequired":{"type":"boolean"},"complianceNotificationHours":{"type":"integer","nullable":true},"sourcePackKey":{"type":"string","nullable":true},"sourcePackVersion":{"type":"integer","nullable":true},"sourceTemplateKey":{"type":"string","nullable":true},"sourceTemplateVersion":{"type":"integer","nullable":true},"sourceTemplateItemId":{"type":"string","format":"uuid","nullable":true},"value":{"type":"string","nullable":true,"description":"The captured value. Signature values are authenticated read URLs, never private object keys."},"valueNumber":{"type":"string","nullable":true},"passState":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"completedByUserId":{"type":"string","format":"uuid","nullable":true}},"required":["id","templateItemId","sectionLabel","sortOrder","label","fieldType","unit","isMandatory","passRule","visibleWhen","enabledWhen","severity","selectOptions","readingType","recommendationTemplate","defaultPricebookCode","complianceTier","complianceCorrectionHours","complianceNotificationRequired","complianceNotificationHours","sourcePackKey","sourcePackVersion","sourceTemplateKey","sourceTemplateVersion","sourceTemplateItemId","value","valueNumber","passState","note","completedAt","completedByUserId"],"additionalProperties":false}},"deficiencies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"responseId":{"type":"string","format":"uuid","nullable":true},"equipmentId":{"type":"string","format":"uuid"},"severity":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"photoUrls":{"type":"array","items":{"type":"string"}},"recommendedPricebookCode":{"type":"string","nullable":true},"recommendedPriceCents":{"type":"integer","nullable":true},"status":{"type":"string"},"estimateId":{"type":"string","format":"uuid","nullable":true}},"required":["id","responseId","equipmentId","severity","title","description","photoUrls","recommendedPricebookCode","recommendedPriceCents","status","estimateId"],"additionalProperties":false}}},"required":["id","equipmentId","template","templateVersion","status","startedAt","completedAt","summary","signatureSrc","shareToken","responses","deficiencies"],"additionalProperties":false},"inspectionTemplates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"version":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sectionLabel":{"type":"string"},"sortOrder":{"type":"integer"},"label":{"type":"string"},"fieldType":{"type":"string"},"unit":{"type":"string","nullable":true},"isMandatory":{"type":"boolean"},"passRule":{"type":"object","nullable":true,"properties":{"min":{"type":"number"},"max":{"type":"number"},"target":{"type":"number"},"nameplateField":{"type":"string"}},"additionalProperties":false},"visibleWhen":{"type":"object","nullable":true,"properties":{"itemRef":{"type":"string"},"operator":{"type":"string","enum":["answered","equals","pass","fail"]},"value":{"type":"string"}},"required":["itemRef","operator"],"additionalProperties":false,"description":"Shows the item only while this rule is met; null when the item always shows."},"enabledWhen":{"type":"object","nullable":true,"properties":{"itemRef":{"type":"string"},"operator":{"type":"string","enum":["answered","equals","pass","fail"]},"value":{"type":"string"}},"required":["itemRef","operator"],"additionalProperties":false,"description":"Locks the item until this rule is met; null when the item is never locked."},"severity":{"type":"string"},"selectOptions":{"type":"array","nullable":true,"items":{"type":"string"}},"readingType":{"type":"string","nullable":true},"recommendationTemplate":{"type":"string","nullable":true},"defaultPricebookCode":{"type":"string","nullable":true},"complianceTier":{"type":"string","nullable":true},"complianceCorrectionHours":{"type":"integer","nullable":true},"complianceNotificationRequired":{"type":"boolean"},"complianceNotificationHours":{"type":"integer","nullable":true}},"required":["id","sectionLabel","sortOrder","label","fieldType","unit","isMandatory","passRule","visibleWhen","enabledWhen","severity","selectOptions","readingType","recommendationTemplate","defaultPricebookCode","complianceTier","complianceCorrectionHours","complianceNotificationRequired","complianceNotificationHours"],"additionalProperties":false}}},"required":["id","name","version","items"],"additionalProperties":false}},"jha":{"type":"object","properties":{"template":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"version":{"type":"integer"},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sortOrder":{"type":"integer"},"prompt":{"type":"string"},"responseType":{"type":"string"},"options":{"type":"array","nullable":true,"items":{"type":"string"}},"hazardTrigger":{"type":"boolean"},"stopOnValue":{"type":"string","nullable":true},"isMandatory":{"type":"boolean"},"isAcknowledgement":{"type":"boolean"}},"required":["id","sortOrder","prompt","responseType","options","hazardTrigger","stopOnValue","isMandatory","isAcknowledgement"],"additionalProperties":false}}},"required":["id","name","version","questions"],"additionalProperties":false},"latestSubmission":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"templateId":{"type":"string","format":"uuid"},"templateVersion":{"type":"integer"},"templateName":{"type":"string"},"stopState":{"type":"string"},"submittedAt":{"type":"string","format":"date-time"}},"required":["id","templateId","templateVersion","templateName","stopState","submittedAt"],"additionalProperties":false}},"required":["template","latestSubmission"],"additionalProperties":false}},"required":["equipmentId","currentAppointment","inspection","inspectionTemplates","jha"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order-inspection-detail","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/jha":{"get":{"operationId":"field_work_order.jha","summary":"Get one work order's arrival JHA template and latest submission","description":"The policy-resolved active JHA template that applies to the work order (by job type and, when a unit is linked, its equipment type) plus the most recent submission already on file for the work order — scoped to the caller's visit where one is resolved, so an earlier visit's completed JHA never hides a later visit's arrival checklist. The whole body is null when no active template applies. The read is NOT gated on the work order being in progress; that is the screen's render condition. Assignment-gated for technicians exactly like field_work_order.get.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","nullable":true,"description":"The applicable JHA template and the latest submission, or null when no active template applies.","properties":{"templateId":{"type":"string","format":"uuid"},"templateName":{"type":"string"},"latestSubmission":{"type":"object","nullable":true,"description":"The most recent JHA submission for the work order (scoped to the caller's visit where one is resolved), or null when none exists.","properties":{"id":{"type":"string","format":"uuid"},"templateName":{"type":"string"},"stopState":{"type":"string"},"submittedAt":{"type":"string","format":"date-time"}},"required":["id","templateName","stopState","submittedAt"],"additionalProperties":false}},"required":["templateId","templateName","latestSubmission"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order-jha","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/line-items":{"get":{"operationId":"field_work_order.line_items","summary":"List one work order's priced line items for the technician app","description":"The priced part/labour lines the technician app's `Parts & Labor` region renders for one work order: id, description, quantity in units, unit price, extended total, the resolved pricebook item and the line's provenance. Org-scoped by the wrapped loader and assignment-gated for technicians: a technician reads only a work order they hold a non-canceled assigned appointment on; a non-technician role in the org may read any work order in the org. The request carries no price, quantity or amount.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's priced line items, in creation order.","properties":{"pricesHidden":{"type":"boolean","description":"True when technician sell prices are redacted; always supplied by the server."},"lineItems":{"type":"array","items":{"type":"object","description":"One priced part/labour line on a work order.","properties":{"id":{"type":"string","format":"uuid"},"description":{"type":"string"},"qtyUnits":{"type":"number","description":"Quantity in units (`quantity_milli / 1000`); fractional labour hours stay off floats."},"unitPriceCents":{"type":"integer","nullable":true},"extendedCents":{"type":"integer","nullable":true,"description":"The row's stored `line_total_cents` — the price captured when the line was added."},"pricebookItemId":{"type":"string","format":"uuid","nullable":true,"description":"The catalogue item the line was added from, resolved from its stored `pricebook_code`; null for a manual or generated line, or one whose catalogue item is gone."},"source":{"type":"string","enum":["pricebook","generated","manual"],"description":"The line's provenance: `pricebook` when it carries a catalogue code, `generated` when a completed appointment produced it, `manual` otherwise."}},"required":["id","description","qtyUnits","unitPriceCents","extendedCents","pricebookItemId","source"],"additionalProperties":false}}},"required":["lineItems"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-payments","x-thermal-examples":[{"name":"assigned-work-order","request":{"id":"00000000-0000-4000-8000-000000000002"}}]}},"/field/work-orders/{id}/messages":{"get":{"operationId":"field_work_order.messages","summary":"List one work order's internal staff messages","description":"The internal staff thread on the work order (customers never see it): the newest page of messages oldest first, the thread's total and unread counts for the signed-in user, and a cursor for earlier messages. Assignment-gated for technicians exactly like field_work_order.get.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"before","in":"query","required":false,"description":"The earlierCursor of a previous page, to read the messages before it.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"One page of the thread and its counts.","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"authorName":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string","description":"UTC ISO timestamp with microseconds."}},"required":["id","authorUserId","authorName","body","createdAt"],"additionalProperties":false}},"totalCount":{"type":"integer"},"unreadCount":{"type":"integer","description":"Messages from other staff newer than this user's read boundary."},"earlierCursor":{"type":"string","nullable":true}},"required":["messages","totalCount","unreadCount","earlierCursor"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order-thread","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/field/work-orders/{id}/parts-stock":{"get":{"operationId":"field_work_order.parts_stock","summary":"Read per-part truck and warehouse stock for one work order","description":"Stock in the work order's branch, grouped by pricebook item: own truck quantity, other trucks with holder names and quantities, and branch warehouse quantity. Items without stock are absent; a work order without a branch returns an empty stock list. Technicians need a non-canceled assigned appointment; office roles may read work orders within their organization and branch scope.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"stock":{"type":"array","items":{"type":"object","properties":{"pricebookItemId":{"type":"string","format":"uuid"},"ownVan":{"type":"integer"},"otherTrucks":{"type":"array","items":{"type":"object","properties":{"holderName":{"type":"string"},"quantity":{"type":"integer"}},"required":["holderName","quantity"],"additionalProperties":false}},"branch":{"type":"integer"}},"required":["pricebookItemId","ownVan","otherTrucks","branch"],"additionalProperties":false}}},"required":["stock"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-work","x-thermal-examples":[{"name":"assigned-work-order","request":{"id":"00000000-0000-4000-8000-000000000004"}}]}},"/field/work-orders/{id}/purchase-orders":{"get":{"operationId":"field_work_order.purchase_orders","summary":"List one work order's receivable purchase orders for the technician app","description":"The purchase orders raised for one work order that can still be received onto a van: ordered or partly received, not deleted, in the caller's branch scope. Each carries its number, status, vendor name and lines with ordered, received and open quantities. Assignment-gated for technicians: a technician reads only a work order they hold a non-canceled assigned appointment on; a non-technician role in the org may read any work order in their branch scope.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's receivable purchase orders (ordered or partly received), by purchase order number.","properties":{"purchaseOrders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"integer","nullable":true},"status":{"type":"string","enum":["ordered","partial"]},"vendorName":{"type":"string","nullable":true},"lines":{"type":"array","items":{"type":"object","description":"One line of a receivable purchase order, with what is still open on it.","properties":{"lineId":{"type":"string","format":"uuid"},"description":{"type":"string"},"inventoryItemId":{"type":"string","format":"uuid","nullable":true,"description":"The stocked item the line receives into; null for a non-stock line."},"quantity":{"type":"integer","description":"Purchase units ordered (see purchaseUnitLabel); eaches = quantity x purchaseUnitFactor."},"receivedQuantity":{"type":"integer","description":"Purchase units already received."},"openQuantity":{"type":"integer","minimum":0,"description":"Purchase units still to receive: ordered minus received, never below zero."},"purchaseUnitFactor":{"type":"integer","minimum":1,"description":"Eaches per purchase unit on this line; 1 when the line is counted in eaches."},"purchaseUnitLabel":{"type":"string","nullable":true,"description":"The purchase unit the quantities are in (\"case\"); null when they are eaches."}},"required":["lineId","description","inventoryItemId","quantity","receivedQuantity","openQuantity","purchaseUnitFactor","purchaseUnitLabel"],"additionalProperties":false}}},"required":["id","number","status","vendorName","lines"],"additionalProperties":false}}},"required":["purchaseOrders"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"van-stock","x-thermal-examples":[{"name":"assigned-work-order","request":{"id":"00000000-0000-4000-8000-000000000004"}}]}},"/inspections/{inspectionId}/completion":{"post":{"operationId":"inspection.complete","summary":"Complete an inspection","description":"Closes the inspection out: the mandatory-item gate and the signature gate are enforced server-side as a backstop, an immutable point-in-time credential attestation is captured for regulator-facing equipment, and a `service_history` row is generated — all under one `status = 'in_progress'` compare-and-set, so a concurrent or duplicated completion is a no-op rather than a second close. Round-trips with `inspection.start` and `inspection.update_response`: every response saved before completion is readable back afterwards, unchanged. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection after the completion attempt.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"status":{"type":"string","enum":["in_progress","completed"]},"completed":{"type":"boolean","description":"False when the inspection was already completed and this delivery closed nothing."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","status","completed","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"complete a signed inspection","request":{}}]}},"/inspections/{inspectionId}/completion/approve":{"post":{"operationId":"inspection.complete.approve","summary":"Complete an inspection — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection after the completion attempt.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"status":{"type":"string","enum":["in_progress","completed"]},"completed":{"type":"boolean","description":"False when the inspection was already completed and this delivery closed nothing."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","status","completed","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"complete a signed inspection","request":{}}]}},"/inspections/{inspectionId}/completion/preview":{"post":{"operationId":"inspection.complete.preview","summary":"Complete an inspection — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"complete a signed inspection","request":{}}]}},"/inspections/{inspectionId}/deficiencies":{"post":{"operationId":"inspection.create_deficiency","summary":"File a deficiency from a failed or flagged item","description":"Files one `inspection_deficiencies` row — the compliance record a failed or flagged checklist item spawns — and, when the item carries a Fire-pack compliance tier, its compliance clock in the SAME transaction. `deficiencyId` is client-generated and is the writer's own replay guard: a duplicate delivery returns the existing row with `created: false` and files no second deficiency, whatever the idempotency key. The equipment must be the inspection's own unit. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The deficiency this inspection now carries.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"created":{"type":"boolean","description":"False when this deficiency id already existed and no second row was filed."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspection_deficiencies","x-thermal-examples":[{"name":"file a safety deficiency for a failed item","request":{"deficiencyId":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","equipmentId":"77777777-7777-4777-8777-777777777777","responseId":"99999999-9999-4999-8999-999999999999","title":"Cracked heat exchanger","severity":"safety"}}]}},"/inspections/{inspectionId}/deficiencies/{deficiencyId}/photo":{"post":{"operationId":"inspection.upload_deficiency_photo","summary":"Attach a photo to a deficiency","description":"THE TWO-STEP DIRECT-UPLOAD CONTRACT (issue 3556's, reused unchanged). STEP 1 — PREPARE: `POST <this path>/prepare-upload` with the file's DECLARATION only (`file: { fileName, contentType, sizeBytes }`), never its bytes. The reply's `target` is an exact-path, single-file, size-capped storage capability whose `pathname` is server-chosen and tenancy-bound, so a caller cannot aim an upload at another tenant's prefix. This step writes nothing. STEP 2 — PUT: the client PUTs the bytes straight to the storage host at `target.pathname` using `target.clientToken`; no Thermal endpoint is involved and bytes never cross the Platform API. A 403 from storage means the capability expired — call prepare again and PUT again. STEP 3 — COMPLETE, FOLDED INTO THIS WRITE: send the SAME `file` declaration plus the `pathname` step 1 returned. The server re-verifies server-side before any row is written (tenancy-bound prefix, the object exists, content type, byte length and magic-number signature all match the declaration); a failed verification writes nothing and deletes the upload. Retrying the TERMINAL write with the same `Idempotency-Key` replays the stored result rather than storing a second artifact. The prepare step is deliberately NOT idempotent: it writes nothing, so calling it twice simply mints two uuid-keyed pathnames and only the one presented on the terminal write is ever verified or attached. The stored artifact is one `work_order_attachments` row plus one appended url on the deficiency's own `photo_urls`; a duplicate delivery under the same `Idempotency-Key` stores exactly one and appends exactly one. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"deficiencyId","in":"path","required":true,"description":"The deficiencyId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The deficiency after the upload.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"photoCount":{"type":"integer","description":"How many photos the deficiency now carries."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","photoCount","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"complete a prepared deficiency photo upload","request":{"file":{"fileName":"exchanger.jpg","contentType":"image/jpeg","sizeBytes":204800},"pathname":"inspection-deficiencies/11111111-1111-4111-8111-111111111111/bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb/44444444-4444-4444-8444-444444444444.jpg"}}]}},"/inspections/{inspectionId}/deficiencies/{deficiencyId}/photo/approve":{"post":{"operationId":"inspection.upload_deficiency_photo.approve","summary":"Attach a photo to a deficiency — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"deficiencyId","in":"path","required":true,"description":"The deficiencyId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The deficiency after the upload.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"photoCount":{"type":"integer","description":"How many photos the deficiency now carries."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","photoCount","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"complete a prepared deficiency photo upload","request":{"file":{"fileName":"exchanger.jpg","contentType":"image/jpeg","sizeBytes":204800},"pathname":"inspection-deficiencies/11111111-1111-4111-8111-111111111111/bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb/44444444-4444-4444-8444-444444444444.jpg"}}]}},"/inspections/{inspectionId}/deficiencies/{deficiencyId}/photo/prepare-upload":{"post":{"operationId":"inspection.upload_deficiency_photo.prepare-upload","summary":"Prepare a direct upload (step 1 of the two-step contract)","description":"A preparatory step of the governed write. Authorized like any other request; causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"deficiencyId","in":"path","required":true,"description":"The deficiencyId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[]}},"/inspections/{inspectionId}/deficiencies/{deficiencyId}/photo/preview":{"post":{"operationId":"inspection.upload_deficiency_photo.preview","summary":"Attach a photo to a deficiency — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"deficiencyId","in":"path","required":true,"description":"The deficiencyId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"complete a prepared deficiency photo upload","request":{"file":{"fileName":"exchanger.jpg","contentType":"image/jpeg","sizeBytes":204800},"pathname":"inspection-deficiencies/11111111-1111-4111-8111-111111111111/bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb/44444444-4444-4444-8444-444444444444.jpg"}}]}},"/inspections/{inspectionId}/deficiencies/approve":{"post":{"operationId":"inspection.create_deficiency.approve","summary":"File a deficiency from a failed or flagged item — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The deficiency this inspection now carries.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"created":{"type":"boolean","description":"False when this deficiency id already existed and no second row was filed."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspection_deficiencies","x-thermal-examples":[{"name":"file a safety deficiency for a failed item","request":{"deficiencyId":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","equipmentId":"77777777-7777-4777-8777-777777777777","responseId":"99999999-9999-4999-8999-999999999999","title":"Cracked heat exchanger","severity":"safety"}}]}},"/inspections/{inspectionId}/deficiencies/preview":{"post":{"operationId":"inspection.create_deficiency.preview","summary":"File a deficiency from a failed or flagged item — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspection_deficiencies","x-thermal-examples":[{"name":"file a safety deficiency for a failed item","request":{"deficiencyId":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","equipmentId":"77777777-7777-4777-8777-777777777777","responseId":"99999999-9999-4999-8999-999999999999","title":"Cracked heat exchanger","severity":"safety"}}]}},"/inspections/{inspectionId}/red-tag":{"post":{"operationId":"inspection.set_equipment_red_tag","summary":"Red-tag the inspected equipment from a failed safety item","description":"Flips the inspected unit's do-not-operate state and files the matching safety deficiency (and its compliance clock) in ONE transaction. ONE-WAY from this surface: it only ever sets the red tag — clearing one is office/owner-only and has no endpoint here. The checklist item must be in a `fail` state, and the equipment must be the work order's own linked unit. Idempotent two ways, both the writer's own: the equipment update re-applies the same state, and a deficiency already filed for this response is not duplicated — so a duplicate offline-queue delivery produces exactly one red tag and exactly one deficiency. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The red-tagged equipment, and the deficiency the red tag filed.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"deficiencyId":{"type":"string","format":"uuid"},"deficiencyCreated":{"type":"boolean","description":"False when this response already had a deficiency and no second one was filed."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","deficiencyId","deficiencyCreated","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"red-tag a unit with a cracked heat exchanger","request":{"equipmentId":"77777777-7777-4777-8777-777777777777","responseId":"99999999-9999-4999-8999-999999999999","deficiencyId":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","redTagReason":"Cracked heat exchanger — do not operate","title":"Cracked heat exchanger"}}]}},"/inspections/{inspectionId}/red-tag/approve":{"post":{"operationId":"inspection.set_equipment_red_tag.approve","summary":"Red-tag the inspected equipment from a failed safety item — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The red-tagged equipment, and the deficiency the red tag filed.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"deficiencyId":{"type":"string","format":"uuid"},"deficiencyCreated":{"type":"boolean","description":"False when this response already had a deficiency and no second one was filed."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","deficiencyId","deficiencyCreated","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"red-tag a unit with a cracked heat exchanger","request":{"equipmentId":"77777777-7777-4777-8777-777777777777","responseId":"99999999-9999-4999-8999-999999999999","deficiencyId":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","redTagReason":"Cracked heat exchanger — do not operate","title":"Cracked heat exchanger"}}]}},"/inspections/{inspectionId}/red-tag/preview":{"post":{"operationId":"inspection.set_equipment_red_tag.preview","summary":"Red-tag the inspected equipment from a failed safety item — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"red-tag a unit with a cracked heat exchanger","request":{"equipmentId":"77777777-7777-4777-8777-777777777777","responseId":"99999999-9999-4999-8999-999999999999","deficiencyId":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","redTagReason":"Cracked heat exchanger — do not operate","title":"Cracked heat exchanger"}}]}},"/inspections/{inspectionId}/responses/{responseId}":{"post":{"operationId":"inspection.update_response","summary":"Save one checklist item's captured value","description":"Persists one checklist item's value. A PARTIAL PATCH: a field left out is untouched, and a field sent as `null` is cleared — so sending only `note` never clobbers a saved reading. Re-sending the same values is naturally a no-op, and a measurement bound to a reading type also appends one `equipment_readings` row (append-only by design: a correction is a new row). The inspection must still be in progress; a closed one is refused. The work order is resolved from the inspection server-side, never taken from the request. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The checklist item after the write.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"inspectionId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","inspectionId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspection_responses","x-thermal-examples":[{"name":"record a failed safety item with a note","request":{"passState":"fail","note":"Cracked heat exchanger"}}]}},"/inspections/{inspectionId}/responses/{responseId}/approve":{"post":{"operationId":"inspection.update_response.approve","summary":"Save one checklist item's captured value — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The checklist item after the write.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"inspectionId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","inspectionId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspection_responses","x-thermal-examples":[{"name":"record a failed safety item with a note","request":{"passState":"fail","note":"Cracked heat exchanger"}}]}},"/inspections/{inspectionId}/responses/{responseId}/photo":{"post":{"operationId":"inspection.upload_response_photo","summary":"Attach a photo (or per-item signature) to a checklist item","description":"THE TWO-STEP DIRECT-UPLOAD CONTRACT (issue 3556's, reused unchanged). STEP 1 — PREPARE: `POST <this path>/prepare-upload` with the file's DECLARATION only (`file: { fileName, contentType, sizeBytes }`), never its bytes. The reply's `target` is an exact-path, single-file, size-capped storage capability whose `pathname` is server-chosen and tenancy-bound, so a caller cannot aim an upload at another tenant's prefix. This step writes nothing. STEP 2 — PUT: the client PUTs the bytes straight to the storage host at `target.pathname` using `target.clientToken`; no Thermal endpoint is involved and bytes never cross the Platform API. A 403 from storage means the capability expired — call prepare again and PUT again. STEP 3 — COMPLETE, FOLDED INTO THIS WRITE: send the SAME `file` declaration plus the `pathname` step 1 returned. The server re-verifies server-side before any row is written (tenancy-bound prefix, the object exists, content type, byte length and magic-number signature all match the declaration); a failed verification writes nothing and deletes the upload. Retrying the TERMINAL write with the same `Idempotency-Key` replays the stored result rather than storing a second artifact. The prepare step is deliberately NOT idempotent: it writes nothing, so calling it twice simply mints two uuid-keyed pathnames and only the one presented on the terminal write is ever verified or attached. A `photo`-fieldType response takes that path. A `signature`-fieldType response does NOT: its ink is private-custody (issue 1590) and must never be staged in the public store this capability writes to, so it is sent as `inlineImageBase64` on this call instead, under the same 2 MB cap, and the writer puts it straight into the private store. Sending `pathname` for a signature response, or inline bytes for a photo response, is refused. The inspection must still be in progress. The stored artifact is one `work_order_attachments` row plus the response's own value; a duplicate delivery under the same `Idempotency-Key` stores exactly one. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The checklist item after the upload.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"inspectionId":{"type":"string","format":"uuid"},"fieldType":{"type":"string","enum":["photo","signature"]},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","inspectionId","fieldType","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"complete a prepared photo upload","request":{"file":{"fileName":"panel.jpg","contentType":"image/jpeg","sizeBytes":182311},"pathname":"inspection-responses/11111111-1111-4111-8111-111111111111/66666666-6666-4666-8666-666666666666/99999999-9999-4999-8999-999999999999/44444444-4444-4444-8444-444444444444.jpg"}}]}},"/inspections/{inspectionId}/responses/{responseId}/photo/approve":{"post":{"operationId":"inspection.upload_response_photo.approve","summary":"Attach a photo (or per-item signature) to a checklist item — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The checklist item after the upload.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"inspectionId":{"type":"string","format":"uuid"},"fieldType":{"type":"string","enum":["photo","signature"]},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","inspectionId","fieldType","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"complete a prepared photo upload","request":{"file":{"fileName":"panel.jpg","contentType":"image/jpeg","sizeBytes":182311},"pathname":"inspection-responses/11111111-1111-4111-8111-111111111111/66666666-6666-4666-8666-666666666666/99999999-9999-4999-8999-999999999999/44444444-4444-4444-8444-444444444444.jpg"}}]}},"/inspections/{inspectionId}/responses/{responseId}/photo/prepare-upload":{"post":{"operationId":"inspection.upload_response_photo.prepare-upload","summary":"Prepare a direct upload (step 1 of the two-step contract)","description":"A preparatory step of the governed write. Authorized like any other request; causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[]}},"/inspections/{inspectionId}/responses/{responseId}/photo/preview":{"post":{"operationId":"inspection.upload_response_photo.preview","summary":"Attach a photo (or per-item signature) to a checklist item — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"complete a prepared photo upload","request":{"file":{"fileName":"panel.jpg","contentType":"image/jpeg","sizeBytes":182311},"pathname":"inspection-responses/11111111-1111-4111-8111-111111111111/66666666-6666-4666-8666-666666666666/99999999-9999-4999-8999-999999999999/44444444-4444-4444-8444-444444444444.jpg"}}]}},"/inspections/{inspectionId}/responses/{responseId}/preview":{"post":{"operationId":"inspection.update_response.preview","summary":"Save one checklist item's captured value — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"responseId","in":"path","required":true,"description":"The responseId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspection_responses","x-thermal-examples":[{"name":"record a failed safety item with a note","request":{"passState":"fail","note":"Cracked heat exchanger"}}]}},"/inspections/{inspectionId}/share-token":{"post":{"operationId":"inspection.ensure_share_token","summary":"Ensure the inspection has a customer share token","description":"Mints the inspection's customer-facing share token if it does not have one, and returns the token either way. This is the SAME action the office detail page's share-link button calls (`(app)/inspections/actions.ts`'s `ensureInspectionShareToken`), not a tech-only copy: its dual gate — office roles pass the area check, a technician must hold a live appointment on the inspection's own work order — is therefore the one enforced here too. Idempotent by construction: an inspection that already has a token keeps it, and `minted` says which happened. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection's share token.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"shareToken":{"type":"string","description":"The token the customer-facing link carries."},"minted":{"type":"boolean","description":"True when this call created the token."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","shareToken","minted","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"share a completed inspection with the customer","request":{}}]}},"/inspections/{inspectionId}/share-token/approve":{"post":{"operationId":"inspection.ensure_share_token.approve","summary":"Ensure the inspection has a customer share token — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection's share token.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"shareToken":{"type":"string","description":"The token the customer-facing link carries."},"minted":{"type":"boolean","description":"True when this call created the token."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","shareToken","minted","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"share a completed inspection with the customer","request":{}}]}},"/inspections/{inspectionId}/share-token/preview":{"post":{"operationId":"inspection.ensure_share_token.preview","summary":"Ensure the inspection has a customer share token — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"share a completed inspection with the customer","request":{}}]}},"/inspections/{inspectionId}/signature":{"post":{"operationId":"inspection.save_signature","summary":"Capture the inspection's sign-off signature","description":"The header-level sign-off that `inspection.complete` gates on. The ink is PRIVATE-CUSTODY (issue 1590): it is written to the private store with a sha256 custody hash, never to a public URL, and it therefore does NOT use the two-step direct-upload contract, whose capability is public — the bytes travel inline as base64 under the same 2 MB image cap. A re-capture SUPERSEDES the prior signature and records the supersession as an evidence event rather than destroying the prior ink. The inspection must still be in progress. A duplicate delivery under the same `Idempotency-Key` stores exactly one signature. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection after the signature was captured.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"superseded":{"type":"boolean","description":"True when a signature was already on file and this capture superseded it."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","superseded","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"capture the customer's sign-off","request":{"file":{"fileName":"signature.png","contentType":"image/png","sizeBytes":9214},"inlineImageBase64":"iVBORw0KGgo…"}}]}},"/inspections/{inspectionId}/signature/approve":{"post":{"operationId":"inspection.save_signature.approve","summary":"Capture the inspection's sign-off signature — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection after the signature was captured.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"superseded":{"type":"boolean","description":"True when a signature was already on file and this capture superseded it."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","superseded","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"capture the customer's sign-off","request":{"file":{"fileName":"signature.png","contentType":"image/png","sizeBytes":9214},"inlineImageBase64":"iVBORw0KGgo…"}}]}},"/inspections/{inspectionId}/signature/preview":{"post":{"operationId":"inspection.save_signature.preview","summary":"Capture the inspection's sign-off signature — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"inspectionId","in":"path","required":true,"description":"The inspectionId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"capture the customer's sign-off","request":{"file":{"fileName":"signature.png","contentType":"image/png","sizeBytes":9214},"inlineImageBase64":"iVBORw0KGgo…"}}]}},"/intake/calls":{"post":{"operationId":"intake.open_call","summary":"Open a call and record its drafted work order","description":"Records a phone call and the work order it proposes as one `call_intake_sessions` row in `awaiting_decision`. Creates NO work order, runs no model and sends nothing. Repeating with the same `runId` refreshes the same row; a call that has already been converted, discarded or parked for a callback is never reopened. A customer or site outside this organization — or a site that is not this customer's — is refused before anything is written. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The call awaiting a decision, and the normalized draft stored against it. No work order exists yet.","properties":{"id":{"type":"string","format":"uuid","description":"The call's run id."},"rowVersion":{"type":"null","description":"`call_intake_sessions` carries no row version; the run id is the guard."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"runId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["awaiting_decision"]},"customerId":{"type":"string","format":"uuid"},"serviceSiteId":{"type":"string","format":"uuid"},"draft":{"type":"object","description":"The drafted work order this call proposes, as the server normalized and stored it.","properties":{"jobType":{"type":"string","enum":["repair","maintenance","install","quote","dispatch_emergency"]},"priority":{"type":"string","enum":["emergency","urgent","routine"]},"summary":{"type":"string"},"notes":{"type":"string"}},"required":["jobType","priority","summary","notes"],"additionalProperties":false},"draftHash":{"type":"string","description":"sha256 over the stored draft — what a later confirm compares to detect an override."}},"required":["id","rowVersion","replayed","runId","status","customerId","serviceSiteId","draft","draftHash"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"call_intake_sessions","x-thermal-examples":[{"name":"open a call with a drafted repair","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","draft":{"jobType":"repair","priority":"urgent","summary":"No cooling on the second-floor RTU","notes":"Caller says it has been blowing warm since this morning."}}}]}},"/intake/calls/approve":{"post":{"operationId":"intake.open_call.approve","summary":"Open a call and record its drafted work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The call awaiting a decision, and the normalized draft stored against it. No work order exists yet.","properties":{"id":{"type":"string","format":"uuid","description":"The call's run id."},"rowVersion":{"type":"null","description":"`call_intake_sessions` carries no row version; the run id is the guard."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"runId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["awaiting_decision"]},"customerId":{"type":"string","format":"uuid"},"serviceSiteId":{"type":"string","format":"uuid"},"draft":{"type":"object","description":"The drafted work order this call proposes, as the server normalized and stored it.","properties":{"jobType":{"type":"string","enum":["repair","maintenance","install","quote","dispatch_emergency"]},"priority":{"type":"string","enum":["emergency","urgent","routine"]},"summary":{"type":"string"},"notes":{"type":"string"}},"required":["jobType","priority","summary","notes"],"additionalProperties":false},"draftHash":{"type":"string","description":"sha256 over the stored draft — what a later confirm compares to detect an override."}},"required":["id","rowVersion","replayed","runId","status","customerId","serviceSiteId","draft","draftHash"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"call_intake_sessions","x-thermal-examples":[{"name":"open a call with a drafted repair","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","draft":{"jobType":"repair","priority":"urgent","summary":"No cooling on the second-floor RTU","notes":"Caller says it has been blowing warm since this morning."}}}]}},"/intake/calls/confirm":{"post":{"operationId":"intake.confirm","summary":"Confirm a call's draft and create the work order","description":"An office user in the dispatch area converts the call's STORED draft into a work order, in one transaction that also marks the call converted — neither lands without the other. Refused for every principal that is not an office user: an API key, an OAuth client, a webhook integration, any delegated credential, and a technician. A replay returns the job the first confirm made and creates no second one; a call that is discarded, parked for a callback or missing is refused, as is a submitted subject that is not the one this call was taken for. Pass the `draftHash` `intake.open_call` returned to bind the confirm to the draft that was actually read: if another refresh has moved it since, the confirm is refused rather than converting a proposal nobody approved. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order this call became. A replay names the job the FIRST confirm made and creates nothing.","properties":{"id":{"type":"string","format":"uuid","description":"The work order's id."},"rowVersion":{"type":"null"},"replayed":{"type":"boolean"},"workOrderId":{"type":"string","format":"uuid"},"number":{"type":"integer","nullable":true,"description":"The job number. Null on a replay, which does not re-read the job it names."},"draftOverridden":{"type":"boolean","nullable":true,"description":"True when the confirming office user changed the stored draft. Null on a replay, which made no such decision."},"callAlreadyConverted":{"type":"boolean","description":"True when this call had already been converted and the named work order is the one the FIRST confirm made. Distinct from `replayed`, which reports an idempotency-key replay: two operators confirming one call present two different keys."}},"required":["id","rowVersion","replayed","workOrderId","number","draftOverridden","callAlreadyConverted"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"confirm the stored draft unchanged","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222"}},{"name":"confirm after raising the priority","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","override":{"priority":"emergency"}}},{"name":"confirm only if the draft has not moved since it was read","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","expectedDraftHash":"3b8c1f0e5d2a47b69c8e1f0a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e"}}]}},"/intake/calls/confirm/approve":{"post":{"operationId":"intake.confirm.approve","summary":"Confirm a call's draft and create the work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order this call became. A replay names the job the FIRST confirm made and creates nothing.","properties":{"id":{"type":"string","format":"uuid","description":"The work order's id."},"rowVersion":{"type":"null"},"replayed":{"type":"boolean"},"workOrderId":{"type":"string","format":"uuid"},"number":{"type":"integer","nullable":true,"description":"The job number. Null on a replay, which does not re-read the job it names."},"draftOverridden":{"type":"boolean","nullable":true,"description":"True when the confirming office user changed the stored draft. Null on a replay, which made no such decision."},"callAlreadyConverted":{"type":"boolean","description":"True when this call had already been converted and the named work order is the one the FIRST confirm made. Distinct from `replayed`, which reports an idempotency-key replay: two operators confirming one call present two different keys."}},"required":["id","rowVersion","replayed","workOrderId","number","draftOverridden","callAlreadyConverted"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"confirm the stored draft unchanged","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222"}},{"name":"confirm after raising the priority","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","override":{"priority":"emergency"}}},{"name":"confirm only if the draft has not moved since it was read","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","expectedDraftHash":"3b8c1f0e5d2a47b69c8e1f0a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e"}}]}},"/intake/calls/confirm/preview":{"post":{"operationId":"intake.confirm.preview","summary":"Confirm a call's draft and create the work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"confirm the stored draft unchanged","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222"}},{"name":"confirm after raising the priority","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","override":{"priority":"emergency"}}},{"name":"confirm only if the draft has not moved since it was read","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","expectedDraftHash":"3b8c1f0e5d2a47b69c8e1f0a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e"}}]}},"/intake/calls/preview":{"post":{"operationId":"intake.open_call.preview","summary":"Open a call and record its drafted work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"call_intake_sessions","x-thermal-examples":[{"name":"open a call with a drafted repair","request":{"runId":"9f0a1b2c-3d4e-4f50-8a6b-7c8d9e0f1a2b","customerId":"11111111-1111-4111-8111-111111111111","serviceSiteId":"22222222-2222-4222-8222-222222222222","draft":{"jobType":"repair","priority":"urgent","summary":"No cooling on the second-floor RTU","notes":"Caller says it has been blowing warm since this morning."}}}]}},"/invoices/{id}/reminders":{"post":{"operationId":"invoice.send_reminder","summary":"Re-notify the customer about an unpaid invoice","description":"Records a `reminder_sent` activity row and sends the AR-collections reminder for a `sent` or `partial` invoice with a balance still due — the same eligibility the `invoice.send_reminder` registry action applies, re-checked at APPLY time so an invoice paid between preview and apply is an honest `sent: false` no-op rather than a stale reminder. Irreversible (the customer receives it) and therefore classed `high`: preview first, then apply with a `--reason`. The invoice row itself is never updated, so no row version is bound or returned. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"Whether a reminder was actually sent for this invoice.","properties":{"id":{"type":"string","format":"uuid"},"sent":{"type":"boolean","description":"False when the invoice was no longer reminder-worthy (paid, void, draft, or nothing due) — an honest no-op, not a failure."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","sent","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"invoices","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"remind on an overdue invoice","request":{"id":"9f1f0a4c-4e0e-4d55-9a1a-1f0d2b3c4d5e"}}]}},"/invoices/{id}/reminders/approve":{"post":{"operationId":"invoice.send_reminder.approve","summary":"Re-notify the customer about an unpaid invoice — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"Whether a reminder was actually sent for this invoice.","properties":{"id":{"type":"string","format":"uuid"},"sent":{"type":"boolean","description":"False when the invoice was no longer reminder-worthy (paid, void, draft, or nothing due) — an honest no-op, not a failure."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","sent","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"invoices","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"remind on an overdue invoice","request":{"id":"9f1f0a4c-4e0e-4d55-9a1a-1f0d2b3c4d5e"}}]}},"/invoices/{id}/reminders/preview":{"post":{"operationId":"invoice.send_reminder.preview","summary":"Re-notify the customer about an unpaid invoice — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"invoices","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"remind on an overdue invoice","request":{"id":"9f1f0a4c-4e0e-4d55-9a1a-1f0d2b3c4d5e"}}]}},"/invoices/{id}/send":{"post":{"operationId":"invoice.send","summary":"Advance a draft invoice to sent","description":"Runs `markInvoiceSentCore` — the same draft→sent transition the office Invoices screen and the `invoice.send` registry action use, including the release gate that refuses an invoice in prebill review, a vendor-portal submission awaiting review, and a draft the org's prebill policy says needs approval. Irreversible and classed `high`, so it is NEVER one-phase: `POST /invoices/{id}/send/preview` mints a proposal bound to the invoice's current row version, and `POST /invoices/{id}/send` applies that proposal with a `--reason`. An invoice that is not a visible draft in the caller's org and branch scope is reported as `404`, never as `403`. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The invoice's status transition, and the row version the send produced.","properties":{"id":{"type":"string","format":"uuid"},"from":{"type":"string","description":"The status the invoice held before the send."},"to":{"type":"string","description":"The status it holds after it."},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","from","to","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"invoices","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"send a draft invoice","request":{"id":"9f1f0a4c-4e0e-4d55-9a1a-1f0d2b3c4d5e"}}]}},"/invoices/{id}/send/approve":{"post":{"operationId":"invoice.send.approve","summary":"Advance a draft invoice to sent — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The invoice's status transition, and the row version the send produced.","properties":{"id":{"type":"string","format":"uuid"},"from":{"type":"string","description":"The status the invoice held before the send."},"to":{"type":"string","description":"The status it holds after it."},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","from","to","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"invoices","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"send a draft invoice","request":{"id":"9f1f0a4c-4e0e-4d55-9a1a-1f0d2b3c4d5e"}}]}},"/invoices/{id}/send/preview":{"post":{"operationId":"invoice.send.preview","summary":"Advance a draft invoice to sent — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"irreversible","x-thermal-area":"invoices","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"send a draft invoice","request":{"id":"9f1f0a4c-4e0e-4d55-9a1a-1f0d2b3c4d5e"}}]}},"/lead-captures/{leadCaptureId}/disposition":{"post":{"operationId":"lead_capture.apply_suggestion","summary":"Apply an approved inquiry disposition","description":"Moves an inbound inquiry to `matched`, `disqualified` or `spam` through `dispositionLeadCapture` — the one door in `packages/core/src/lead-capture-core.ts`, never a direct `disposition` update. `from` is the state the suggestion was staged against and is the operation's own compare-and-set: a capture somebody else already triaged is refused rather than overwritten. Matching requires an account, and a move to `disqualified` requires a reason; the core enforces both. Classed `medium` — the same core's reverse moves undo it — and the write is confined to `lead_captures`: opening an account and drafting a quote are hand-offs this operation can never reach. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"leadCaptureId","in":"path","required":true,"description":"The leadCaptureId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inquiry's disposition after the move.","properties":{"id":{"type":"string","format":"uuid","description":"The `lead_captures` row id."},"from":{"type":"string"},"to":{"type":"string"},"changed":{"type":"boolean","description":"False when the capture already held the target disposition — a safe retry, not a second move."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: `lead_captures` is not a spine table and carries no `row_version`; `from` is this operation's compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","from","to","changed","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"customers","x-thermal-target-table":"lead_captures","x-thermal-examples":[{"name":"match an inquiry to an account","request":{"leadCaptureId":"2c4e6a80-1357-4bd9-8e02-46a8c0e24680","from":"captured","to":"matched","customerId":"7a1b2c3d-4e5f-4061-8273-8495a6b7c8d9"}}]}},"/lead-captures/{leadCaptureId}/disposition/approve":{"post":{"operationId":"lead_capture.apply_suggestion.approve","summary":"Apply an approved inquiry disposition — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"leadCaptureId","in":"path","required":true,"description":"The leadCaptureId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inquiry's disposition after the move.","properties":{"id":{"type":"string","format":"uuid","description":"The `lead_captures` row id."},"from":{"type":"string"},"to":{"type":"string"},"changed":{"type":"boolean","description":"False when the capture already held the target disposition — a safe retry, not a second move."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: `lead_captures` is not a spine table and carries no `row_version`; `from` is this operation's compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","from","to","changed","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"customers","x-thermal-target-table":"lead_captures","x-thermal-examples":[{"name":"match an inquiry to an account","request":{"leadCaptureId":"2c4e6a80-1357-4bd9-8e02-46a8c0e24680","from":"captured","to":"matched","customerId":"7a1b2c3d-4e5f-4061-8273-8495a6b7c8d9"}}]}},"/lead-captures/{leadCaptureId}/disposition/preview":{"post":{"operationId":"lead_capture.apply_suggestion.preview","summary":"Apply an approved inquiry disposition — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"leadCaptureId","in":"path","required":true,"description":"The leadCaptureId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"customers","x-thermal-target-table":"lead_captures","x-thermal-examples":[{"name":"match an inquiry to an account","request":{"leadCaptureId":"2c4e6a80-1357-4bd9-8e02-46a8c0e24680","from":"captured","to":"matched","customerId":"7a1b2c3d-4e5f-4061-8273-8495a6b7c8d9"}}]}},"/legacy/work-orders/{id}":{"get":{"operationId":"legacy.work_order.get","summary":"Get one work order (legacy flattened shape)","description":"The pre-contract response shape existing `/api/v1/work-orders/{id}` consumers read: the same record as `work_order.get` plus `scheduledStart`, `scheduledEnd` and `assignedUser` hoisted from the earliest non-cancelled appointment. Deprecated in favour of `work_order.get`; the old behaviour keeps working through its stated window (openapi-allowlist-and-breaking-change-policy.md § Deprecation and sunset).","deprecated":true,"security":[{"clerkSessionJwt":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The legacy flattened work-order shape.","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","description":"The spine row's current version (`_shared.ts`'s server-owned `row_version`, guarded by migration 0385's trigger). A client presents this back as `expectedRowVersion` on a governed write; a stale value is a 409, never a silent last-write-wins.","minimum":1},"number":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"jobType":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"customer":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"serviceSite":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","nullable":true},"addressLine1":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"zip":{"type":"string","nullable":true}},"required":["id","label","addressLine1","city","state","zip"],"additionalProperties":false},"equipment":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","nullable":true},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true}},"required":["id","type","make","model","serial"],"additionalProperties":false},"appointments":{"type":"array","items":{"type":"object","description":"One visit on a work order. A work order can have several (ADR-0005), so this array never lies about a single-visit shape.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"assignedUserId":{"type":"string","format":"uuid","nullable":true}},"required":["id","status","scheduledStart","scheduledEnd","assignedUserId"],"additionalProperties":false}},"updatedAt":{"type":"string","format":"date-time"},"scheduledStart":{"type":"string","format":"date-time","nullable":true},"scheduledEnd":{"type":"string","format":"date-time","nullable":true},"assignedUser":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","firstName","lastName"],"additionalProperties":false}},"required":["id","rowVersion","number","status","priority","jobType","summary","completedAt","customer","serviceSite","equipment","appointments","updatedAt","scheduledStart","scheduledEnd","assignedUser"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":true,"x-thermal-side-effect":"read","x-thermal-area":"dispatch","x-thermal-deprecation":{"since":"2026-09-19","replacement":"work_order.get"},"x-thermal-examples":[{"name":"legacy-detail","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/me/branch-scope":{"post":{"operationId":"user.set_branch_scope_override","summary":"Set the signed-in user's own branch-scope override","description":"Sets or clears the caller's own `users.branch_scope_override`. Self-scoped by construction — the row written is the caller's own staff row, and no other user's id can be named. Direct/online-only. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's own branch-scope override after the write.","properties":{"id":{"type":"string","format":"uuid","description":"The acting user's staff user id."},"scope":{"type":"string","enum":["all","home"],"nullable":true,"description":"The override now stored on the caller's own row; null means the role default."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","scope","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"users","x-thermal-examples":[{"name":"see every branch","request":{"scope":"all"}},{"name":"back to the role default","request":{"scope":null}}]}},"/me/branch-scope/approve":{"post":{"operationId":"user.set_branch_scope_override.approve","summary":"Set the signed-in user's own branch-scope override — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's own branch-scope override after the write.","properties":{"id":{"type":"string","format":"uuid","description":"The acting user's staff user id."},"scope":{"type":"string","enum":["all","home"],"nullable":true,"description":"The override now stored on the caller's own row; null means the role default."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","scope","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"users","x-thermal-examples":[{"name":"see every branch","request":{"scope":"all"}},{"name":"back to the role default","request":{"scope":null}}]}},"/me/branch-scope/preview":{"post":{"operationId":"user.set_branch_scope_override.preview","summary":"Set the signed-in user's own branch-scope override — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"users","x-thermal-examples":[{"name":"see every branch","request":{"scope":"all"}},{"name":"back to the role default","request":{"scope":null}}]}},"/me/push-tokens":{"post":{"operationId":"registerPushToken","summary":"Register this device's push token for the signed-in user","description":"Stores the device's push token for the signed-in user so assigned visits can be pushed to it. One active token per device: re-registering the same device updates it in place, and registering a device that belongs to another user revokes that user's token first. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's active push token for this device after the write.","properties":{"id":{"type":"string","format":"uuid","description":"The `device_push_tokens` row now active for this device."},"deviceId":{"type":"string"},"platform":{"type":"string","enum":["ios","android"]},"created":{"type":"boolean","description":"False when the caller already had an active row for this device and this call updated it in place."},"replacedOtherUser":{"type":"boolean","description":"True when the device was registered to a different user and that registration was revoked by this call (a shared device changing hands)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: `device_push_tokens` carries no server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","deviceId","platform","created","replacedOtherUser","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile","x-thermal-target-table":"device_push_tokens","x-thermal-examples":[{"name":"register an iPhone","request":{"token":"ExponentPushToken[example-0000]","platform":"ios","deviceId":"device-example-1"}}]}},"/me/push-tokens/approve":{"post":{"operationId":"registerPushToken.approve","summary":"Register this device's push token for the signed-in user — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's active push token for this device after the write.","properties":{"id":{"type":"string","format":"uuid","description":"The `device_push_tokens` row now active for this device."},"deviceId":{"type":"string"},"platform":{"type":"string","enum":["ios","android"]},"created":{"type":"boolean","description":"False when the caller already had an active row for this device and this call updated it in place."},"replacedOtherUser":{"type":"boolean","description":"True when the device was registered to a different user and that registration was revoked by this call (a shared device changing hands)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: `device_push_tokens` carries no server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","deviceId","platform","created","replacedOtherUser","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile","x-thermal-target-table":"device_push_tokens","x-thermal-examples":[{"name":"register an iPhone","request":{"token":"ExponentPushToken[example-0000]","platform":"ios","deviceId":"device-example-1"}}]}},"/me/push-tokens/preview":{"post":{"operationId":"registerPushToken.preview","summary":"Register this device's push token for the signed-in user — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile","x-thermal-target-table":"device_push_tokens","x-thermal-examples":[{"name":"register an iPhone","request":{"token":"ExponentPushToken[example-0000]","platform":"ios","deviceId":"device-example-1"}}]}},"/me/push-tokens/revoke":{"post":{"operationId":"revokePushToken","summary":"Revoke the signed-in user's push token for a device","description":"Revokes the signed-in user's active push token for the named device, so no further pushes are sent to it. Only the caller's own token in the caller's own organization can be revoked; anything else answers not found. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's push token for this device, now revoked.","properties":{"id":{"type":"string","format":"uuid","description":"The `device_push_tokens` row this call revoked."},"deviceId":{"type":"string"},"revokedAt":{"type":"string","format":"date-time"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: `device_push_tokens` carries no server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","deviceId","revokedAt","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile","x-thermal-target-table":"device_push_tokens","x-thermal-examples":[{"name":"sign out on this device","request":{"deviceId":"device-example-1"}}]}},"/me/push-tokens/revoke/approve":{"post":{"operationId":"revokePushToken.approve","summary":"Revoke the signed-in user's push token for a device — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's push token for this device, now revoked.","properties":{"id":{"type":"string","format":"uuid","description":"The `device_push_tokens` row this call revoked."},"deviceId":{"type":"string"},"revokedAt":{"type":"string","format":"date-time"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: `device_push_tokens` carries no server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","deviceId","revokedAt","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile","x-thermal-target-table":"device_push_tokens","x-thermal-examples":[{"name":"sign out on this device","request":{"deviceId":"device-example-1"}}]}},"/me/push-tokens/revoke/preview":{"post":{"operationId":"revokePushToken.preview","summary":"Revoke the signed-in user's push token for a device — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile","x-thermal-target-table":"device_push_tokens","x-thermal-examples":[{"name":"sign out on this device","request":{"deviceId":"device-example-1"}}]}},"/operations/agreements":{"get":{"operationId":"operations.agreements","summary":"Read operational agreements","description":"Read-only, organization and branch scoped agreements projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","status","expiresOn","revenueCents","totalCostCents","customerId"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","nullable":true},"expiresOn":{"type":"string","nullable":true},"revenueCents":{"type":"integer","nullable":true},"totalCostCents":{"type":"integer","nullable":true},"customerId":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"agreements","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/customers":{"get":{"operationId":"operations.customers","summary":"Read operational customers","description":"Read-only, organization and branch scoped customers projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"customers","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/equipment":{"get":{"operationId":"operations.equipment","summary":"Read operational equipment","description":"Read-only, organization and branch scoped equipment projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","installYear","isRedTagged","serviceSiteId"],"properties":{"id":{"type":"string","format":"uuid"},"installYear":{"type":"integer","nullable":true},"isRedTagged":{"type":"boolean","nullable":true},"serviceSiteId":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"equipment","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/invoices":{"get":{"operationId":"operations.invoices","summary":"Read operational invoices","description":"Read-only, organization and branch scoped invoices projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","status","dueOn","balanceDueCents","customerId","currency"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","nullable":true},"dueOn":{"type":"string","nullable":true},"balanceDueCents":{"type":"integer","nullable":true},"customerId":{"type":"string","nullable":true},"currency":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"invoices","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/payments":{"get":{"operationId":"operations.payments","summary":"Read operational payments","description":"Read-only, organization and branch scoped payments projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","invoiceId","amountCents","status","receivedAt","currency"],"properties":{"id":{"type":"string","format":"uuid"},"invoiceId":{"type":"string","nullable":true},"amountCents":{"type":"integer","nullable":true},"status":{"type":"string","nullable":true},"receivedAt":{"type":"string","nullable":true},"currency":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"invoices","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/pm-schedules":{"get":{"operationId":"operations.pm_schedules","summary":"Read operational pm schedules","description":"Read-only, organization and branch scoped pm schedules projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","active","nextDueOn","serviceAgreementId","visitType"],"properties":{"id":{"type":"string","format":"uuid"},"active":{"type":"boolean","nullable":true},"nextDueOn":{"type":"string","nullable":true},"serviceAgreementId":{"type":"string","nullable":true},"visitType":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"agreements","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/proposals":{"get":{"operationId":"operations.proposals","summary":"Read operational proposals","description":"Read-only, organization and branch scoped proposals projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","status","sentAt","customerId"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","nullable":true},"sentAt":{"type":"string","nullable":true},"customerId":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"proposals","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/purchase-orders":{"get":{"operationId":"operations.purchase_orders","summary":"Read operational purchase orders","description":"Read-only, organization and branch scoped purchase orders projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","status","expectedDate","requiredByDate","workOrderId"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","nullable":true},"expectedDate":{"type":"string","nullable":true},"requiredByDate":{"type":"string","nullable":true},"workOrderId":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"purchasing","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/service-sites":{"get":{"operationId":"operations.service_sites","summary":"Read operational service sites","description":"Read-only, organization and branch scoped service sites projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","customerId","label","addressLine1"],"properties":{"id":{"type":"string","format":"uuid"},"customerId":{"type":"string","nullable":true},"label":{"type":"string","nullable":true},"addressLine1":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"customers","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/operations/work-orders":{"get":{"operationId":"operations.work_orders","summary":"Read operational work orders","description":"Read-only, organization and branch scoped work orders projection for operational prompts. Follow nextCursor to completion before claiming no findings. Policy is normalized organization settings; asOf is the server read timestamp.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"description":"Last returned record id; keyset continuation.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size; defaults to 100.","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["items","nextCursor","limit","asOf","today","policy"],"properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","status","completedAt","hasInvoice","visits","siteCustomerId","billToCustomerId","agreementPayerId"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","nullable":true},"completedAt":{"type":"string","nullable":true},"hasInvoice":{"type":"boolean","nullable":true},"visits":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","status","scheduledStart","assignedUserId","subcontractorId"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"scheduledStart":{"type":"string"},"assignedUserId":{"type":"string","nullable":true},"subcontractorId":{"type":"string","nullable":true}}}},"siteCustomerId":{"type":"string","nullable":true},"billToCustomerId":{"type":"string","nullable":true},"agreementPayerId":{"type":"string","nullable":true}}}},"nextCursor":{"type":"string","format":"uuid","nullable":true},"limit":{"type":"integer"},"asOf":{"type":"string","format":"date-time"},"today":{"type":"string","format":"date"},"policy":{"type":"object","additionalProperties":false,"required":["pmOverdueDays","unbilledDays","dispatchLateMinutes","quoteNoResponseDays","collectionOverdueDays","collectionAgeingBucketDays","equipmentRiskAgeYears","purchasingOverdueDays","minimumAgreementMarginBps","renewalHorizonDays"],"properties":{"pmOverdueDays":{"type":"integer"},"unbilledDays":{"type":"integer"},"dispatchLateMinutes":{"type":"integer"},"quoteNoResponseDays":{"type":"integer"},"collectionOverdueDays":{"type":"integer"},"collectionAgeingBucketDays":{"type":"integer"},"equipmentRiskAgeYears":{"type":"integer"},"purchasingOverdueDays":{"type":"integer"},"minimumAgreementMarginBps":{"type":"integer"},"renewalHorizonDays":{"type":"integer"}}}}}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"work-orders","x-thermal-pagination":{"style":"cursor","defaultPageSize":100,"maxPageSize":100,"sortKeys":["id"]},"x-thermal-examples":[{"name":"first-page","request":{"limit":100}}]}},"/profile":{"get":{"operationId":"technician.profile","summary":"Get the calling technician's own profile summary","description":"The calling technician's own profile: identity and role, today's jobs-done / first-time-fix / booked-today stats, year-to-date commission (present only when the org pays commission), compliance credentials, today's clock state and clock-in phase options, today's closed time entries, the caller's own field purchases, their van link-out with its open low-stock count, and their own monthly scorecard trend. Own-record only; there is no way to name another technician.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The calling technician's own profile summary.","properties":{"technician":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"role":{"type":"string"}},"required":["id","firstName","lastName","role"],"additionalProperties":false},"voiceAssistReleased":{"type":"boolean"},"voiceAssist":{"type":"string","enum":["off","suggest","auto"]},"certLabel":{"type":"string","nullable":true},"today":{"type":"object","properties":{"jobsDone":{"type":"integer"},"firstTimeFixPct":{"type":"integer","nullable":true},"bookedTodayCents":{"type":"integer"}},"required":["jobsDone","firstTimeFixPct","bookedTodayCents"],"additionalProperties":false},"ytd":{"type":"object","properties":{"paysCommission":{"type":"boolean"},"earnedCents":{"type":"integer"}},"required":["paysCommission","earnedCents"],"additionalProperties":false},"credentials":{"type":"array","items":{"type":"object","description":"One compliance credential belonging to the calling technician (techCredentials, own-data-only).","properties":{"id":{"type":"string","format":"uuid"},"credType":{"type":"string"},"credName":{"type":"string","nullable":true},"expiresOn":{"type":"string","format":"date-time","nullable":true},"isRevoked":{"type":"boolean"},"status":{"type":"string","enum":["active","expiring_soon","expired","revoked"],"description":"classifyCredential's read-time status."}},"required":["id","credType","credName","expiresOn","isRevoked","status"],"additionalProperties":false}},"fieldApp":{"type":"object","description":"The organization's native field-app options the phone acts on.","properties":{"autoArrive":{"type":"boolean","description":"When true, the app marks the caller's en-route visit arrived after two consecutive accurate position fixes near the site, while open."}},"required":["autoArrive"],"additionalProperties":false},"branchScope":{"type":"object","description":"The caller's live branch-view setting and effective scope.","properties":{"branchCount":{"type":"integer"},"isMultiBranch":{"type":"boolean"},"homeBranchName":{"type":"string","nullable":true},"roleDefault":{"type":"string","enum":["all","home"]},"override":{"type":"string","enum":["all","home"],"nullable":true},"effective":{"type":"string","enum":["all","home"]}},"required":["branchCount","isMultiBranch","homeBranchName","roleDefault","override","effective"],"additionalProperties":false},"clock":{"type":"object","properties":{"timezone":{"type":"string"},"openEntry":{"type":"object","description":"The caller's most recent open time entry, if any — including one left open from an earlier day (clock it out with an occurredAt end time).","properties":{"id":{"type":"string","format":"uuid"},"timeType":{"type":"string"},"workOrderId":{"type":"string","format":"uuid","nullable":true},"workOrderNumber":{"type":"integer","nullable":true},"leftOpenFromPriorDay":{"type":"boolean"},"clockInAt":{"type":"string","format":"date-time"},"clockOutAt":{"type":"string","format":"date-time","nullable":true},"locationRecorded":{"type":"boolean","description":"True when the clock-in carried a device location (issue 5819). The coordinates themselves are office-only and never returned here."}},"required":["clockInAt","clockOutAt"],"additionalProperties":false,"nullable":true},"driveMs":{"type":"integer"},"onSiteMs":{"type":"integer"},"phaseOptions":{"type":"array","items":{"type":"object","description":"One (work order, phase) clock-in attribution option (getTodayPhaseOptions).","properties":{"workOrderId":{"type":"string","format":"uuid"},"workOrderNumber":{"type":"integer","nullable":true},"phaseId":{"type":"string","format":"uuid"},"phaseName":{"type":"string"},"projectName":{"type":"string"}},"required":["workOrderId","workOrderNumber","phaseId","phaseName","projectName"],"additionalProperties":false}},"closedEntries":{"type":"array","items":{"type":"object","description":"One closed time entry of the caller's today, or an earlier day's never-submitted draft (getTodayClosedEntries, unchanged shape).","properties":{"id":{"type":"string","format":"uuid"},"timeType":{"type":"string"},"approvalStatus":{"type":"string"},"clockInAt":{"type":"string","format":"date-time"},"clockOutAt":{"type":"string","format":"date-time"},"notes":{"type":"string","nullable":true},"workOrderId":{"type":"string","format":"uuid","nullable":true},"phaseId":{"type":"string","format":"uuid","nullable":true},"workOrderNumber":{"type":"integer","nullable":true},"fromEarlierDay":{"type":"boolean"}},"required":["id","timeType","approvalStatus","clockInAt","clockOutAt","notes","workOrderId","phaseId"],"additionalProperties":false}}},"required":["openEntry","driveMs","onSiteMs","phaseOptions","closedEntries"],"additionalProperties":false},"fieldPurchases":{"type":"array","items":{"type":"object","description":"One of the caller's own field purchases (getFieldPurchases, bounded to 20).","properties":{"id":{"type":"string","format":"uuid"},"vendorName":{"type":"string"},"purchaseDate":{"type":"string","format":"date"},"totalCents":{"type":"integer"},"status":{"type":"string","enum":["draft","submitted","approved","rejected"]},"rejectionReason":{"type":"string","nullable":true},"offlineId":{"type":"string","nullable":true}},"required":["id","vendorName","purchaseDate","totalCents","status","rejectionReason","offlineId"],"additionalProperties":false}},"van":{"type":"object","description":"The caller's own van and its open low-stock alert count, or null when none.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"openAlerts":{"type":"integer"}},"required":["id","name","openAlerts"],"additionalProperties":false,"nullable":true},"scorecard":{"type":"array","items":{"type":"object","description":"One of the caller's own persisted monthly KPI snapshots (own-data-only).","properties":{"monthStart":{"type":"string","format":"date"},"compositeScore":{"type":"integer"},"utilizationPct":{"type":"integer"},"callbackRateTenths":{"type":"integer"},"onTimeArrivalPct":{"type":"integer"},"csatTenths":{"type":"integer"},"csatReviews":{"type":"integer"}},"required":["monthStart","compositeScore","utilizationPct","callbackRateTenths","onTimeArrivalPct","csatTenths","csatReviews"],"additionalProperties":false}}},"required":["technician","voiceAssist","voiceAssistReleased","certLabel","today","ytd","credentials","fieldApp","branchScope","clock","fieldPurchases","van","scorecard"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":true,"x-thermal-side-effect":"read","x-thermal-area":"field-profile","x-thermal-examples":[{"name":"own-profile","request":{}}]}},"/purchase-orders":{"post":{"operationId":"purchase_order.create","summary":"Draft a purchase order","description":"Runs `createPurchaseOrderCore` — the same draft-PO writer the purchasing screen and the `purchase_order.create` registry action use, including the sequential PO number mint and its org-membership checks on every optional reference. A vendor, work order, ship-to site or project that is not in the caller's own organization is reported as `404`: the reference is not visible, and its existence elsewhere is not a fact this caller is entitled to. Classed `medium` because the purchase order is created in `draft`; committing money happens when it is ORDERED, which is not this operation. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The draft purchase order this request created.","properties":{"id":{"type":"string","format":"uuid","description":"The `purchase_orders` row id."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: `purchase_orders` is not a spine table and carries no `row_version`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"purchasing","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"draft a PO against a job","request":{"vendorId":"6e5d4c3b-2a19-4870-9f6e-5d4c3b2a1908","workOrderId":"33333333-3333-4333-8333-333333333333","notes":"Contactor + capacitor for the Ridgeline RTU"}}]}},"/purchase-orders/approve":{"post":{"operationId":"purchase_order.create.approve","summary":"Draft a purchase order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The draft purchase order this request created.","properties":{"id":{"type":"string","format":"uuid","description":"The `purchase_orders` row id."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: `purchase_orders` is not a spine table and carries no `row_version`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"purchasing","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"draft a PO against a job","request":{"vendorId":"6e5d4c3b-2a19-4870-9f6e-5d4c3b2a1908","workOrderId":"33333333-3333-4333-8333-333333333333","notes":"Contactor + capacitor for the Ridgeline RTU"}}]}},"/purchase-orders/preview":{"post":{"operationId":"purchase_order.create.preview","summary":"Draft a purchase order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"purchasing","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"draft a PO against a job","request":{"vendorId":"6e5d4c3b-2a19-4870-9f6e-5d4c3b2a1908","workOrderId":"33333333-3333-4333-8333-333333333333","notes":"Contactor + capacitor for the Ridgeline RTU"}}]}},"/route":{"get":{"operationId":"technician.route_today","summary":"Get the calling technician's route order for today","description":"Today's visits for the calling technician in persisted `route_sequence` order, with `pinUnsequencedActiveEmergencies`'s pinning preserved — the same order `/tech/route` renders. `today` is resolved server-side from the organization's timezone, never from a client-supplied instant.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"timeZone":{"type":"string","description":"The organization's IANA timezone used to render each scheduled instant."},"date":{"type":"string","format":"date"},"stops":{"type":"array","items":{"type":"object","description":"One of today's visits in persisted route order (route-order.ts's pin preserved for an un-sequenced active emergency).","properties":{"driveMinutes":{"type":"number","minimum":0,"description":"Stored optimiser drive minutes from the adjacent previous stop."},"leaveBy":{"type":"string","format":"date-time","description":"Promised window start minus the stored drive minutes; format in the response timeZone."},"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"routeSequence":{"type":"integer","nullable":true},"pinned":{"type":"boolean","description":"True for an un-sequenced active emergency pinned ahead of the DB order."},"status":{"type":"string"},"priority":{"type":"string"},"jobType":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true},"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"serviceSite":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","nullable":true},"addressLine1":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"customerName":{"type":"string","nullable":true}},"required":["id","label","addressLine1","city","state","customerName"],"additionalProperties":false}},"required":["id","workOrderId","routeSequence","pinned","status","priority","jobType","summary","scheduledStart","scheduledEnd","serviceSite"],"additionalProperties":false}}},"required":["timeZone","date","stops"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-schedule","x-thermal-examples":[{"name":"todays-route","request":{}}]}},"/schedule":{"get":{"operationId":"technician.schedule_week","summary":"Get the calling technician's 7-day schedule","description":"The technician's own visits for the next 7 calendar days (today through +6), grouped by day in the organization's timezone — the same window and day-grouping `/tech/schedule` renders, computed the same way (`isoDateInTz`, `classifyTechVisitDay`, `buildTechSpineRows`). The window is resolved server-side; it is never a client-supplied date range.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"today":{"type":"string","format":"date"},"horizonEnd":{"type":"string","format":"date"},"days":{"type":"array","items":{"type":"object","description":"One calendar day of the 7-day window, today through +6, in the org's timezone.","properties":{"date":{"type":"string","format":"date"},"label":{"type":"string","description":"\"Today\", \"Tomorrow\", or a weekday label."},"isSunday":{"type":"boolean"},"rows":{"type":"array","items":{"type":"object","description":"One visit as the technician's day spine renders it (today-data.ts's TechSpineRow) — the same row Today/Schedule/Route already build, reused verbatim rather than re-derived for the API.","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"href":{"type":"string"},"label":{"type":"string"},"customerName":{"type":"string"},"workOrderLabel":{"type":"string","nullable":true},"status":{"type":"string"},"timeLabel":{"type":"string"},"promisedWindowLabel":{"type":"string"},"agreementLabel":{"type":"string","nullable":true},"equipmentIdentifier":{"type":"string","nullable":true},"visitPositionLabel":{"type":"string"},"siteLabel":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true},"equipmentLabel":{"type":"string","nullable":true},"accessNotes":{"type":"string","nullable":true},"telHref":{"type":"string","nullable":true},"mapsHref":{"type":"string","nullable":true},"lateLabel":{"type":"string","nullable":true},"jobTypeLabel":{"type":"string"},"emergency":{"type":"boolean"},"awaitingParts":{"type":"boolean"},"onPartsHold":{"type":"boolean"},"state":{"type":"string","enum":["default","next","in-progress","complete","late"]},"group":{"type":"string","nullable":true},"travelFromPrevious":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["same-site"]},"label":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["optimized-drive"]},"label":{"type":"string"},"driveMinutes":{"type":"number"}},"required":["kind","label","driveMinutes"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["direct-distance"]},"label":{"type":"string"},"directMiles":{"type":"number"}},"required":["kind","label","directMiles"],"additionalProperties":false}],"nullable":true}},"required":["id","workOrderId","href","label","customerName","workOrderLabel","status","timeLabel","promisedWindowLabel","agreementLabel","equipmentIdentifier","visitPositionLabel","siteLabel","summary","equipmentLabel","accessNotes","telHref","mapsHref","lateLabel","jobTypeLabel","emergency","awaitingParts","onPartsHold","state","group","travelFromPrevious"],"additionalProperties":false}}},"required":["date","label","isSunday","rows"],"additionalProperties":false}}},"required":["today","horizonEnd","days"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"field-schedule","x-thermal-examples":[{"name":"seven-day-window","request":{}}]}},"/service-agreements/{serviceAgreementId}/pm-visits":{"post":{"operationId":"work_order.create_pm_visit","summary":"Create the preventive-maintenance work order a PM plan identified","description":"Creates a PM visit through the `work_order.create_pm_visit` registry action. Idempotent at the database level: if the same PM item was already fulfilled, the existing open work order is returned with `created: false` rather than a duplicate being written. `equipmentType` is not part of this contract — the action resolves the checklist template from the equipment row itself. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"serviceAgreementId","in":"path","required":true,"description":"The serviceAgreementId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The preventive-maintenance work order this visit resolved to.","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"integer"},"status":{"type":"string"},"created":{"type":"boolean","description":"False when a concurrent run or a second approval had already fulfilled this exact PM item and the call resolved to the pre-existing work order."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","number","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"create a quarterly PM visit","request":{"serviceSiteId":"99999999-9999-4999-8999-999999999999","summary":"Q3 preventive maintenance","scheduledStart":"2026-09-25T15:00:00.000Z","scheduledEnd":"2026-09-25T17:00:00.000Z"}}]}},"/service-agreements/{serviceAgreementId}/pm-visits/approve":{"post":{"operationId":"work_order.create_pm_visit.approve","summary":"Create the preventive-maintenance work order a PM plan identified — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"serviceAgreementId","in":"path","required":true,"description":"The serviceAgreementId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The preventive-maintenance work order this visit resolved to.","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"integer"},"status":{"type":"string"},"created":{"type":"boolean","description":"False when a concurrent run or a second approval had already fulfilled this exact PM item and the call resolved to the pre-existing work order."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","number","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"create a quarterly PM visit","request":{"serviceSiteId":"99999999-9999-4999-8999-999999999999","summary":"Q3 preventive maintenance","scheduledStart":"2026-09-25T15:00:00.000Z","scheduledEnd":"2026-09-25T17:00:00.000Z"}}]}},"/service-agreements/{serviceAgreementId}/pm-visits/preview":{"post":{"operationId":"work_order.create_pm_visit.preview","summary":"Create the preventive-maintenance work order a PM plan identified — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"serviceAgreementId","in":"path","required":true,"description":"The serviceAgreementId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"create a quarterly PM visit","request":{"serviceSiteId":"99999999-9999-4999-8999-999999999999","summary":"Q3 preventive maintenance","scheduledStart":"2026-09-25T15:00:00.000Z","scheduledEnd":"2026-09-25T17:00:00.000Z"}}]}},"/service-sites/{serviceSiteId}/work-orders":{"post":{"operationId":"work_order.create","summary":"Create a work order for a service site","description":"Creates a work order through the `work_order.create` registry action. The owning branch comes from the caller's resolved scope, never from the request; the non-compete and phase gates are enforced by the action itself. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"serviceSiteId","in":"path","required":true,"description":"The serviceSiteId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The created work order.","properties":{"id":{"type":"string","format":"uuid","description":"The created work order."},"serviceSiteId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","serviceSiteId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"create a repair job","request":{"jobType":"repair","summary":"No cooling on RTU-2","priority":"high"}}]}},"/service-sites/{serviceSiteId}/work-orders/approve":{"post":{"operationId":"work_order.create.approve","summary":"Create a work order for a service site — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"serviceSiteId","in":"path","required":true,"description":"The serviceSiteId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The created work order.","properties":{"id":{"type":"string","format":"uuid","description":"The created work order."},"serviceSiteId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","serviceSiteId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"create a repair job","request":{"jobType":"repair","summary":"No cooling on RTU-2","priority":"high"}}]}},"/service-sites/{serviceSiteId}/work-orders/preview":{"post":{"operationId":"work_order.create.preview","summary":"Create a work order for a service site — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"serviceSiteId","in":"path","required":true,"description":"The serviceSiteId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"create a repair job","request":{"jobType":"repair","summary":"No cooling on RTU-2","priority":"high"}}]}},"/technicians/{id}/route/optimize":{"post":{"operationId":"optimizeMyRoute","summary":"Optimize one technician's route for today","description":"Re-sequences the named technician's own active stops for today through the same server-side optimizer and applyRoutePlanWrite persistence path used by the technician web action. A technician may name only themselves; office roles retain branch-scoped access to technicians they manage. Scheduled start times are preserved. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The optimized technician route and the number of persisted stops.","properties":{"id":{"type":"string","format":"uuid"},"stopCount":{"type":"integer","minimum":2},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: the route is an ordered set, not a row-versioned spine record."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response without optimizing twice."}},"required":["id","stopCount","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"optimize today's route","request":{}}]}},"/technicians/{id}/route/optimize/approve":{"post":{"operationId":"optimizeMyRoute.approve","summary":"Optimize one technician's route for today — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The optimized technician route and the number of persisted stops.","properties":{"id":{"type":"string","format":"uuid"},"stopCount":{"type":"integer","minimum":2},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: the route is an ordered set, not a row-versioned spine record."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response without optimizing twice."}},"required":["id","stopCount","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"optimize today's route","request":{}}]}},"/technicians/{id}/route/optimize/preview":{"post":{"operationId":"optimizeMyRoute.preview","summary":"Optimize one technician's route for today — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"optimize today's route","request":{}}]}},"/technicians/{technicianUserId}/shift-next-visits":{"post":{"operationId":"dispatch.shift_next_visits","summary":"Push back a technician's next visits today","description":"Running late: moves the named technician's next 1–3 open visits today (route order) later by 1–120 minutes, sets each visit's customer ETA, and re-notices customers who had confirmed. Preview first: the preview binds the exact moves into a proposal, and the apply presents it back — by the technician, or through `/approve` by an office user in the same branch. A technician may name only themselves. Refusals carry a named code: `not_own_visits`, `shift_not_same_day`, `visit_already_arrived`, `no_visits_to_shift` or `placement_rejected`. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"technicianUserId","in":"path","required":true,"description":"The technicianUserId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The visits the governed write moved, and the confirmed customers it re-noticed.","properties":{"id":{"type":"string","format":"uuid","description":"The technician whose visits moved."},"shifted":{"type":"integer","minimum":1,"maximum":3},"appointmentIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The appointments moved, in route order."},"reconfirmedWorkOrderIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Work orders whose customer confirmation was cleared by the move."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: the operation declares `rowVersionStrategy: \"none\"` — the bounded action re-plans against live state inside its own transaction."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","shifted","appointmentIds","reconfirmedWorkOrderIds","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"running 30 minutes late for the next two visits","request":{"technicianUserId":"55555555-5555-4555-8555-555555555555","delayMinutes":30,"count":2,"delayReason":"Stuck behind a crash on the interstate","notifyContacts":true}}]}},"/technicians/{technicianUserId}/shift-next-visits/approve":{"post":{"operationId":"dispatch.shift_next_visits.approve","summary":"Push back a technician's next visits today — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"technicianUserId","in":"path","required":true,"description":"The technicianUserId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The visits the governed write moved, and the confirmed customers it re-noticed.","properties":{"id":{"type":"string","format":"uuid","description":"The technician whose visits moved."},"shifted":{"type":"integer","minimum":1,"maximum":3},"appointmentIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The appointments moved, in route order."},"reconfirmedWorkOrderIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Work orders whose customer confirmation was cleared by the move."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: the operation declares `rowVersionStrategy: \"none\"` — the bounded action re-plans against live state inside its own transaction."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","shifted","appointmentIds","reconfirmedWorkOrderIds","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"running 30 minutes late for the next two visits","request":{"technicianUserId":"55555555-5555-4555-8555-555555555555","delayMinutes":30,"count":2,"delayReason":"Stuck behind a crash on the interstate","notifyContacts":true}}]}},"/technicians/{technicianUserId}/shift-next-visits/preview":{"post":{"operationId":"dispatch.shift_next_visits.preview","summary":"Push back a technician's next visits today — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"technicianUserId","in":"path","required":true,"description":"The technicianUserId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-schedule","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"running 30 minutes late for the next two visits","request":{"technicianUserId":"55555555-5555-4555-8555-555555555555","delayMinutes":30,"count":2,"delayReason":"Stuck behind a crash on the interstate","notifyContacts":true}}]}},"/time-entries/clock-in":{"post":{"operationId":"time_entry.clock_in","summary":"Clock the signed-in technician in","description":"Opens a time entry for the signed-in technician, optionally attributed to a work order and project phase. Idempotent twice over: the writer short-circuits when an entry is already open, and a replayed idempotency key returns the stored result without a second effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The technician's own time card after the clock-in.","properties":{"id":{"type":"string","format":"uuid","description":"The acting technician's staff user id — the time card this operation acts on."},"timeEntryId":{"type":"string","format":"uuid","nullable":true,"description":"The open time entry after this call: the one just opened, or the one that was already open."},"alreadyOpen":{"type":"boolean","description":"True when an entry was already open and the writer short-circuited. The clock-in is idempotent by construction, independently of the idempotency key."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","timeEntryId","alreadyOpen","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"plain clock-in","request":{"occurredAt":"2026-09-21T15:00:00.000Z"}},{"name":"clock in against a job phase","request":{"workOrderId":"33333333-3333-4333-8333-333333333333","phaseId":"44444444-4444-4444-8444-444444444444","timeType":"reg","occurredAt":"2026-09-21T15:00:00.000Z"}},{"name":"clock in with the device location","request":{"occurredAt":"2026-09-21T15:00:00.000Z","location":{"latitude":49.2827,"longitude":-123.1207,"accuracyM":12}}}]}},"/time-entries/clock-in/approve":{"post":{"operationId":"time_entry.clock_in.approve","summary":"Clock the signed-in technician in — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The technician's own time card after the clock-in.","properties":{"id":{"type":"string","format":"uuid","description":"The acting technician's staff user id — the time card this operation acts on."},"timeEntryId":{"type":"string","format":"uuid","nullable":true,"description":"The open time entry after this call: the one just opened, or the one that was already open."},"alreadyOpen":{"type":"boolean","description":"True when an entry was already open and the writer short-circuited. The clock-in is idempotent by construction, independently of the idempotency key."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","timeEntryId","alreadyOpen","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"plain clock-in","request":{"occurredAt":"2026-09-21T15:00:00.000Z"}},{"name":"clock in against a job phase","request":{"workOrderId":"33333333-3333-4333-8333-333333333333","phaseId":"44444444-4444-4444-8444-444444444444","timeType":"reg","occurredAt":"2026-09-21T15:00:00.000Z"}},{"name":"clock in with the device location","request":{"occurredAt":"2026-09-21T15:00:00.000Z","location":{"latitude":49.2827,"longitude":-123.1207,"accuracyM":12}}}]}},"/time-entries/clock-in/preview":{"post":{"operationId":"time_entry.clock_in.preview","summary":"Clock the signed-in technician in — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"plain clock-in","request":{"occurredAt":"2026-09-21T15:00:00.000Z"}},{"name":"clock in against a job phase","request":{"workOrderId":"33333333-3333-4333-8333-333333333333","phaseId":"44444444-4444-4444-8444-444444444444","timeType":"reg","occurredAt":"2026-09-21T15:00:00.000Z"}},{"name":"clock in with the device location","request":{"occurredAt":"2026-09-21T15:00:00.000Z","location":{"latitude":49.2827,"longitude":-123.1207,"accuracyM":12}}}]}},"/time-entries/clock-out":{"post":{"operationId":"time_entry.clock_out","summary":"Clock the signed-in technician out","description":"Closes the signed-in technician's open time entry and reconciles its cost attribution, in the same transaction the web app's own clock-out uses. A replay returns the first result and never re-closes an entry, so `clock_out_at` is written exactly once. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The technician's own time card after the clock-out.","properties":{"id":{"type":"string","format":"uuid","description":"The acting technician's staff user id."},"timeEntryId":{"type":"string","format":"uuid","nullable":true,"description":"The entry this call closed, or null when there was no open entry to close."},"closed":{"type":"boolean","description":"True when this call closed an entry."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","timeEntryId","closed","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"clock out","request":{"occurredAt":"2026-09-21T23:00:00.000Z"}},{"name":"clock out with the device location","request":{"occurredAt":"2026-09-21T23:00:00.000Z","location":{"latitude":49.2827,"longitude":-123.1207,"accuracyM":12}}}]}},"/time-entries/clock-out/approve":{"post":{"operationId":"time_entry.clock_out.approve","summary":"Clock the signed-in technician out — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The technician's own time card after the clock-out.","properties":{"id":{"type":"string","format":"uuid","description":"The acting technician's staff user id."},"timeEntryId":{"type":"string","format":"uuid","nullable":true,"description":"The entry this call closed, or null when there was no open entry to close."},"closed":{"type":"boolean","description":"True when this call closed an entry."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","timeEntryId","closed","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"clock out","request":{"occurredAt":"2026-09-21T23:00:00.000Z"}},{"name":"clock out with the device location","request":{"occurredAt":"2026-09-21T23:00:00.000Z","location":{"latitude":49.2827,"longitude":-123.1207,"accuracyM":12}}}]}},"/time-entries/clock-out/preview":{"post":{"operationId":"time_entry.clock_out.preview","summary":"Clock the signed-in technician out — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"clock out","request":{"occurredAt":"2026-09-21T23:00:00.000Z"}},{"name":"clock out with the device location","request":{"occurredAt":"2026-09-21T23:00:00.000Z","location":{"latitude":49.2827,"longitude":-123.1207,"accuracyM":12}}}]}},"/time-entries/submit-day":{"post":{"operationId":"time_entry.submit_day","summary":"Submit the signed-in technician's own closed draft entries for today","description":"Moves the caller's own still-draft, already-closed entries clocked in today to `submitted`, and returns the soft payroll-period warnings the web app surfaces as a toast. Direct/online-only, matching the web app's own non-queued posture. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The result of submitting the technician's own closed draft entries for today.","properties":{"id":{"type":"string","format":"uuid","description":"The acting technician's staff user id."},"warnings":{"type":"array","description":"Soft payroll-period validation warnings. Advisory only — `submitDay` never blocks the submit on them.","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":true}},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","warnings","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"submit today","request":{}}]}},"/time-entries/submit-day/approve":{"post":{"operationId":"time_entry.submit_day.approve","summary":"Submit the signed-in technician's own closed draft entries for today — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The result of submitting the technician's own closed draft entries for today.","properties":{"id":{"type":"string","format":"uuid","description":"The acting technician's staff user id."},"warnings":{"type":"array","description":"Soft payroll-period validation warnings. Advisory only — `submitDay` never blocks the submit on them.","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":true}},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: neither `time_entries` nor `users` carries migration 0385's server-owned `row_version`, so the operation declares `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","warnings","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"submit today","request":{}}]}},"/time-entries/submit-day/preview":{"post":{"operationId":"time_entry.submit_day.preview","summary":"Submit the signed-in technician's own closed draft entries for today — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"time-clock","x-thermal-target-table":"time_entries","x-thermal-examples":[{"name":"submit today","request":{}}]}},"/van":{"get":{"operationId":"van_stock.list","summary":"List the calling technician's own van stock","description":"Every line item with a live presence on the calling technician's own van — the same list, and the same own-van scoping, `/tech/van` renders (`resolveOwnVanLocation` then `fetchVanBrowseData`). `van` is null when the caller has no van assigned: an honest empty state, never another van's stock or the org warehouse.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's own van (or null) and its live-presence line items.","properties":{"van":{"type":"object","nullable":true,"description":"The caller's own van stock location, or null when none is assigned.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"stock":{"type":"array","items":{"type":"object","description":"One line item with a live presence on the caller's own van (van-core.ts's VanBrowseItem).","properties":{"id":{"type":"string","format":"uuid"},"pricebookItemId":{"type":"string","format":"uuid","nullable":true,"description":"The catalogue item backed by this inventory row, or null when the stocked item is not linked to the pricebook."},"name":{"type":"string"},"category":{"type":"string","nullable":true},"isSerialized":{"type":"boolean"},"onHand":{"type":"integer","description":"Quantity on hand for a quantity item, or the live `in_stock` unit count for a serialized one — `fetchVanBrowseData`'s own accounting."},"reorderThreshold":{"type":"integer"},"low":{"type":"boolean"}},"required":["id","pricebookItemId","name","category","isSerialized","onHand","reorderThreshold","low"],"additionalProperties":false}},"itemCount":{"type":"integer"}},"required":["van","stock","itemCount"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"van-stock","x-thermal-examples":[{"name":"own-van-stock","request":{}}]}},"/van-stock/items/{id}/checkout":{"post":{"operationId":"checkoutVanQuantity","summary":"Charge bulk van stock to a work order","description":"Charges a whole-number quantity of a non-serialized item from the caller's own van to a work order they are assigned to. Refused when the quantity exceeds what is available on that van after commitments. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The bulk item's van availability after the checkout. `availableQuantity` is the same on-hand-minus-committed figure the item detail screen shows, re-read after the write.","properties":{"inventoryItemId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"quantity":{"type":"integer","minimum":1,"description":"The quantity this call charged to the job."},"availableQuantity":{"type":"integer","description":"On-hand minus committed on this van after the write. Not a stock decrement — work-order completion is the single site that depletes `inventory_stock` (see van-core.ts's header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["inventoryItemId","workOrderId","stockLocationId","quantity","availableQuantity","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_stock","x-thermal-examples":[{"name":"two lengths of line set","request":{"id":"55555555-5555-4555-8555-555555555555","workOrderId":"33333333-3333-4333-8333-333333333333","quantity":2}}]}},"/van-stock/items/{id}/checkout/approve":{"post":{"operationId":"checkoutVanQuantity.approve","summary":"Charge bulk van stock to a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The bulk item's van availability after the checkout. `availableQuantity` is the same on-hand-minus-committed figure the item detail screen shows, re-read after the write.","properties":{"inventoryItemId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"quantity":{"type":"integer","minimum":1,"description":"The quantity this call charged to the job."},"availableQuantity":{"type":"integer","description":"On-hand minus committed on this van after the write. Not a stock decrement — work-order completion is the single site that depletes `inventory_stock` (see van-core.ts's header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["inventoryItemId","workOrderId","stockLocationId","quantity","availableQuantity","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_stock","x-thermal-examples":[{"name":"two lengths of line set","request":{"id":"55555555-5555-4555-8555-555555555555","workOrderId":"33333333-3333-4333-8333-333333333333","quantity":2}}]}},"/van-stock/items/{id}/checkout/preview":{"post":{"operationId":"checkoutVanQuantity.preview","summary":"Charge bulk van stock to a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_stock","x-thermal-examples":[{"name":"two lengths of line set","request":{"id":"55555555-5555-4555-8555-555555555555","workOrderId":"33333333-3333-4333-8333-333333333333","quantity":2}}]}},"/van-stock/items/{id}/consume":{"post":{"operationId":"consumeVanStock","summary":"Consume stock directly from the technician's van","description":"Records direct use of a quantity of an item from the caller's own van, outside any work order. Serialized items are consumed one unit at a time. The van is resolved from the caller's assignment, never from the request. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The van's on-hand quantity after the direct consumption, read back inside the same idempotent effect.","properties":{"inventoryItemId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"quantity":{"type":"integer","minimum":1,"description":"The quantity this call consumed."},"onHandQuantity":{"type":"integer","description":"The van's on-hand count after the write (floored at zero by incrementStock)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["inventoryItemId","stockLocationId","quantity","onHandQuantity","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_stock","x-thermal-examples":[{"name":"one damaged filter","request":{"id":"55555555-5555-4555-8555-555555555555","quantity":1,"note":"damaged in transit"}}]}},"/van-stock/items/{id}/consume/approve":{"post":{"operationId":"consumeVanStock.approve","summary":"Consume stock directly from the technician's van — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The van's on-hand quantity after the direct consumption, read back inside the same idempotent effect.","properties":{"inventoryItemId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"quantity":{"type":"integer","minimum":1,"description":"The quantity this call consumed."},"onHandQuantity":{"type":"integer","description":"The van's on-hand count after the write (floored at zero by incrementStock)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["inventoryItemId","stockLocationId","quantity","onHandQuantity","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_stock","x-thermal-examples":[{"name":"one damaged filter","request":{"id":"55555555-5555-4555-8555-555555555555","quantity":1,"note":"damaged in transit"}}]}},"/van-stock/items/{id}/consume/preview":{"post":{"operationId":"consumeVanStock.preview","summary":"Consume stock directly from the technician's van — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_stock","x-thermal-examples":[{"name":"one damaged filter","request":{"id":"55555555-5555-4555-8555-555555555555","quantity":1,"note":"damaged in transit"}}]}},"/van-stock/items/{id}/restock-request":{"post":{"operationId":"requestVanRestock","summary":"Ask the office to restock an item on the technician's van","description":"Files a restock ask for an item on the caller's own van, snapshotting the quantity and reorder threshold at ask time. A re-tap while an ask is already open returns that same ask rather than filing a second one. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The open restock ask for this item on this van. At most one can exist — `inventory_restock_requests_open_uq` is a partial unique index over ('pending','partially_fulfilled') — so this identifies a row rather than one of several.","properties":{"restockRequestId":{"type":"string","format":"uuid"},"inventoryItemId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"status":{"type":"string","description":"The ask's status. `pending` on a fresh request."},"requestedQuantity":{"type":"integer","minimum":1},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["restockRequestId","inventoryItemId","stockLocationId","status","requestedQuantity","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_restock_requests","x-thermal-examples":[{"name":"out of 20x25 filters","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/van-stock/items/{id}/restock-request/approve":{"post":{"operationId":"requestVanRestock.approve","summary":"Ask the office to restock an item on the technician's van — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The open restock ask for this item on this van. At most one can exist — `inventory_restock_requests_open_uq` is a partial unique index over ('pending','partially_fulfilled') — so this identifies a row rather than one of several.","properties":{"restockRequestId":{"type":"string","format":"uuid"},"inventoryItemId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"status":{"type":"string","description":"The ask's status. `pending` on a fresh request."},"requestedQuantity":{"type":"integer","minimum":1},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["restockRequestId","inventoryItemId","stockLocationId","status","requestedQuantity","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_restock_requests","x-thermal-examples":[{"name":"out of 20x25 filters","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/van-stock/items/{id}/restock-request/preview":{"post":{"operationId":"requestVanRestock.preview","summary":"Ask the office to restock an item on the technician's van — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"inventory_restock_requests","x-thermal-examples":[{"name":"out of 20x25 filters","request":{"id":"55555555-5555-4555-8555-555555555555"}}]}},"/van-stock/purchase-orders/{id}/receive":{"post":{"operationId":"purchase_order.receive_to_van","summary":"Receive a job's purchase order lines onto the technician's van","description":"Receives whole-number quantities of one or more lines of a purchase order raised for a work order the caller is assigned to, into the caller's own van. The purchase order must be ordered or partly received. Every line must be on the purchase order and no quantity may exceed what is still open; otherwise the whole request is refused and nothing is written. The van is resolved from the caller's assignment, never from the request. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The lines to receive (1 to 200, each line at most once) and how many of each. The van is never named: it is the caller's own, resolved server-side.","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string","format":"uuid","description":"A line on this purchase order."},"quantity":{"type":"integer","minimum":1,"description":"Whole units to receive; at most the line's open quantity."}},"required":["lineId","quantity"],"additionalProperties":false}}},"required":["lines"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The purchase order after the receipt, read back inside the same idempotent effect so a replay returns the identical body.","properties":{"purchaseOrderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["partial","received"],"description":"The purchase order's status after the receipt."},"receiptId":{"type":"string","format":"uuid","description":"The posted receipt this call wrote."},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string","format":"uuid"},"receivedQuantity":{"type":"integer","minimum":1,"description":"Units this call received."},"totalReceivedQuantity":{"type":"integer","minimum":0},"openQuantity":{"type":"integer","minimum":0}},"required":["lineId","receivedQuantity","totalReceivedQuantity","openQuantity"],"additionalProperties":false}},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["purchaseOrderId","status","receiptId","stockLocationId","lines","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"three filters delivered to the job","request":{"id":"66666666-6666-4666-8666-666666666666","lines":[{"lineId":"77777777-7777-4777-8777-777777777777","quantity":3}]}}]}},"/van-stock/purchase-orders/{id}/receive/approve":{"post":{"operationId":"purchase_order.receive_to_van.approve","summary":"Receive a job's purchase order lines onto the technician's van — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The lines to receive (1 to 200, each line at most once) and how many of each. The van is never named: it is the caller's own, resolved server-side.","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string","format":"uuid","description":"A line on this purchase order."},"quantity":{"type":"integer","minimum":1,"description":"Whole units to receive; at most the line's open quantity."}},"required":["lineId","quantity"],"additionalProperties":false}}},"required":["lines"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The purchase order after the receipt, read back inside the same idempotent effect so a replay returns the identical body.","properties":{"purchaseOrderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["partial","received"],"description":"The purchase order's status after the receipt."},"receiptId":{"type":"string","format":"uuid","description":"The posted receipt this call wrote."},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string","format":"uuid"},"receivedQuantity":{"type":"integer","minimum":1,"description":"Units this call received."},"totalReceivedQuantity":{"type":"integer","minimum":0},"openQuantity":{"type":"integer","minimum":0}},"required":["lineId","receivedQuantity","totalReceivedQuantity","openQuantity"],"additionalProperties":false}},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["purchaseOrderId","status","receiptId","stockLocationId","lines","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"three filters delivered to the job","request":{"id":"66666666-6666-4666-8666-666666666666","lines":[{"lineId":"77777777-7777-4777-8777-777777777777","quantity":3}]}}]}},"/van-stock/purchase-orders/{id}/receive/preview":{"post":{"operationId":"purchase_order.receive_to_van.preview","summary":"Receive a job's purchase order lines onto the technician's van — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The lines to receive (1 to 200, each line at most once) and how many of each. The van is never named: it is the caller's own, resolved server-side.","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string","format":"uuid","description":"A line on this purchase order."},"quantity":{"type":"integer","minimum":1,"description":"Whole units to receive; at most the line's open quantity."}},"required":["lineId","quantity"],"additionalProperties":false}}},"required":["lines"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"three filters delivered to the job","request":{"id":"66666666-6666-4666-8666-666666666666","lines":[{"lineId":"77777777-7777-4777-8777-777777777777","quantity":3}]}}]}},"/van-stock/units/{id}/checkout":{"post":{"operationId":"checkoutVanUnit","summary":"Check a serialized unit out of the technician's van onto a work order","description":"Reserves one in-stock serialized unit from the caller's own van to a work order they are assigned to, and charges it to that job as a line item. The van is resolved from the caller's assignment, never from the request. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The serialized unit's state after the checkout, read back inside the same idempotent effect so a replay returns the identical body.","properties":{"unitId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"unitStatus":{"type":"string","description":"The unit's status after the write. `checked_out` on success."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["unitId","workOrderId","stockLocationId","unitStatus","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"units","x-thermal-examples":[{"name":"load a compressor onto today's job","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333"}}]}},"/van-stock/units/{id}/checkout/approve":{"post":{"operationId":"checkoutVanUnit.approve","summary":"Check a serialized unit out of the technician's van onto a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The serialized unit's state after the checkout, read back inside the same idempotent effect so a replay returns the identical body.","properties":{"unitId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"stockLocationId":{"type":"string","format":"uuid","description":"The technician's own van, resolved server-side — never supplied by the caller."},"unitStatus":{"type":"string","description":"The unit's status after the write. `checked_out` on success."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["unitId","workOrderId","stockLocationId","unitStatus","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"units","x-thermal-examples":[{"name":"load a compressor onto today's job","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333"}}]}},"/van-stock/units/{id}/checkout/preview":{"post":{"operationId":"checkoutVanUnit.preview","summary":"Check a serialized unit out of the technician's van onto a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"van-stock","x-thermal-target-table":"units","x-thermal-examples":[{"name":"load a compressor onto today's job","request":{"id":"44444444-4444-4444-8444-444444444444","workOrderId":"33333333-3333-4333-8333-333333333333"}}]}},"/van/items/{itemId}":{"get":{"operationId":"van_stock.get","summary":"Get one item's detail on the calling technician's own van","description":"One inventory item's detail as `/tech/van/[itemId]` renders it — serialized unit rows or quantity on-hand/committed/available — wrapped from `fetchVanItemDetail` verbatim. The caller's own van is resolved server-side; an item with no presence on that van answers `404`, never another van's detail.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"itemId","in":"path","required":true,"description":"The inventory item id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"One item's detail on the caller's own van — van-core.ts's VanItemDetail, unchanged.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"category":{"type":"string","nullable":true},"isSerialized":{"type":"boolean"},"reorderThreshold":{"type":"integer"},"low":{"type":"boolean"},"chargeable":{"type":"boolean","description":"True when the item is linked to an active, priced pricebook item."},"unitPriceCents":{"type":"integer","nullable":true},"pricebookCode":{"type":"string","nullable":true},"inStockUnits":{"type":"array","items":{"type":"object","description":"One serialized unit on the caller's own van (van-core.ts's VanUnitRow).","properties":{"id":{"type":"string","format":"uuid"},"serial":{"type":"string","nullable":true},"status":{"type":"string","enum":["in_stock","checked_out","consumed"]},"updatedAt":{"type":"string","format":"date-time"},"workOrderNumber":{"type":"integer","nullable":true}},"required":["id","serial","status","updatedAt","workOrderNumber"],"additionalProperties":false}},"recentlyUsed":{"type":"array","items":{"type":"object","description":"One serialized unit on the caller's own van (van-core.ts's VanUnitRow).","properties":{"id":{"type":"string","format":"uuid"},"serial":{"type":"string","nullable":true},"status":{"type":"string","enum":["in_stock","checked_out","consumed"]},"updatedAt":{"type":"string","format":"date-time"},"workOrderNumber":{"type":"integer","nullable":true}},"required":["id","serial","status","updatedAt","workOrderNumber"],"additionalProperties":false}},"onHand":{"type":"integer"},"committed":{"type":"integer"},"available":{"type":"integer"},"pendingRestockRequest":{"type":"boolean"}},"required":["id","name","category","isSerialized","reorderThreshold","low","chargeable","unitPriceCents","pricebookCode","inStockUnits","recentlyUsed","onHand","committed","available","pendingRestockRequest"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"van-stock","x-thermal-examples":[{"name":"own-van-item","request":{"itemId":"00000000-0000-4000-8000-000000000010"}}]}},"/voice/sessions":{"post":{"operationId":"voice.sessions.open","summary":"Open the technician's voice session","description":"Technician session only. Organization, user and branch are resolved from the principal. Off refuses admission. End is atomic and repeatable.","security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"engine":{"type":"string","enum":["openai"]},"clientSecret":{"type":"string","description":"Ephemeral credential. Expires within 60 seconds; never logged or stored on device."},"expiresAt":{"type":"integer"},"model":{"type":"string"},"socketUrl":{"type":"string","format":"uri","description":"Cloudflare voice gateway WebSocket URL. Contains no credential."},"level":{"type":"string","enum":["suggest","auto"]},"tools":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string","enum":["whats_next","equipment_history","running_late","add_note_or_time","on_my_way","start_work","navigate_to_stop","stop_listening"]},"operationId":{"type":"string"},"mode":{"type":"string","enum":["read","preview","apply","client"]}},"required":["tool","operationId","mode"],"additionalProperties":false}}},"required":["id","engine","clientSecret","expiresAt","model","socketUrl","level","tools"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile"}},"/voice/sessions/{id}/end":{"patch":{"operationId":"voice.sessions.end","summary":"End the technician's own voice session","description":"Technician session only. Organization, user and branch are resolved from the principal. Off refuses admission. End is atomic and repeatable.","security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ended_reason":{"type":"string","enum":["user_stop","org_off","offline","engine_error","screen_exit","navigation","superseded","reconnect"]},"duration_ms":{"type":"integer","minimum":0,"maximum":2147483647},"usage":{"type":"object","description":"Session totals from response.done, deduplicated by response id. Input text/audio counts exclude separately reported cached counts. active_audio_ms is microphone frames appended plus audio played, not elapsed duration. Cached text + audio must total at most 2147483647.","properties":{"input_text_tokens":{"type":"integer","minimum":0,"maximum":2147483647},"input_audio_tokens":{"type":"integer","minimum":0,"maximum":2147483647},"input_cached_text_tokens":{"type":"integer","minimum":0,"maximum":2147483647},"input_cached_audio_tokens":{"type":"integer","minimum":0,"maximum":2147483647},"output_text_tokens":{"type":"integer","minimum":0,"maximum":2147483647},"output_audio_tokens":{"type":"integer","minimum":0,"maximum":2147483647},"responses":{"type":"integer","minimum":0,"maximum":2147483647},"active_audio_ms":{"type":"integer","minimum":0,"maximum":2147483647}},"required":["input_text_tokens","input_audio_tokens","input_cached_text_tokens","input_cached_audio_tokens","output_text_tokens","output_audio_tokens","responses","active_audio_ms"],"additionalProperties":false}},"required":["ended_reason","duration_ms"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"ended_at":{"type":"string","format":"date-time"},"duration_ms":{"type":"integer"},"ended_reason":{"type":"string"},"kill_switch_hit":{"type":"boolean"}},"required":["id","ended_at","duration_ms","ended_reason","kill_switch_hit"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"502":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"503":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-profile"}},"/whoami":{"get":{"operationId":"principal.whoami","summary":"Get the calling credential's resolved principal","description":"The principal the server resolved for the presented credential (user session, OAuth client token or org API key): its type, id, server-owned delegation class, role ceiling and scopes, the organization it is acting in, and every organization it may act in. Send the optional `thermal-organization` header to select an organization; it is a claim the server verifies, and naming an organization the credential cannot act in is refused 403 `wrong_org`. A credential that may act in more than one organization and names none is refused 409 `ambiguous_organization`, whose body lists those organizations and no principal. Nothing in the request can choose the delegation class.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The resolved principal and its organizations.","properties":{"principal":{"type":"object","properties":{"type":{"type":"string","enum":["user","oauthClient","apiKey","webhookIntegration"]},"id":{"type":"string"},"delegationClass":{"type":"string","enum":["integration","external-agent"],"nullable":true},"roleCeiling":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string"}}},"required":["type","id","delegationClass","roleCeiling","scopes"],"additionalProperties":false},"organization":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"organizations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["principal","organization","organizations"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version. Also `ambiguous_organization` when the credential may act in more than one organization and names none.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/AmbiguousOrganization"}]}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"integrations","x-thermal-examples":[{"name":"whoami","request":{}}]}},"/work-orders":{"get":{"operationId":"work_order.list","summary":"List work orders for the technician's day","description":"Today's work orders for the caller's resolved branch — the first surface M2's thin slice opens. `scope=today` resolves the day server-side from the organization's timezone; a client never supplies the instant. Branch scope comes from the resolved context, never from a filter.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"scope","in":"query","required":false,"description":"`today` (default) for the technician's day, `open` for every open work order in scope.","schema":{"type":"string","enum":["today","open"]}},{"name":"branchId","in":"query","required":false,"description":"Narrow to one branch the caller is granted. Never WIDENS scope: the resolver denies a branch outside the credential's grants with `wrong_branch`.","schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"description":"Page size. The maximum is a contract limit and is validated, not clamped silently (http-contract.md § Pagination).","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"Opaque keyset cursor from a previous page's nextCursor. There is no offset pagination on spine reads, so a concurrent write cannot shift a page boundary.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A cursor-paginated page of work orders.","properties":{"items":{"type":"array","items":{"type":"object","description":"A work order as the technician's-day list shows it.","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","description":"The spine row's current version (`_shared.ts`'s server-owned `row_version`, guarded by migration 0385's trigger). A client presents this back as `expectedRowVersion` on a governed write; a stale value is a 409, never a silent last-write-wins.","minimum":1},"number":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"summary":{"type":"string","nullable":true},"serviceSiteId":{"type":"string","format":"uuid","nullable":true},"scheduledStart":{"type":"string","format":"date-time","nullable":true},"scheduledEnd":{"type":"string","format":"date-time","nullable":true}},"required":["id","rowVersion","number","status","priority","summary","serviceSiteId","scheduledStart","scheduledEnd"],"additionalProperties":false}},"nextCursor":{"type":"string","nullable":true,"description":"Opaque cursor for the next page, or null when no more rows exist."},"limit":{"type":"integer","description":"The page size actually applied."}},"required":["items","nextCursor","limit"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"read","x-thermal-area":"dispatch","x-thermal-pagination":{"style":"cursor","defaultPageSize":25,"maxPageSize":100,"sortKeys":["scheduledStart","id"]},"x-thermal-examples":[{"name":"today","request":{"scope":"today","limit":25}},{"name":"open-page-two","request":{"scope":"open","limit":50,"cursor":"eyJrIjoxfQ"}}]}},"/work-orders/{id}":{"get":{"operationId":"work_order.get","summary":"Get one work order with customer, site, equipment and appointments","description":"The work-order detail surface. Returns the spine context a technician needs — customer, service site, installed equipment, and every non-cancelled appointment. This is the operation the legacy `/api/v1/work-orders/{id}` route is the compatibility shape of.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The work order id.","schema":{"type":"string","format":"uuid"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"A work order with its customer, service site, equipment and appointments — the detail surface M2's MOB-SLICE opens.","properties":{"id":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","description":"The spine row's current version (`_shared.ts`'s server-owned `row_version`, guarded by migration 0385's trigger). A client presents this back as `expectedRowVersion` on a governed write; a stale value is a 409, never a silent last-write-wins.","minimum":1},"number":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"jobType":{"type":"string","nullable":true},"summary":{"type":"string","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"customer":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"serviceSite":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","nullable":true},"addressLine1":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"state":{"type":"string","nullable":true},"zip":{"type":"string","nullable":true}},"required":["id","label","addressLine1","city","state","zip"],"additionalProperties":false},"equipment":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","nullable":true},"make":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"serial":{"type":"string","nullable":true}},"required":["id","type","make","model","serial"],"additionalProperties":false},"appointments":{"type":"array","items":{"type":"object","description":"One visit on a work order. A work order can have several (ADR-0005), so this array never lies about a single-visit shape.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"assignedUserId":{"type":"string","format":"uuid","nullable":true}},"required":["id","status","scheduledStart","scheduledEnd","assignedUserId"],"additionalProperties":false}},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","rowVersion","number","status","priority","jobType","summary","completedAt","customer","serviceSite","equipment","appointments","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"low","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":false,"x-thermal-sensitive-read-allowlisted":true,"x-thermal-side-effect":"read","x-thermal-area":"dispatch","x-thermal-examples":[{"name":"one-work-order","request":{"id":"00000000-0000-4000-8000-000000000001"}}]}},"/work-orders/{id}/assign":{"post":{"operationId":"work_order.assign","summary":"Assign a technician to a work order","description":"Assigns (or reassigns) a technician to a work order through the `work_order.assign` registry action — the same door the dispatch board uses. Placement blocks, certification gates and phase gates are re-checked server-side; an unacknowledged warning or an ungated override is refused, never applied. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's assignment after the governed write.","properties":{"id":{"type":"string","format":"uuid"},"technicianId":{"type":"string","format":"uuid"},"from":{"type":"string","description":"The work order's status before the assignment."},"to":{"type":"string","description":"The work order's status after the assignment."},"technicianOnLeave":{"type":"boolean","description":"True when the assigned technician is on leave — warn-but-allow, never a block."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","technicianId","from","to","technicianOnLeave","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"assign a technician","request":{"technicianId":"77777777-7777-4777-8777-777777777777"}}]}},"/work-orders/{id}/assign/approve":{"post":{"operationId":"work_order.assign.approve","summary":"Assign a technician to a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's assignment after the governed write.","properties":{"id":{"type":"string","format":"uuid"},"technicianId":{"type":"string","format":"uuid"},"from":{"type":"string","description":"The work order's status before the assignment."},"to":{"type":"string","description":"The work order's status after the assignment."},"technicianOnLeave":{"type":"boolean","description":"True when the assigned technician is on leave — warn-but-allow, never a block."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","technicianId","from","to","technicianOnLeave","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"assign a technician","request":{"technicianId":"77777777-7777-4777-8777-777777777777"}}]}},"/work-orders/{id}/assign/preview":{"post":{"operationId":"work_order.assign.preview","summary":"Assign a technician to a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"assign a technician","request":{"technicianId":"77777777-7777-4777-8777-777777777777"}}]}},"/work-orders/{id}/attached-equipment":{"post":{"operationId":"equipment.attach_to_work_order","summary":"Attach an existing unit to a work order","description":"Links an equipment record that already sits at the job's service site to the work order (`work_orders.equipment_id`). Wraps the tech-portal `attachEquipmentToWO` writer, whose service-site guard is what keeps the two from drifting apart. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order after the attach, and the row version it produced.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"equipmentId":{"type":"string","format":"uuid"}},"required":["id","rowVersion","replayed","equipmentId"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"attach the unit the tech scanned","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","expectedRowVersion":3}}]}},"/work-orders/{id}/attached-equipment/approve":{"post":{"operationId":"equipment.attach_to_work_order.approve","summary":"Attach an existing unit to a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order after the attach, and the row version it produced.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"equipmentId":{"type":"string","format":"uuid"}},"required":["id","rowVersion","replayed","equipmentId"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"attach the unit the tech scanned","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","expectedRowVersion":3}}]}},"/work-orders/{id}/attached-equipment/preview":{"post":{"operationId":"equipment.attach_to_work_order.preview","summary":"Attach an existing unit to a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"attach the unit the tech scanned","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","expectedRowVersion":3}}]}},"/work-orders/{id}/attachments":{"post":{"operationId":"work_order.upload_attachment","summary":"Record a photo captured against a work order","description":"The terminal half of the two-step direct upload the mobile field app uses. `POST {path}/prepare-upload` mints the object key and its scoped client token; the caller PUTs the bytes straight to storage; this call presents the declaration back, the server re-HEADs and re-sniffs the stored object, and the attachment row is written. One-phase: every delivery carries the idempotency key the outbox minted at enqueue, so a retried queue entry produces no second row. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment row the verified upload produced.","properties":{"id":{"type":"string","format":"uuid","description":"The attachment row's id."},"workOrderId":{"type":"string","format":"uuid"},"url":{"type":"string","description":"The stored object's public URL."},"pathname":{"type":"string"},"slot":{"type":"string","enum":["before","after","other"]},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_attachments carries no row_version (migration 0385 covers the six spine tables), which the handler declares as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","url","pathname","slot","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"a before photo, completing a prepared direct upload","request":{"id":"33333333-3333-4333-8333-333333333333","fileName":"nameplate.jpg","contentType":"image/jpeg","sizeBytes":184320,"pathname":"wo/11111111-1111-4111-8111-111111111111/33333333-3333-4333-8333-333333333333/44444444-4444-4444-8444-444444444444.jpg","slot":"before"}}]}},"/work-orders/{id}/attachments/{attachmentId}":{"post":{"operationId":"work_order.delete_attachment","summary":"Remove a photo from a work order","description":"Removes one work-order photo and, best-effort, its stored object. Org-scoped and subject to the same appointment/terminal-status guard every attachment mutation shares. One-phase and idempotent: a duplicate delivery under the same key replays the stored result and runs no second delete. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"description":"The attachmentId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment that was removed.","properties":{"id":{"type":"string","format":"uuid","description":"The attachment row's id."},"workOrderId":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","description":"True when this delivery removed the row. A replayed delivery reports the stored result and runs no second delete."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null — see `work_order.upload_attachment`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","deleted","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"remove a mis-captured photo","request":{"id":"33333333-3333-4333-8333-333333333333","attachmentId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/attachments/{attachmentId}/approve":{"post":{"operationId":"work_order.delete_attachment.approve","summary":"Remove a photo from a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"description":"The attachmentId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment that was removed.","properties":{"id":{"type":"string","format":"uuid","description":"The attachment row's id."},"workOrderId":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","description":"True when this delivery removed the row. A replayed delivery reports the stored result and runs no second delete."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null — see `work_order.upload_attachment`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","deleted","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"remove a mis-captured photo","request":{"id":"33333333-3333-4333-8333-333333333333","attachmentId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/attachments/{attachmentId}/preview":{"post":{"operationId":"work_order.delete_attachment.preview","summary":"Remove a photo from a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"description":"The attachmentId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"remove a mis-captured photo","request":{"id":"33333333-3333-4333-8333-333333333333","attachmentId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/attachments/approve":{"post":{"operationId":"work_order.upload_attachment.approve","summary":"Record a photo captured against a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment row the verified upload produced.","properties":{"id":{"type":"string","format":"uuid","description":"The attachment row's id."},"workOrderId":{"type":"string","format":"uuid"},"url":{"type":"string","description":"The stored object's public URL."},"pathname":{"type":"string"},"slot":{"type":"string","enum":["before","after","other"]},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_attachments carries no row_version (migration 0385 covers the six spine tables), which the handler declares as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","url","pathname","slot","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"a before photo, completing a prepared direct upload","request":{"id":"33333333-3333-4333-8333-333333333333","fileName":"nameplate.jpg","contentType":"image/jpeg","sizeBytes":184320,"pathname":"wo/11111111-1111-4111-8111-111111111111/33333333-3333-4333-8333-333333333333/44444444-4444-4444-8444-444444444444.jpg","slot":"before"}}]}},"/work-orders/{id}/attachments/prepare-upload":{"post":{"operationId":"work_order.upload_attachment.prepare-upload","summary":"Mint the object key and scoped client token for one work-order photo","description":"A preparatory step of the governed write. Authorized like any other request; causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[]}},"/work-orders/{id}/attachments/preview":{"post":{"operationId":"work_order.upload_attachment.preview","summary":"Record a photo captured against a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_attachments","x-thermal-examples":[{"name":"a before photo, completing a prepared direct upload","request":{"id":"33333333-3333-4333-8333-333333333333","fileName":"nameplate.jpg","contentType":"image/jpeg","sizeBytes":184320,"pathname":"wo/11111111-1111-4111-8111-111111111111/33333333-3333-4333-8333-333333333333/44444444-4444-4444-8444-444444444444.jpg","slot":"before"}}]}},"/work-orders/{id}/charge":{"post":{"operationId":"chargeWorkOrder","summary":"Open a hosted Stripe Checkout Session for this job's balance","description":"Never queued for offline replay — a card charge needs the network by definition. An Idempotency-Key is REQUIRED and is handed to Stripe as its own idempotency key, so a client retry after a network timeout returns the first Checkout Session and therefore the one PaymentIntent, even when the retry arrives before the first attempt's record landed. A keyless request is refused with 400 before anything reaches Stripe. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The hosted Stripe Checkout Session for this job's outstanding balance. `outcome` is the writer's own typed answer, preserved rather than re-shaped: a `not_wired`/`nothing_due`/`not_payable`/`consolidated` answer is an ANSWER (issue 849's design), so the field client renders its existing explanation instead of treating a degraded perimeter as a failure.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["checkout","not_wired","nothing_due","not_payable","consolidated"]},"checkoutUrl":{"type":"string","nullable":true,"description":"Present only on `checkout`. The URL the customer pays at."},"invoiceId":{"type":"string","format":"uuid","nullable":true},"amountCents":{"type":"integer","nullable":true,"description":"Server-resolved balance the session was priced at. Present only on `checkout`."},"stripeIdempotencyKey":{"type":"string","nullable":true,"description":"The capture-idempotency key this collection is pinned to (`fieldChargeIdempotencyKey`). Stable across retries, which is what makes a duplicated charge one PaymentIntent rather than two."},"invoiceStatus":{"type":"string","nullable":true,"description":"Present only on `not_payable`: the status that refused the charge."},"workOrderCount":{"type":"integer","nullable":true,"description":"Present only on `consolidated`: how many jobs share the bill the office collects."}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"charge the outstanding balance","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/charge/approve":{"post":{"operationId":"chargeWorkOrder.approve","summary":"Open a hosted Stripe Checkout Session for this job's balance — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The hosted Stripe Checkout Session for this job's outstanding balance. `outcome` is the writer's own typed answer, preserved rather than re-shaped: a `not_wired`/`nothing_due`/`not_payable`/`consolidated` answer is an ANSWER (issue 849's design), so the field client renders its existing explanation instead of treating a degraded perimeter as a failure.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["checkout","not_wired","nothing_due","not_payable","consolidated"]},"checkoutUrl":{"type":"string","nullable":true,"description":"Present only on `checkout`. The URL the customer pays at."},"invoiceId":{"type":"string","format":"uuid","nullable":true},"amountCents":{"type":"integer","nullable":true,"description":"Server-resolved balance the session was priced at. Present only on `checkout`."},"stripeIdempotencyKey":{"type":"string","nullable":true,"description":"The capture-idempotency key this collection is pinned to (`fieldChargeIdempotencyKey`). Stable across retries, which is what makes a duplicated charge one PaymentIntent rather than two."},"invoiceStatus":{"type":"string","nullable":true,"description":"Present only on `not_payable`: the status that refused the charge."},"workOrderCount":{"type":"integer","nullable":true,"description":"Present only on `consolidated`: how many jobs share the bill the office collects."}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"charge the outstanding balance","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/charge/preview":{"post":{"operationId":"chargeWorkOrder.preview","summary":"Open a hosted Stripe Checkout Session for this job's balance — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"charge the outstanding balance","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/deposits":{"post":{"operationId":"takeFieldDeposit","summary":"Take a deposit on a visit before the job is completed","description":"Before completion, the technician on an en_route, arrived or in_progress visit takes a deposit (up to what is left of the job's current total) by cash, cheque, card or pay link. It is booked on the job's deposit invoice — never the job's own bill, and the job's status is unchanged — and credited to the job's invoice when that is issued. An Idempotency-Key is REQUIRED and is the deposit's key: a replay records nothing new. `cash`/`check` may be queued offline; `card`/`pay_link` need the network. `GET /field/work-orders/{id}/balance` reports `mode: deposit`, the visit to name and the remaining cap. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The deposit's result (issue 5199). `recorded` for cash/cheque (one payment on the job's deposit invoice); `checkout` for card (the session the customer pays in); `sent` / `no_recipient` for a pay link; `not_wired` when the card or delivery perimeter is unconfigured (nothing was created); `nothing_due` when this key's deposit is already settled. A refusal (visit not yours or not on site, amount above what is left, no billable lines, office approval required) is an error response, not an outcome.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["recorded","checkout","sent","no_recipient","not_wired","nothing_due"]},"invoiceId":{"type":"string","format":"uuid","nullable":true,"description":"The job's deposit invoice (never the job's own bill)."},"amountCents":{"type":"integer","nullable":true,"description":"The deposit amount: recorded (`recorded`) or what the session charges (`checkout`)."},"paymentId":{"type":"string","format":"uuid","nullable":true,"description":"Present only on `recorded`."},"checkoutUrl":{"type":"string","nullable":true,"description":"Present only on `checkout`."},"stripeIdempotencyKey":{"type":"string","nullable":true,"description":"Present only on `checkout`."},"sms":{"type":"boolean","nullable":true,"description":"Present only on `sent`."},"email":{"type":"boolean","nullable":true,"description":"Present only on `sent`."}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"cash deposit on site","request":{"id":"33333333-3333-4333-8333-333333333333","visitId":"44444444-4444-4444-8444-444444444444","amountCents":25000,"method":"cash"}},{"name":"card deposit for the full job (pay at the door)","request":{"id":"33333333-3333-4333-8333-333333333333","visitId":"44444444-4444-4444-8444-444444444444","amountCents":41250,"method":"card"}}]}},"/work-orders/{id}/deposits/approve":{"post":{"operationId":"takeFieldDeposit.approve","summary":"Take a deposit on a visit before the job is completed — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The deposit's result (issue 5199). `recorded` for cash/cheque (one payment on the job's deposit invoice); `checkout` for card (the session the customer pays in); `sent` / `no_recipient` for a pay link; `not_wired` when the card or delivery perimeter is unconfigured (nothing was created); `nothing_due` when this key's deposit is already settled. A refusal (visit not yours or not on site, amount above what is left, no billable lines, office approval required) is an error response, not an outcome.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["recorded","checkout","sent","no_recipient","not_wired","nothing_due"]},"invoiceId":{"type":"string","format":"uuid","nullable":true,"description":"The job's deposit invoice (never the job's own bill)."},"amountCents":{"type":"integer","nullable":true,"description":"The deposit amount: recorded (`recorded`) or what the session charges (`checkout`)."},"paymentId":{"type":"string","format":"uuid","nullable":true,"description":"Present only on `recorded`."},"checkoutUrl":{"type":"string","nullable":true,"description":"Present only on `checkout`."},"stripeIdempotencyKey":{"type":"string","nullable":true,"description":"Present only on `checkout`."},"sms":{"type":"boolean","nullable":true,"description":"Present only on `sent`."},"email":{"type":"boolean","nullable":true,"description":"Present only on `sent`."}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"cash deposit on site","request":{"id":"33333333-3333-4333-8333-333333333333","visitId":"44444444-4444-4444-8444-444444444444","amountCents":25000,"method":"cash"}},{"name":"card deposit for the full job (pay at the door)","request":{"id":"33333333-3333-4333-8333-333333333333","visitId":"44444444-4444-4444-8444-444444444444","amountCents":41250,"method":"card"}}]}},"/work-orders/{id}/deposits/preview":{"post":{"operationId":"takeFieldDeposit.preview","summary":"Take a deposit on a visit before the job is completed — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"cash deposit on site","request":{"id":"33333333-3333-4333-8333-333333333333","visitId":"44444444-4444-4444-8444-444444444444","amountCents":25000,"method":"cash"}},{"name":"card deposit for the full job (pay at the door)","request":{"id":"33333333-3333-4333-8333-333333333333","visitId":"44444444-4444-4444-8444-444444444444","amountCents":41250,"method":"card"}}]}},"/work-orders/{id}/draft-feedback":{"post":{"operationId":"work_order.record_draft_feedback","summary":"Rate the drafted wrap summary","description":"Stores the technician's rating of the drafted summary. A null rating is a CLEARED rating — tapping the active thumb again — and succeeds with `effect: \"no_effect\"` and nothing written, which is the deliberate outcome rather than an error. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"ai_draft_feedback","x-thermal-examples":[{"name":"thumbs down with a reason","request":{"id":"33333333-3333-4333-8333-333333333333","rating":"down","reason":"wrong_details"}},{"name":"cleared rating (no effect)","request":{"id":"33333333-3333-4333-8333-333333333333","rating":null}}]}},"/work-orders/{id}/draft-feedback/approve":{"post":{"operationId":"work_order.record_draft_feedback.approve","summary":"Rate the drafted wrap summary — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"ai_draft_feedback","x-thermal-examples":[{"name":"thumbs down with a reason","request":{"id":"33333333-3333-4333-8333-333333333333","rating":"down","reason":"wrong_details"}},{"name":"cleared rating (no effect)","request":{"id":"33333333-3333-4333-8333-333333333333","rating":null}}]}},"/work-orders/{id}/draft-feedback/preview":{"post":{"operationId":"work_order.record_draft_feedback.preview","summary":"Rate the drafted wrap summary — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"ai_draft_feedback","x-thermal-examples":[{"name":"thumbs down with a reason","request":{"id":"33333333-3333-4333-8333-333333333333","rating":"down","reason":"wrong_details"}},{"name":"cleared rating (no effect)","request":{"id":"33333333-3333-4333-8333-333333333333","rating":null}}]}},"/work-orders/{id}/equipment":{"post":{"operationId":"equipment.create_for_work_order","summary":"Create a unit at the job's site and attach it","description":"Inserts a confirmed equipment record at the work order's service site and attaches it in the same transaction. Wraps the tech-portal `createEquipmentForWO` writer unchanged. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The equipment record the write created.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"confirm a scanned nameplate","request":{"id":"33333333-3333-4333-8333-333333333333","type":"rtu","make":"Carrier","model":"48TC","serial":"1234X"}}]}},"/work-orders/{id}/equipment-attachments/{attachmentId}/delete":{"post":{"operationId":"equipment_attachment.delete_for_work_order","summary":"Remove an attachment from the unit on this job","description":"Removes one attachment the tech added, and its Blob object. Wraps `deleteEquipmentAttachmentWO` unchanged. A duplicate delivery under the same idempotency key replays the first result rather than reporting the row as already gone. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"description":"The attachmentId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment the write removed.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"removed":{"type":"boolean","description":"False when there was nothing to remove — an already-removed row, or an id this caller cannot see. A duplicate delivery is a no-op, never an error."}},"required":["id","rowVersion","replayed","removed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"remove a photo added by mistake","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","attachmentId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/equipment-attachments/{attachmentId}/delete/approve":{"post":{"operationId":"equipment_attachment.delete_for_work_order.approve","summary":"Remove an attachment from the unit on this job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"description":"The attachmentId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment the write removed.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"removed":{"type":"boolean","description":"False when there was nothing to remove — an already-removed row, or an id this caller cannot see. A duplicate delivery is a no-op, never an error."}},"required":["id","rowVersion","replayed","removed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"remove a photo added by mistake","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","attachmentId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/equipment-attachments/{attachmentId}/delete/preview":{"post":{"operationId":"equipment_attachment.delete_for_work_order.preview","summary":"Remove an attachment from the unit on this job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"attachmentId","in":"path","required":true,"description":"The attachmentId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"remove a photo added by mistake","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","attachmentId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/equipment-attachments/file":{"post":{"operationId":"equipment_attachment.upload_for_work_order","summary":"Attach a photo or PDF to the unit on this job","description":"The two-step direct upload issue 3556 defines: `prepare-upload` mints a short-lived token for one exact Blob pathname, the client PUTs the bytes there, and this route verifies the object and records the row through `uploadEquipmentAttachmentWO` unchanged. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment row the upload produced.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"a nameplate photo from the field","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","fileName":"plate.jpg","contentType":"image/jpeg","sizeBytes":220144}}]}},"/work-orders/{id}/equipment-attachments/file/approve":{"post":{"operationId":"equipment_attachment.upload_for_work_order.approve","summary":"Attach a photo or PDF to the unit on this job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The attachment row the upload produced.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"a nameplate photo from the field","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","fileName":"plate.jpg","contentType":"image/jpeg","sizeBytes":220144}}]}},"/work-orders/{id}/equipment-attachments/file/prepare-upload":{"post":{"operationId":"equipment_attachment.upload_for_work_order.prepare-upload","summary":"Mint a one-pathname upload capability for an equipment attachment","description":"A preparatory step of the governed write. Authorized like any other request; causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[]}},"/work-orders/{id}/equipment-attachments/file/preview":{"post":{"operationId":"equipment_attachment.upload_for_work_order.preview","summary":"Attach a photo or PDF to the unit on this job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"a nameplate photo from the field","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","fileName":"plate.jpg","contentType":"image/jpeg","sizeBytes":220144}}]}},"/work-orders/{id}/equipment-attachments/link":{"post":{"operationId":"equipment_attachment.add_link_for_work_order","summary":"Attach an external link to the unit on this job","description":"Records a link attachment against the unit attached to this work order. Wraps `addEquipmentAttachmentLinkWO` unchanged, including its http(s)-only URL rule. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The link attachment row the write produced.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"the manufacturer's manual","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","url":"https://example.com/manual.pdf","label":"Install manual"}}]}},"/work-orders/{id}/equipment-attachments/link/approve":{"post":{"operationId":"equipment_attachment.add_link_for_work_order.approve","summary":"Attach an external link to the unit on this job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The link attachment row the write produced.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"the manufacturer's manual","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","url":"https://example.com/manual.pdf","label":"Install manual"}}]}},"/work-orders/{id}/equipment-attachments/link/preview":{"post":{"operationId":"equipment_attachment.add_link_for_work_order.preview","summary":"Attach an external link to the unit on this job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"equipment_attachments","x-thermal-examples":[{"name":"the manufacturer's manual","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","url":"https://example.com/manual.pdf","label":"Install manual"}}]}},"/work-orders/{id}/equipment-nameplate-scan":{"post":{"operationId":"equipment.scan_nameplate_for_work_order","summary":"Replay a captured nameplate photo for a work order","description":"The offline-queue replay path: extracts the nameplate, always persists the photo, and either creates the unit or records review flags against the one already attached. Wraps `scanNameplateWOQueued` unchanged; saved values are never overwritten. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The unit the replay resolved to, and whether it was created or reconciled.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"created":{"type":"boolean"}},"required":["id","rowVersion","replayed","created"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"replay a queued capture","request":{"id":"33333333-3333-4333-8333-333333333333","nameplate":{"fileName":"plate.jpg","contentType":"image/jpeg","dataBase64":"<base64>"}}}]}},"/work-orders/{id}/equipment-nameplate-scan/approve":{"post":{"operationId":"equipment.scan_nameplate_for_work_order.approve","summary":"Replay a captured nameplate photo for a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The unit the replay resolved to, and whether it was created or reconciled.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"created":{"type":"boolean"}},"required":["id","rowVersion","replayed","created"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"replay a queued capture","request":{"id":"33333333-3333-4333-8333-333333333333","nameplate":{"fileName":"plate.jpg","contentType":"image/jpeg","dataBase64":"<base64>"}}}]}},"/work-orders/{id}/equipment-nameplate-scan/preview":{"post":{"operationId":"equipment.scan_nameplate_for_work_order.preview","summary":"Replay a captured nameplate photo for a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"replay a queued capture","request":{"id":"33333333-3333-4333-8333-333333333333","nameplate":{"fileName":"plate.jpg","contentType":"image/jpeg","dataBase64":"<base64>"}}}]}},"/work-orders/{id}/equipment/approve":{"post":{"operationId":"equipment.create_for_work_order.approve","summary":"Create a unit at the job's site and attach it — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The equipment record the write created.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"confirm a scanned nameplate","request":{"id":"33333333-3333-4333-8333-333333333333","type":"rtu","make":"Carrier","model":"48TC","serial":"1234X"}}]}},"/work-orders/{id}/equipment/preview":{"post":{"operationId":"equipment.create_for_work_order.preview","summary":"Create a unit at the job's site and attach it — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"confirm a scanned nameplate","request":{"id":"33333333-3333-4333-8333-333333333333","type":"rtu","make":"Carrier","model":"48TC","serial":"1234X"}}]}},"/work-orders/{id}/field-requests/follow-up-visit":{"post":{"operationId":"createFieldRequest:follow_up_visit","summary":"Ask dispatch for another trip to this job","description":"Files a pending `follow_up_visit` field request for dispatch review. It never schedules the visit — only a dispatch review does that. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pending field request this call filed, or the still-pending one it updated in place.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_requests` row."},"workOrderId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["reschedule","recommend_work","follow_up_visit","needs_parts"]},"status":{"type":"string","enum":["pending"],"description":"Always `pending`: only a dispatch review moves it."},"created":{"type":"boolean","description":"False when a same-key request was already pending and this call updated its payload in place (upsert-on-resubmit)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","type","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"needs another trip","request":{"id":"33333333-3333-4333-8333-333333333333","priority":"emergency","payload":{"reason":"Compressor part is on order","suggestedTimeframe":"this_week","sameTechPreferred":true,"outstandingWork":"Swap the compressor and recommission"}}}]}},"/work-orders/{id}/field-requests/follow-up-visit/approve":{"post":{"operationId":"createFieldRequest:follow_up_visit.approve","summary":"Ask dispatch for another trip to this job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pending field request this call filed, or the still-pending one it updated in place.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_requests` row."},"workOrderId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["reschedule","recommend_work","follow_up_visit","needs_parts"]},"status":{"type":"string","enum":["pending"],"description":"Always `pending`: only a dispatch review moves it."},"created":{"type":"boolean","description":"False when a same-key request was already pending and this call updated its payload in place (upsert-on-resubmit)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","type","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"needs another trip","request":{"id":"33333333-3333-4333-8333-333333333333","priority":"emergency","payload":{"reason":"Compressor part is on order","suggestedTimeframe":"this_week","sameTechPreferred":true,"outstandingWork":"Swap the compressor and recommission"}}}]}},"/work-orders/{id}/field-requests/follow-up-visit/preview":{"post":{"operationId":"createFieldRequest:follow_up_visit.preview","summary":"Ask dispatch for another trip to this job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"needs another trip","request":{"id":"33333333-3333-4333-8333-333333333333","priority":"emergency","payload":{"reason":"Compressor part is on order","suggestedTimeframe":"this_week","sameTechPreferred":true,"outstandingWork":"Swap the compressor and recommission"}}}]}},"/work-orders/{id}/field-requests/recommend-work":{"post":{"operationId":"createFieldRequest","summary":"Capture recommended work for the office to quote","description":"Files a pending `recommend_work` field request for office review. It creates no proposal, no quote and no work order. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pending field request this call filed, or the still-pending one it updated in place.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_requests` row."},"workOrderId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["reschedule","recommend_work","follow_up_visit","needs_parts"]},"status":{"type":"string","enum":["pending"],"description":"Always `pending`: only a dispatch review moves it."},"created":{"type":"boolean","description":"False when a same-key request was already pending and this call updated its payload in place (upsert-on-resubmit)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","type","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"recommend a replacement","request":{"id":"33333333-3333-4333-8333-333333333333","payload":{"recommendationType":"replacement","narrative":"Heat exchanger is cracked; unit is 19 years old.","ballparkCents":850000}}}]}},"/work-orders/{id}/field-requests/recommend-work/approve":{"post":{"operationId":"createFieldRequest.approve","summary":"Capture recommended work for the office to quote — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pending field request this call filed, or the still-pending one it updated in place.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_requests` row."},"workOrderId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["reschedule","recommend_work","follow_up_visit","needs_parts"]},"status":{"type":"string","enum":["pending"],"description":"Always `pending`: only a dispatch review moves it."},"created":{"type":"boolean","description":"False when a same-key request was already pending and this call updated its payload in place (upsert-on-resubmit)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","type","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"recommend a replacement","request":{"id":"33333333-3333-4333-8333-333333333333","payload":{"recommendationType":"replacement","narrative":"Heat exchanger is cracked; unit is 19 years old.","ballparkCents":850000}}}]}},"/work-orders/{id}/field-requests/recommend-work/preview":{"post":{"operationId":"createFieldRequest.preview","summary":"Capture recommended work for the office to quote — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"recommend a replacement","request":{"id":"33333333-3333-4333-8333-333333333333","payload":{"recommendationType":"replacement","narrative":"Heat exchanger is cracked; unit is 19 years old.","ballparkCents":850000}}}]}},"/work-orders/{id}/field-requests/reschedule":{"post":{"operationId":"createFieldRequest:reschedule","summary":"Ask dispatch to move a scheduled visit","description":"Files a pending `reschedule` field request for dispatch review. It never moves the appointment — only a dispatch review does that. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pending field request this call filed, or the still-pending one it updated in place.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_requests` row."},"workOrderId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["reschedule","recommend_work","follow_up_visit","needs_parts"]},"status":{"type":"string","enum":["pending"],"description":"Always `pending`: only a dispatch review moves it."},"created":{"type":"boolean","description":"False when a same-key request was already pending and this call updated its payload in place (upsert-on-resubmit)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","type","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"reschedule this visit","request":{"id":"33333333-3333-4333-8333-333333333333","appointmentId":"44444444-4444-4444-8444-444444444444","payload":{"reason":"Customer is not on site","preferredWindow":"morning"}}}]}},"/work-orders/{id}/field-requests/reschedule/approve":{"post":{"operationId":"createFieldRequest:reschedule.approve","summary":"Ask dispatch to move a scheduled visit — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The pending field request this call filed, or the still-pending one it updated in place.","properties":{"id":{"type":"string","format":"uuid","description":"The `field_requests` row."},"workOrderId":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["reschedule","recommend_work","follow_up_visit","needs_parts"]},"status":{"type":"string","enum":["pending"],"description":"Always `pending`: only a dispatch review moves it."},"created":{"type":"boolean","description":"False when a same-key request was already pending and this call updated its payload in place (upsert-on-resubmit)."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","type","status","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"reschedule this visit","request":{"id":"33333333-3333-4333-8333-333333333333","appointmentId":"44444444-4444-4444-8444-444444444444","payload":{"reason":"Customer is not on site","preferredWindow":"morning"}}}]}},"/work-orders/{id}/field-requests/reschedule/preview":{"post":{"operationId":"createFieldRequest:reschedule.preview","summary":"Ask dispatch to move a scheduled visit — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"field_requests","x-thermal-examples":[{"name":"reschedule this visit","request":{"id":"33333333-3333-4333-8333-333333333333","appointmentId":"44444444-4444-4444-8444-444444444444","payload":{"reason":"Customer is not on site","preferredWindow":"morning"}}}]}},"/work-orders/{id}/hold":{"post":{"operationId":"work_order.hold","summary":"Put an assigned job on hold","description":"Technician-only hold on an own non-canceled visit. Parts holds use Request parts. Other requires a note. A stale row version is a conflict. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["awaiting_customer","waiting_access","needs_second_tech","other","waiting_parts"]},"note":{"type":"string","maxLength":280},"expectedRowVersion":{"type":"integer","minimum":1}},"required":["reason","expectedRowVersion"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"holdingTag":{"type":"string","nullable":true},"holdingNote":{"type":"string","nullable":true},"rowVersion":{"type":"integer"},"replayed":{"type":"boolean"}},"required":["id","holdingTag","holdingNote","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"waiting for access","request":{"id":"33333333-3333-4333-8333-333333333333","expectedRowVersion":3,"reason":"waiting_access"}}]}},"/work-orders/{id}/hold/approve":{"post":{"operationId":"work_order.hold.approve","summary":"Put an assigned job on hold — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["awaiting_customer","waiting_access","needs_second_tech","other","waiting_parts"]},"note":{"type":"string","maxLength":280},"expectedRowVersion":{"type":"integer","minimum":1}},"required":["reason","expectedRowVersion"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"holdingTag":{"type":"string","nullable":true},"holdingNote":{"type":"string","nullable":true},"rowVersion":{"type":"integer"},"replayed":{"type":"boolean"}},"required":["id","holdingTag","holdingNote","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"waiting for access","request":{"id":"33333333-3333-4333-8333-333333333333","expectedRowVersion":3,"reason":"waiting_access"}}]}},"/work-orders/{id}/hold/preview":{"post":{"operationId":"work_order.hold.preview","summary":"Put an assigned job on hold — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["awaiting_customer","waiting_access","needs_second_tech","other","waiting_parts"]},"note":{"type":"string","maxLength":280},"expectedRowVersion":{"type":"integer","minimum":1}},"required":["reason","expectedRowVersion"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"waiting for access","request":{"id":"33333333-3333-4333-8333-333333333333","expectedRowVersion":3,"reason":"waiting_access"}}]}},"/work-orders/{id}/line-items":{"post":{"operationId":"addPricebookLineItem","summary":"Add a pricebook item as a work-order line item","description":"Adds a flat-rate pricebook item to a work order the caller is assigned to. The unit price is resolved server-side from the catalog (plus the customer's tier) at add-time; no price or amount field is accepted, and a line total is stored, never derived from client input. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The line item as it landed, priced by the server from the catalog at add-time. Current caller visibility applies to first responses and replays.","properties":{"lineItemId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"pricebookItemId":{"type":"string","format":"uuid"},"quantityMilli":{"type":"integer","description":"Quantity in thousandths of a unit, as stored (1.5 → 1500)."},"pricesHidden":{"type":"boolean"},"unitPriceCents":{"type":"integer","nullable":true,"description":"The catalog price resolved server-side at add-time — never a client-supplied value."},"lineTotalCents":{"type":"integer","nullable":true,"description":"unitPriceCents × quantity, stored at add-time."},"approvalStatus":{"type":"string","enum":["pending"],"nullable":true,"description":"`pending` when a negative-money line crossed an approval-rules threshold; null otherwise."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["lineItemId","workOrderId","pricebookItemId","quantityMilli","unitPriceCents","lineTotalCents","approvalStatus","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_line_items","x-thermal-examples":[{"name":"two lengths of line set","request":{"id":"33333333-3333-4333-8333-333333333333","pricebookItemId":"55555555-5555-4555-8555-555555555555","qtyUnits":2,"pricebookTier":"standard"}}]}},"/work-orders/{id}/line-items/{lineItemId}":{"delete":{"operationId":"removeLineItem","summary":"Remove a line item from a work order","description":"Removes one line item from an editable work order the caller is assigned to. A serialized line returns its checked-out unit to stock. Removing generated customer labor is an office billing decision and is refused for a technician. A duplicate delivery of the same intent is a no-op replay, not an error. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"lineItemId","in":"path","required":true,"description":"The lineItemId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The removed line item. A duplicate delivery under the same idempotency key replays this body with `replayed: true` and removes nothing further.","properties":{"lineItemId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"removed":{"type":"boolean"},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["lineItemId","workOrderId","removed","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_line_items","x-thermal-examples":[{"name":"remove the mis-picked part","request":{"id":"33333333-3333-4333-8333-333333333333","lineItemId":"77777777-7777-4777-8777-777777777777"}}]}},"/work-orders/{id}/line-items/{lineItemId}/approve":{"post":{"operationId":"removeLineItem.approve","summary":"Remove a line item from a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"lineItemId","in":"path","required":true,"description":"The lineItemId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The removed line item. A duplicate delivery under the same idempotency key replays this body with `replayed: true` and removes nothing further.","properties":{"lineItemId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"removed":{"type":"boolean"},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["lineItemId","workOrderId","removed","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_line_items","x-thermal-examples":[{"name":"remove the mis-picked part","request":{"id":"33333333-3333-4333-8333-333333333333","lineItemId":"77777777-7777-4777-8777-777777777777"}}]}},"/work-orders/{id}/line-items/{lineItemId}/preview":{"post":{"operationId":"removeLineItem.preview","summary":"Remove a line item from a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"lineItemId","in":"path","required":true,"description":"The lineItemId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_line_items","x-thermal-examples":[{"name":"remove the mis-picked part","request":{"id":"33333333-3333-4333-8333-333333333333","lineItemId":"77777777-7777-4777-8777-777777777777"}}]}},"/work-orders/{id}/line-items/approve":{"post":{"operationId":"addPricebookLineItem.approve","summary":"Add a pricebook item as a work-order line item — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The line item as it landed, priced by the server from the catalog at add-time. Current caller visibility applies to first responses and replays.","properties":{"lineItemId":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"pricebookItemId":{"type":"string","format":"uuid"},"quantityMilli":{"type":"integer","description":"Quantity in thousandths of a unit, as stored (1.5 → 1500)."},"pricesHidden":{"type":"boolean"},"unitPriceCents":{"type":"integer","nullable":true,"description":"The catalog price resolved server-side at add-time — never a client-supplied value."},"lineTotalCents":{"type":"integer","nullable":true,"description":"unitPriceCents × quantity, stored at add-time."},"approvalStatus":{"type":"string","enum":["pending"],"nullable":true,"description":"`pending` when a negative-money line crossed an approval-rules threshold; null otherwise."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["lineItemId","workOrderId","pricebookItemId","quantityMilli","unitPriceCents","lineTotalCents","approvalStatus","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_line_items","x-thermal-examples":[{"name":"two lengths of line set","request":{"id":"33333333-3333-4333-8333-333333333333","pricebookItemId":"55555555-5555-4555-8555-555555555555","qtyUnits":2,"pricebookTier":"standard"}}]}},"/work-orders/{id}/line-items/preview":{"post":{"operationId":"addPricebookLineItem.preview","summary":"Add a pricebook item as a work-order line item — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_line_items","x-thermal-examples":[{"name":"two lengths of line set","request":{"id":"33333333-3333-4333-8333-333333333333","pricebookItemId":"55555555-5555-4555-8555-555555555555","qtyUnits":2,"pricebookTier":"standard"}}]}},"/work-orders/{id}/messages":{"post":{"operationId":"work_order.post_message","summary":"Post an internal staff message on a work order","description":"Adds a message to the work order's internal staff thread (customers never see it), authored by the signed-in user. Technicians may post only on a work order they hold a non-canceled appointment on. One-phase: every delivery carries the idempotency key the outbox minted at enqueue, so a replayed send stores one message. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The message text.","properties":{"body":{"type":"string","description":"1–2000 characters; not blank."}},"required":["body"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The message the write stored.","properties":{"id":{"type":"string","format":"uuid","description":"The work_order_messages row's id."},"workOrderId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"authorName":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string","description":"UTC ISO timestamp with microseconds."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_messages and work_order_message_reads carry no row_version, declared as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","authorUserId","authorName","body","createdAt","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_messages","x-thermal-examples":[{"name":"tell the office a part is on order","request":{"id":"33333333-3333-4333-8333-333333333333","body":"Compressor contactor is on order, back Thursday."}}]}},"/work-orders/{id}/messages/approve":{"post":{"operationId":"work_order.post_message.approve","summary":"Post an internal staff message on a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The message text.","properties":{"body":{"type":"string","description":"1–2000 characters; not blank."}},"required":["body"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The message the write stored.","properties":{"id":{"type":"string","format":"uuid","description":"The work_order_messages row's id."},"workOrderId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"authorName":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string","description":"UTC ISO timestamp with microseconds."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_messages and work_order_message_reads carry no row_version, declared as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","authorUserId","authorName","body","createdAt","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_messages","x-thermal-examples":[{"name":"tell the office a part is on order","request":{"id":"33333333-3333-4333-8333-333333333333","body":"Compressor contactor is on order, back Thursday."}}]}},"/work-orders/{id}/messages/preview":{"post":{"operationId":"work_order.post_message.preview","summary":"Post an internal staff message on a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The message text.","properties":{"body":{"type":"string","description":"1–2000 characters; not blank."}},"required":["body"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_messages","x-thermal-examples":[{"name":"tell the office a part is on order","request":{"id":"33333333-3333-4333-8333-333333333333","body":"Compressor contactor is on order, back Thursday."}}]}},"/work-orders/{id}/messages/read":{"post":{"operationId":"work_order.mark_messages_read","summary":"Mark a work order's staff messages read up to a message","description":"Moves the signed-in user's read boundary on the work order's internal staff thread to the named message's time. The server keeps the greatest boundary, so a stale or replayed write never moves it back. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The newest message the caller has seen in this thread.","properties":{"lastMessageId":{"type":"string","format":"uuid"}},"required":["lastMessageId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's read boundary on the thread after the write.","properties":{"id":{"type":"string","format":"uuid","description":"The work order id."},"workOrderId":{"type":"string","format":"uuid"},"lastMessageId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_messages and work_order_message_reads carry no row_version, declared as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","lastMessageId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_message_reads","x-thermal-examples":[{"name":"the thread was opened","request":{"id":"33333333-3333-4333-8333-333333333333","lastMessageId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/messages/read/approve":{"post":{"operationId":"work_order.mark_messages_read.approve","summary":"Mark a work order's staff messages read up to a message — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The newest message the caller has seen in this thread.","properties":{"lastMessageId":{"type":"string","format":"uuid"}},"required":["lastMessageId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The caller's read boundary on the thread after the write.","properties":{"id":{"type":"string","format":"uuid","description":"The work order id."},"workOrderId":{"type":"string","format":"uuid"},"lastMessageId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_messages and work_order_message_reads carry no row_version, declared as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","lastMessageId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_message_reads","x-thermal-examples":[{"name":"the thread was opened","request":{"id":"33333333-3333-4333-8333-333333333333","lastMessageId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/messages/read/preview":{"post":{"operationId":"work_order.mark_messages_read.preview","summary":"Mark a work order's staff messages read up to a message — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The newest message the caller has seen in this thread.","properties":{"lastMessageId":{"type":"string","format":"uuid"}},"required":["lastMessageId"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_message_reads","x-thermal-examples":[{"name":"the thread was opened","request":{"id":"33333333-3333-4333-8333-333333333333","lastMessageId":"55555555-5555-4555-8555-555555555555"}}]}},"/work-orders/{id}/parts-requests":{"post":{"operationId":"requestNeedsParts","summary":"Request a part for this job","description":"Creates a DRAFT purchase order for the requested part and logs the matching dispatch-review row. It orders nothing: the office reconciles and sends the order. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The draft purchase order the parts request created, and whether the job was put on hold for it.","properties":{"id":{"type":"string","format":"uuid","description":"The `purchase_orders` row, in `draft`."},"workOrderId":{"type":"string","format":"uuid"},"purchaseOrderId":{"type":"string","format":"uuid"},"holdForParts":{"type":"boolean","description":"Whether this call also placed the job on the parts hold."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","purchaseOrderId","holdForParts","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"request a part and hold the job","request":{"id":"33333333-3333-4333-8333-333333333333","pricebookItemId":"55555555-5555-4555-8555-555555555555","quantity":2,"note":"OEM only","holdForParts":true}}]}},"/work-orders/{id}/parts-requests/approve":{"post":{"operationId":"requestNeedsParts.approve","summary":"Request a part for this job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The draft purchase order the parts request created, and whether the job was put on hold for it.","properties":{"id":{"type":"string","format":"uuid","description":"The `purchase_orders` row, in `draft`."},"workOrderId":{"type":"string","format":"uuid"},"purchaseOrderId":{"type":"string","format":"uuid"},"holdForParts":{"type":"boolean","description":"Whether this call also placed the job on the parts hold."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","purchaseOrderId","holdForParts","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"request a part and hold the job","request":{"id":"33333333-3333-4333-8333-333333333333","pricebookItemId":"55555555-5555-4555-8555-555555555555","quantity":2,"note":"OEM only","holdForParts":true}}]}},"/work-orders/{id}/parts-requests/preview":{"post":{"operationId":"requestNeedsParts.preview","summary":"Request a part for this job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"purchase_orders","x-thermal-examples":[{"name":"request a part and hold the job","request":{"id":"33333333-3333-4333-8333-333333333333","pricebookItemId":"55555555-5555-4555-8555-555555555555","quantity":2,"note":"OEM only","holdForParts":true}}]}},"/work-orders/{id}/pay-link":{"post":{"operationId":"fetchWorkOrderPayLink","summary":"Mint this job's signed customer-facing pay URL (online-only read-through)","description":"Signs the work-order-scoped `/pay/wo/{id}` token so the Collect panel's QR and hand-over rails keep working once the technician loses signal. Mutates nothing: the bill is resolved or minted at redemption time, not here. Issue 3565 spells this operation `GET`; `WriteOperationDescriptor.method` is the literal `\"post\"` and `writeRoutesFor` emits `post`, so the verb is pending the registry-driven engine (unit W-3569) — see FIELD_PAYMENT_READ_THROUGH_OPERATIONS. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The customer-facing signed `/pay/wo/{id}` URL for this job. Minting it changes no billing state; the bill is resolved at redemption time.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["ready","not_wired","not_ready","consolidated"]},"payUrl":{"type":"string","nullable":true,"description":"Present only on `ready`."},"reason":{"type":"string","enum":["unassigned","status"],"nullable":true,"description":"Present only on `not_ready`."},"invoiceId":{"type":"string","format":"uuid","nullable":true,"description":"Present only on `consolidated`."},"workOrderCount":{"type":"integer","nullable":true,"description":"Present only on `consolidated`: how many jobs share the bill."}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"fetch the signed pay URL while online","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/pay-link/approve":{"post":{"operationId":"fetchWorkOrderPayLink.approve","summary":"Mint this job's signed customer-facing pay URL (online-only read-through) — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The customer-facing signed `/pay/wo/{id}` URL for this job. Minting it changes no billing state; the bill is resolved at redemption time.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["ready","not_wired","not_ready","consolidated"]},"payUrl":{"type":"string","nullable":true,"description":"Present only on `ready`."},"reason":{"type":"string","enum":["unassigned","status"],"nullable":true,"description":"Present only on `not_ready`."},"invoiceId":{"type":"string","format":"uuid","nullable":true,"description":"Present only on `consolidated`."},"workOrderCount":{"type":"integer","nullable":true,"description":"Present only on `consolidated`: how many jobs share the bill."}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"fetch the signed pay URL while online","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/pay-link/preview":{"post":{"operationId":"fetchWorkOrderPayLink.preview","summary":"Mint this job's signed customer-facing pay URL (online-only read-through) — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"fetch the signed pay URL while online","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/pay-link/send":{"post":{"operationId":"sendPaymentLink","summary":"Send this job's payment link to the customer's billing contact","description":"The same collection as `chargeWorkOrder`, addressed to the customer's own phone or inbox instead of the technician's screen. Live-only: it opens a Checkout Session through the same seam, and a queued send would carry a stale session URL. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The result of addressing this job's collection to the customer's own billing contact. Same typed-answer contract as `chargeWorkOrder`.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["sent","no_recipient","not_wired","nothing_due","not_payable","consolidated"]},"invoiceId":{"type":"string","format":"uuid","nullable":true},"sms":{"type":"boolean","nullable":true,"description":"True when an SMS actually left."},"email":{"type":"boolean","nullable":true,"description":"True when an email actually left."},"invoiceStatus":{"type":"string","nullable":true},"workOrderCount":{"type":"integer","nullable":true}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"send the link to the billing contact","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/pay-link/send-cached":{"post":{"operationId":"sendFetchedPaymentLink","summary":"Send an already-signed pay URL to the customer's billing contact","description":"The one queueable send of the five: the URL was signed while online, so a reconnect replays the dispatch with no signing secret on the device. Idempotency-keyed, so a replay sends nothing a second time. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The result of replaying an already-signed pay URL to the customer's billing contact. The URL is sent verbatim; the figure in the message is priced from the invoice's server-read balance.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["sent","no_recipient","not_wired","nothing_due","not_payable","consolidated"]},"invoiceId":{"type":"string","format":"uuid","nullable":true},"sms":{"type":"boolean","nullable":true},"email":{"type":"boolean","nullable":true},"invoiceStatus":{"type":"string","nullable":true},"workOrderCount":{"type":"integer","nullable":true}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"replay a fetched link on reconnect","request":{"id":"33333333-3333-4333-8333-333333333333","payUrl":"https://app.trythermal.com/pay/wo/33333333-3333-4333-8333-333333333333?token=1758326400000.abc123"}}]}},"/work-orders/{id}/pay-link/send-cached/approve":{"post":{"operationId":"sendFetchedPaymentLink.approve","summary":"Send an already-signed pay URL to the customer's billing contact — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The result of replaying an already-signed pay URL to the customer's billing contact. The URL is sent verbatim; the figure in the message is priced from the invoice's server-read balance.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["sent","no_recipient","not_wired","nothing_due","not_payable","consolidated"]},"invoiceId":{"type":"string","format":"uuid","nullable":true},"sms":{"type":"boolean","nullable":true},"email":{"type":"boolean","nullable":true},"invoiceStatus":{"type":"string","nullable":true},"workOrderCount":{"type":"integer","nullable":true}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"replay a fetched link on reconnect","request":{"id":"33333333-3333-4333-8333-333333333333","payUrl":"https://app.trythermal.com/pay/wo/33333333-3333-4333-8333-333333333333?token=1758326400000.abc123"}}]}},"/work-orders/{id}/pay-link/send-cached/preview":{"post":{"operationId":"sendFetchedPaymentLink.preview","summary":"Send an already-signed pay URL to the customer's billing contact — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"replay a fetched link on reconnect","request":{"id":"33333333-3333-4333-8333-333333333333","payUrl":"https://app.trythermal.com/pay/wo/33333333-3333-4333-8333-333333333333?token=1758326400000.abc123"}}]}},"/work-orders/{id}/pay-link/send/approve":{"post":{"operationId":"sendPaymentLink.approve","summary":"Send this job's payment link to the customer's billing contact — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The result of addressing this job's collection to the customer's own billing contact. Same typed-answer contract as `chargeWorkOrder`.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"outcome":{"type":"string","enum":["sent","no_recipient","not_wired","nothing_due","not_payable","consolidated"]},"invoiceId":{"type":"string","format":"uuid","nullable":true},"sms":{"type":"boolean","nullable":true,"description":"True when an SMS actually left."},"email":{"type":"boolean","nullable":true,"description":"True when an email actually left."},"invoiceStatus":{"type":"string","nullable":true},"workOrderCount":{"type":"integer","nullable":true}},"required":["id","rowVersion","replayed","outcome"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"send the link to the billing contact","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/pay-link/send/preview":{"post":{"operationId":"sendPaymentLink.preview","summary":"Send this job's payment link to the customer's billing contact — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":false,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"invoices","x-thermal-examples":[{"name":"send the link to the billing contact","request":{"id":"33333333-3333-4333-8333-333333333333"}}]}},"/work-orders/{id}/payments":{"post":{"operationId":"recordFieldPayment","summary":"Record a cash or cheque payment collected in the field","description":"Mints or finds the work order's real invoice (the same idempotent core the office invoicing flow calls), records the payment for the invoice's server-read balance, and marks it paid. Queueable: the device's outbox replays it on reconnect under one idempotency key, and a replay is a no-op rather than a second payment row. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The cash/cheque collection's result. `amountCents` is the invoice's server-read balance at collection time — the value written to `payments.amount_cents`, never a figure the caller supplied.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"invoiceId":{"type":"string","format":"uuid"},"amountCents":{"type":"integer","description":"Server-resolved. 0 when the invoice was already settled and this call was a no-op."},"alreadyPaid":{"type":"boolean","description":"True when the invoice was already `paid` and no second payment row was written — the writer's own replay guard, independent of the idempotency store."}},"required":["id","rowVersion","replayed","invoiceId","amountCents","alreadyPaid"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"payments","x-thermal-examples":[{"name":"cash, collected in full on site","request":{"id":"33333333-3333-4333-8333-333333333333","method":"cash"}},{"name":"cheque, with the cheque number","request":{"id":"33333333-3333-4333-8333-333333333333","method":"check","reference":"10428"}}]}},"/work-orders/{id}/payments/approve":{"post":{"operationId":"recordFieldPayment.approve","summary":"Record a cash or cheque payment collected in the field — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The cash/cheque collection's result. `amountCents` is the invoice's server-read balance at collection time — the value written to `payments.amount_cents`, never a figure the caller supplied.","properties":{"id":{"type":"string","format":"uuid","description":"The work order this collection was raised for."},"rowVersion":{"type":"null","description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the invoice is resolved (and on a first collection minted) server-side, so no caller ever read a version to present back."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"invoiceId":{"type":"string","format":"uuid"},"amountCents":{"type":"integer","description":"Server-resolved. 0 when the invoice was already settled and this call was a no-op."},"alreadyPaid":{"type":"boolean","description":"True when the invoice was already `paid` and no second payment row was written — the writer's own replay guard, independent of the idempotency store."}},"required":["id","rowVersion","replayed","invoiceId","amountCents","alreadyPaid"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"payments","x-thermal-examples":[{"name":"cash, collected in full on site","request":{"id":"33333333-3333-4333-8333-333333333333","method":"cash"}},{"name":"cheque, with the cheque number","request":{"id":"33333333-3333-4333-8333-333333333333","method":"check","reference":"10428"}}]}},"/work-orders/{id}/payments/preview":{"post":{"operationId":"recordFieldPayment.preview","summary":"Record a cash or cheque payment collected in the field — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-payments","x-thermal-target-table":"payments","x-thermal-examples":[{"name":"cash, collected in full on site","request":{"id":"33333333-3333-4333-8333-333333333333","method":"cash"}},{"name":"cheque, with the cheque number","request":{"id":"33333333-3333-4333-8333-333333333333","method":"check","reference":"10428"}}]}},"/work-orders/{id}/readings":{"post":{"operationId":"work_order.log_equipment_reading","summary":"Log a diagnostic reading against this job's equipment","description":"Records a meter or gauge reading captured on site, outside any formal inspection. The reading must be for THIS work order's equipment, its type must be one the organization has active, and its unit is resolved server-side from the organization's reading definitions — never supplied by the client. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment_readings","x-thermal-examples":[{"name":"capacitor microfarads","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","readingType":"capacitor_uf","value":42.5}}]}},"/work-orders/{id}/readings/approve":{"post":{"operationId":"work_order.log_equipment_reading.approve","summary":"Log a diagnostic reading against this job's equipment — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment_readings","x-thermal-examples":[{"name":"capacitor microfarads","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","readingType":"capacitor_uf","value":42.5}}]}},"/work-orders/{id}/readings/preview":{"post":{"operationId":"work_order.log_equipment_reading.preview","summary":"Log a diagnostic reading against this job's equipment — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment_readings","x-thermal-examples":[{"name":"capacitor microfarads","request":{"id":"33333333-3333-4333-8333-333333333333","equipmentId":"44444444-4444-4444-8444-444444444444","readingType":"capacitor_uf","value":42.5}}]}},"/work-orders/{id}/resume":{"post":{"operationId":"work_order.resume","summary":"Resume an assigned job","description":"Technician-only release of a job hold, clearing its reason and note. An unheld job is a no-op. A stale row version is a conflict. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expectedRowVersion":{"type":"integer","minimum":1}},"required":["expectedRowVersion"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"holdingTag":{"type":"string","nullable":true},"holdingNote":{"type":"string","nullable":true},"rowVersion":{"type":"integer"},"replayed":{"type":"boolean"}},"required":["id","holdingTag","holdingNote","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"resume","request":{"id":"33333333-3333-4333-8333-333333333333","expectedRowVersion":3}}]}},"/work-orders/{id}/resume/approve":{"post":{"operationId":"work_order.resume.approve","summary":"Resume an assigned job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expectedRowVersion":{"type":"integer","minimum":1}},"required":["expectedRowVersion"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"holdingTag":{"type":"string","nullable":true},"holdingNote":{"type":"string","nullable":true},"rowVersion":{"type":"integer"},"replayed":{"type":"boolean"}},"required":["id","holdingTag","holdingNote","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"resume","request":{"id":"33333333-3333-4333-8333-333333333333","expectedRowVersion":3}}]}},"/work-orders/{id}/resume/preview":{"post":{"operationId":"work_order.resume.preview","summary":"Resume an assigned job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expectedRowVersion":{"type":"integer","minimum":1}},"required":["expectedRowVersion"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"resume","request":{"id":"33333333-3333-4333-8333-333333333333","expectedRowVersion":3}}]}},"/work-orders/{id}/scanned-asset-label":{"post":{"operationId":"equipment.resolve_scanned_asset_label","summary":"Resolve a scanned asset label in the caller's org","description":"Turns a printed asset-label payload into the unit it names, IN THE CALLER'S ORG ONLY, and says whether that unit is the one on this job. Wraps `resolveScannedAssetLabel` unchanged: the token is the only input that crosses the wire and the org comes from the resolved principal, never from the request. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The resolve outcome, in the same three-state shape the tech portal renders.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"ok":{"type":"boolean"},"reason":{"type":"string","enum":["invalid","not_found","not_authorized"],"nullable":true},"equipmentId":{"type":"string","format":"uuid","nullable":true},"label":{"type":"string","nullable":true},"isJobEquipment":{"type":"boolean","nullable":true}},"required":["id","rowVersion","replayed","ok"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"a label scanned on the job","request":{"id":"33333333-3333-4333-8333-333333333333","raw":"https://trythermal.com/p/asset/abc123"}}]}},"/work-orders/{id}/scanned-asset-label/approve":{"post":{"operationId":"equipment.resolve_scanned_asset_label.approve","summary":"Resolve a scanned asset label in the caller's org — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The resolve outcome, in the same three-state shape the tech portal renders.","properties":{"id":{"type":"string"},"rowVersion":{"type":"integer","nullable":true,"description":"The version this write produced, or null for a target this operation does not compare-and-set."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."},"ok":{"type":"boolean"},"reason":{"type":"string","enum":["invalid","not_found","not_authorized"],"nullable":true},"equipmentId":{"type":"string","format":"uuid","nullable":true},"label":{"type":"string","nullable":true},"isJobEquipment":{"type":"boolean","nullable":true}},"required":["id","rowVersion","replayed","ok"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"a label scanned on the job","request":{"id":"33333333-3333-4333-8333-333333333333","raw":"https://trythermal.com/p/asset/abc123"}}]}},"/work-orders/{id}/scanned-asset-label/preview":{"post":{"operationId":"equipment.resolve_scanned_asset_label.preview","summary":"Resolve a scanned asset label in the caller's org — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"equipment","x-thermal-examples":[{"name":"a label scanned on the job","request":{"id":"33333333-3333-4333-8333-333333333333","raw":"https://trythermal.com/p/asset/abc123"}}]}},"/work-orders/{id}/signature":{"post":{"operationId":"work_order.save_signature","summary":"Capture the customer signature on a work order's active visit","description":"Stores the PNG capture in the private signature store and stamps the target appointment's signature_key + signature_sha256 (ADR-0005). A second save REPLACES the stored signature and records the supersession; a duplicate delivery under the same idempotency key produces no second effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The PNG signature and, optionally, the printed signer name. Older clients may omit signerName; supplied names are trimmed and must contain 1–200 characters.","properties":{"signature":{"type":"string","description":"A PNG data URL captured by the field app."},"signerName":{"type":"string","description":"Optional printed signer name. Trimmed before storage; must contain 1–200 characters."}},"required":["signature"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The appointment whose stored signature was replaced.","properties":{"id":{"type":"string","format":"uuid","description":"The target appointment's id."},"workOrderId":{"type":"string","format":"uuid"},"signatureKey":{"type":"string","description":"The private object key the capture was stored under. A re-capture REPLACES this value on the same appointment row and records a `signature_superseded` event carrying the prior key — it never appends a second signature."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_appointments carries no row_version (migration 0385 covers the six spine tables), declared as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","signatureKey","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"capture the customer's signature","request":{"id":"33333333-3333-4333-8333-333333333333","signature":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=","signerName":"Pat Customer"}}]}},"/work-orders/{id}/signature/approve":{"post":{"operationId":"work_order.save_signature.approve","summary":"Capture the customer signature on a work order's active visit — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The PNG signature and, optionally, the printed signer name. Older clients may omit signerName; supplied names are trimmed and must contain 1–200 characters.","properties":{"signature":{"type":"string","description":"A PNG data URL captured by the field app."},"signerName":{"type":"string","description":"Optional printed signer name. Trimmed before storage; must contain 1–200 characters."}},"required":["signature"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The appointment whose stored signature was replaced.","properties":{"id":{"type":"string","format":"uuid","description":"The target appointment's id."},"workOrderId":{"type":"string","format":"uuid"},"signatureKey":{"type":"string","description":"The private object key the capture was stored under. A re-capture REPLACES this value on the same appointment row and records a `signature_superseded` event carrying the prior key — it never appends a second signature."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: work_order_appointments carries no row_version (migration 0385 covers the six spine tables), declared as `rowVersionStrategy: \"none\"`."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","signatureKey","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"capture the customer's signature","request":{"id":"33333333-3333-4333-8333-333333333333","signature":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=","signerName":"Pat Customer"}}]}},"/work-orders/{id}/signature/preview":{"post":{"operationId":"work_order.save_signature.preview","summary":"Capture the customer signature on a work order's active visit — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"The PNG signature and, optionally, the printed signer name. Older clients may omit signerName; supplied names are trimmed and must contain 1–200 characters.","properties":{"signature":{"type":"string","description":"A PNG data URL captured by the field app."},"signerName":{"type":"string","description":"Optional printed signer name. Trimmed before storage; must contain 1–200 characters."}},"required":["signature"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-evidence","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"capture the customer's signature","request":{"id":"33333333-3333-4333-8333-333333333333","signature":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=","signerName":"Pat Customer"}}]}},"/work-orders/{id}/status":{"post":{"operationId":"work_order.update_status","summary":"Set a work order's status","description":"The technician's-day status change. On my way and start work advance the caller's current open visit and return the work-order rollup. No eligible visit, an invalid visit transition, or an unmet start gate returns 409 with work_order_visit_not_held, work_order_visit_transition_refused, or work_order_visit_start_gate respectively. Below the risk threshold this is one-phase for every principal; at or above it, a preview proposal and (for a `flag`-ceiling principal) a human approval are required. Completing open work is refused: a transition into `completed` or `invoiced` from any other status is a 409 with code `work_order_completion_requires_workflow` on both preview and apply, and mints no proposal — a work order is completed by completing its visits, not by setting its status. Moving between `completed` and `invoiced`, or reopening out of them, is unchanged. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's status after the governed write, and the row version it produced.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["unscheduled","scheduled","assigned","en_route","in_progress","completed","invoiced","canceled"]},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","status","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"en route (below threshold, one-phase)","request":{"id":"33333333-3333-4333-8333-333333333333","status":"en_route","expectedRowVersion":3}},{"name":"cancel (at threshold, preview/apply)","request":{"id":"33333333-3333-4333-8333-333333333333","status":"canceled"}}]}},"/work-orders/{id}/status/approve":{"post":{"operationId":"work_order.update_status.approve","summary":"Set a work order's status — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's status after the governed write, and the row version it produced.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["unscheduled","scheduled","assigned","en_route","in_progress","completed","invoiced","canceled"]},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","status","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"en route (below threshold, one-phase)","request":{"id":"33333333-3333-4333-8333-333333333333","status":"en_route","expectedRowVersion":3}},{"name":"cancel (at threshold, preview/apply)","request":{"id":"33333333-3333-4333-8333-333333333333","status":"canceled"}}]}},"/work-orders/{id}/status/preview":{"post":{"operationId":"work_order.update_status.preview","summary":"Set a work order's status — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]},"lastStatusChange":{"type":"object","nullable":true,"description":"Who last changed this work order's status, when, and from what, read from the events ledger. Null when no status event matches the current status.","properties":{"updatedBy":{"type":"object","nullable":true,"description":"The staff user who made the change; null for a non-user or unresolvable actor.","properties":{"userId":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"roleLabel":{"type":"string","nullable":true}},"required":["userId","displayName","roleLabel"],"additionalProperties":false},"updatedAt":{"type":"string","format":"date-time"},"previousStatus":{"type":"string","nullable":true},"note":{"type":"string","nullable":true,"description":"The optional office note recorded with the change; null or absent when there is none."}},"required":["updatedBy","updatedAt","previousStatus"],"additionalProperties":false}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"work-orders","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"en route (below threshold, one-phase)","request":{"id":"33333333-3333-4333-8333-333333333333","status":"en_route","expectedRowVersion":3}},{"name":"cancel (at threshold, preview/apply)","request":{"id":"33333333-3333-4333-8333-333333333333","status":"canceled"}}]}},"/work-orders/{id}/suggested-fix-decision":{"post":{"operationId":"work_order.record_suggested_fix_decision","summary":"Record whether the technician used or dismissed the suggested fix","description":"Appends one durable decision row to the event ledger alongside the card's instant local flip. It never replaces that flip and never gates it — the record exists so an agent-trust surface can say what the technician did with the suggestion. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"events","x-thermal-examples":[{"name":"used the suggested fix","request":{"id":"33333333-3333-4333-8333-333333333333","decision":"accepted","reason":"Capacitor reading matches the suggested failure."}}]}},"/work-orders/{id}/suggested-fix-decision/approve":{"post":{"operationId":"work_order.record_suggested_fix_decision.approve","summary":"Record whether the technician used or dismissed the suggested fix — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"events","x-thermal-examples":[{"name":"used the suggested fix","request":{"id":"33333333-3333-4333-8333-333333333333","decision":"accepted","reason":"Capacitor reading matches the suggested failure."}}]}},"/work-orders/{id}/suggested-fix-decision/preview":{"post":{"operationId":"work_order.record_suggested_fix_decision.preview","summary":"Record whether the technician used or dismissed the suggested fix — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"events","x-thermal-examples":[{"name":"used the suggested fix","request":{"id":"33333333-3333-4333-8333-333333333333","decision":"accepted","reason":"Capacitor reading matches the suggested failure."}}]}},"/work-orders/{id}/summary":{"post":{"operationId":"work_order.update_summary","summary":"Replace the work order's summary","description":"The technician's Wrap-beat summary edit. Refused once the work order is invoiced or canceled — a precondition on the row's current state, reported with its own conflict code so a client can tell it apart from a row-version conflict that a re-read would fix. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's summary after the write, and the row version it produced.","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written"]},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean"}},"required":["id","workOrderId","effect","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"wrap summary edit","request":{"id":"33333333-3333-4333-8333-333333333333","summary":"Replaced the run capacitor; unit cycling normally on departure."}}]}},"/work-orders/{id}/summary/approve":{"post":{"operationId":"work_order.update_summary.approve","summary":"Replace the work order's summary — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The work order's summary after the write, and the row version it produced.","properties":{"id":{"type":"string","format":"uuid"},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written"]},"rowVersion":{"type":"integer","description":"The version this write produced — the value the next compare-and-set must present."},"replayed":{"type":"boolean"}},"required":["id","workOrderId","effect","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"wrap summary edit","request":{"id":"33333333-3333-4333-8333-333333333333","summary":"Replaced the run capacitor; unit cycling normally on departure."}}]}},"/work-orders/{id}/summary/preview":{"post":{"operationId":"work_order.update_summary.preview","summary":"Replace the work order's summary — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_orders","x-thermal-examples":[{"name":"wrap summary edit","request":{"id":"33333333-3333-4333-8333-333333333333","summary":"Replaced the run capacitor; unit cycling normally on departure."}}]}},"/work-orders/{id}/tasks/{taskId}/complete":{"post":{"operationId":"work_order.complete_task","summary":"Complete or re-open a work order's checklist task","description":"Stamps or clears a checklist item's completion. A technician may act only on a work order they hold an assigned, non-canceled appointment on. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"taskId","in":"path","required":true,"description":"The taskId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The checklist task's completion state after the governed write.","properties":{"id":{"type":"string","format":"uuid","description":"The checklist task's id."},"workOrderId":{"type":"string","format":"uuid"},"completed":{"type":"boolean","description":"True when `completed_at` is stamped after this write."},"completedAt":{"type":"string","format":"date-time","nullable":true,"description":"The completion stamp, or null when the task is open."},"completedByUserId":{"type":"string","format":"uuid","nullable":true,"description":"The staff user credited with the completion. Always the acting technician, never a service principal."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","completed","completedAt","completedByUserId","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_checklist_items","x-thermal-examples":[{"name":"complete a checklist item","request":{"id":"33333333-3333-4333-8333-333333333333","taskId":"44444444-4444-4444-8444-444444444444","complete":true}},{"name":"re-open a checklist item","request":{"id":"33333333-3333-4333-8333-333333333333","taskId":"44444444-4444-4444-8444-444444444444","complete":false}}]}},"/work-orders/{id}/tasks/{taskId}/complete/approve":{"post":{"operationId":"work_order.complete_task.approve","summary":"Complete or re-open a work order's checklist task — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"taskId","in":"path","required":true,"description":"The taskId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The checklist task's completion state after the governed write.","properties":{"id":{"type":"string","format":"uuid","description":"The checklist task's id."},"workOrderId":{"type":"string","format":"uuid"},"completed":{"type":"boolean","description":"True when `completed_at` is stamped after this write."},"completedAt":{"type":"string","format":"date-time","nullable":true,"description":"The completion stamp, or null when the task is open."},"completedByUserId":{"type":"string","format":"uuid","nullable":true,"description":"The staff user credited with the completion. Always the acting technician, never a service principal."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","completed","completedAt","completedByUserId","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_checklist_items","x-thermal-examples":[{"name":"complete a checklist item","request":{"id":"33333333-3333-4333-8333-333333333333","taskId":"44444444-4444-4444-8444-444444444444","complete":true}},{"name":"re-open a checklist item","request":{"id":"33333333-3333-4333-8333-333333333333","taskId":"44444444-4444-4444-8444-444444444444","complete":false}}]}},"/work-orders/{id}/tasks/{taskId}/complete/preview":{"post":{"operationId":"work_order.complete_task.preview","summary":"Complete or re-open a work order's checklist task — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"taskId","in":"path","required":true,"description":"The taskId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"work_order_checklist_items","x-thermal-examples":[{"name":"complete a checklist item","request":{"id":"33333333-3333-4333-8333-333333333333","taskId":"44444444-4444-4444-8444-444444444444","complete":true}},{"name":"re-open a checklist item","request":{"id":"33333333-3333-4333-8333-333333333333","taskId":"44444444-4444-4444-8444-444444444444","complete":false}}]}},"/work-orders/{id}/visit-summary-decision":{"post":{"operationId":"work_order.record_visit_summary_decision","summary":"Record whether the technician accepted or dismissed the suggested visit summary","description":"Appends one durable decision row to the event ledger for the pre-visit briefing's suggested visit-summary slice. The card's local flip is instant and is never blocked or reversed by this write; a caller that cannot store the decision should treat the error as non-blocking rather than surfacing it. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"events","x-thermal-examples":[{"name":"dismissed the suggested recap","request":{"id":"33333333-3333-4333-8333-333333333333","decision":"dismissed"}}]}},"/work-orders/{id}/visit-summary-decision/approve":{"post":{"operationId":"work_order.record_visit_summary_decision.approve","summary":"Record whether the technician accepted or dismissed the suggested visit summary — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The record the write produced, and whether an idempotency key replayed it.","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"The written row's id, or null when the operation deliberately wrote nothing."},"workOrderId":{"type":"string","format":"uuid"},"effect":{"type":"string","enum":["written","no_effect"],"description":"`no_effect` is a SUCCESS with nothing stored — a cleared draft rating is the only case."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","effect","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"events","x-thermal-examples":[{"name":"dismissed the suggested recap","request":{"id":"33333333-3333-4333-8333-333333333333","decision":"dismissed"}}]}},"/work-orders/{id}/visit-summary-decision/preview":{"post":{"operationId":"work_order.record_visit_summary_decision.preview","summary":"Record whether the technician accepted or dismissed the suggested visit summary — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"events","x-thermal-examples":[{"name":"dismissed the suggested recap","request":{"id":"33333333-3333-4333-8333-333333333333","decision":"dismissed"}}]}},"/work-orders/{id}/warranty-claims":{"post":{"operationId":"createFieldWarrantyDraftQueued","summary":"Open a warranty claim draft from this job","description":"Opens a DRAFT warranty claim for office review, keyed on the caller's own `clientClaimId` so an offline retry never opens a second one. It approves nothing and submits nothing to a manufacturer. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The warranty claim DRAFT this call opened. Drafting is never approving.","properties":{"id":{"type":"string","format":"uuid","description":"The `warranty_claims` row, in draft."},"workOrderId":{"type":"string","format":"uuid"},"claimId":{"type":"string","format":"uuid"},"idempotentReplay":{"type":"boolean","description":"True when this `clientClaimId` had already opened a draft and the existing claim was returned — the writer's own idempotency, distinct from the transport `replayed`."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","claimId","idempotentReplay","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"warranty_claims","x-thermal-examples":[{"name":"open a draft","request":{"id":"33333333-3333-4333-8333-333333333333","clientClaimId":"66666666-6666-4666-8666-666666666666","description":"Compressor failed inside the 5-year parts warranty."}}]}},"/work-orders/{id}/warranty-claims/approve":{"post":{"operationId":"createFieldWarrantyDraftQueued.approve","summary":"Open a warranty claim draft from this job — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The warranty claim DRAFT this call opened. Drafting is never approving.","properties":{"id":{"type":"string","format":"uuid","description":"The `warranty_claims` row, in draft."},"workOrderId":{"type":"string","format":"uuid"},"claimId":{"type":"string","format":"uuid"},"idempotentReplay":{"type":"boolean","description":"True when this `clientClaimId` had already opened a draft and the existing claim was returned — the writer's own idempotency, distinct from the transport `replayed`."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null for this operation: it appends a new row rather than compare-and-setting an existing one."},"replayed":{"type":"boolean","description":"True when the transport Idempotency-Key replayed a stored result and no second effect ran."}},"required":["id","workOrderId","claimId","idempotentReplay","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"warranty_claims","x-thermal-examples":[{"name":"open a draft","request":{"id":"33333333-3333-4333-8333-333333333333","clientClaimId":"66666666-6666-4666-8666-666666666666","description":"Compressor failed inside the 5-year parts warranty."}}]}},"/work-orders/{id}/warranty-claims/preview":{"post":{"operationId":"createFieldWarrantyDraftQueued.preview","summary":"Open a warranty claim draft from this job — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]},{"oauthClientToken":[]},{"orgApiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"The id the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":false,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-requests","x-thermal-target-table":"warranty_claims","x-thermal-examples":[{"name":"open a draft","request":{"id":"33333333-3333-4333-8333-333333333333","clientClaimId":"66666666-6666-4666-8666-666666666666","description":"Compressor failed inside the 5-year parts warranty."}}]}},"/work-orders/{workOrderId}/auto-schedule":{"post":{"operationId":"dispatch.auto_schedule_work_order","summary":"Create the first appointment window for an unscheduled work order","description":"Runs the `dispatch.auto_schedule_work_order` registry action. Compare-and-set guarded by the action itself: the work order must still be unscheduled with zero appointment rows at lock time, otherwise the call reports `scheduled: false` and writes nothing. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The first appointment window created for a previously-unscheduled work order.","properties":{"id":{"type":"string","format":"uuid","description":"The work order."},"scheduled":{"type":"boolean","description":"False when the work order was no longer eligible at lock time — already scheduled by someone else. A no-op, never an error: a double-booked technician would be worse."},"technicianId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","scheduled","technicianId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"schedule an unscheduled job","request":{"technicianId":"77777777-7777-4777-8777-777777777777","scheduledStart":"2026-09-25T15:00:00.000Z","scheduledEnd":"2026-09-25T17:00:00.000Z","scheduleReason":"Nearest qualified technician with an open window"}}]}},"/work-orders/{workOrderId}/auto-schedule/approve":{"post":{"operationId":"dispatch.auto_schedule_work_order.approve","summary":"Create the first appointment window for an unscheduled work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The first appointment window created for a previously-unscheduled work order.","properties":{"id":{"type":"string","format":"uuid","description":"The work order."},"scheduled":{"type":"boolean","description":"False when the work order was no longer eligible at lock time — already scheduled by someone else. A no-op, never an error: a double-booked technician would be worse."},"technicianId":{"type":"string","format":"uuid"},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: these operations declare `rowVersionStrategy: \"none\"` — the wrapped registry action owns its own concurrency guard."},"replayed":{"type":"boolean","description":"True when this idempotency key replayed the stored response and no second effect ran."}},"required":["id","scheduled","technicianId","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"schedule an unscheduled job","request":{"technicianId":"77777777-7777-4777-8777-777777777777","scheduledStart":"2026-09-25T15:00:00.000Z","scheduledEnd":"2026-09-25T17:00:00.000Z","scheduleReason":"Nearest qualified technician with an open window"}}]}},"/work-orders/{workOrderId}/auto-schedule/preview":{"post":{"operationId":"dispatch.auto_schedule_work_order.preview","summary":"Create the first appointment window for an unscheduled work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"high","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"dispatch","x-thermal-target-table":"work_order_appointments","x-thermal-examples":[{"name":"schedule an unscheduled job","request":{"technicianId":"77777777-7777-4777-8777-777777777777","scheduledStart":"2026-09-25T15:00:00.000Z","scheduledEnd":"2026-09-25T17:00:00.000Z","scheduleReason":"Nearest qualified technician with an open window"}}]}},"/work-orders/{workOrderId}/inspections":{"post":{"operationId":"inspection.start","summary":"Start an inspection on a work order","description":"Instantiates an inspection from a template against the work order's OWN linked equipment. `inspectionId` and every `items[].responseId` are client-generated so the checklist renders offline before this write is ever sent, and a duplicate delivery of the queued write finds the row it already created and returns `created: false`. The server re-derives every checklist item's section, label, field type, unit, mandatory flag and compliance snapshot from the template's own rows — nothing but the two ids is trusted from the client. A work order in another organization, or one this technician holds no live appointment on, is reported as `404`. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection this work order now has in progress.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"created":{"type":"boolean","description":"False when this inspection id already existed and no second inspection was created."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"start the PM checklist on an assigned job","request":{"inspectionId":"66666666-6666-4666-8666-666666666666","equipmentId":"77777777-7777-4777-8777-777777777777","templateId":"88888888-8888-4888-8888-888888888888","items":[{"responseId":"99999999-9999-4999-8999-999999999999","templateItemId":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}]}}]}},"/work-orders/{workOrderId}/inspections/approve":{"post":{"operationId":"inspection.start.approve","summary":"Start an inspection on a work order — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The inspection this work order now has in progress.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"created":{"type":"boolean","description":"False when this inspection id already existed and no second inspection was created."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","created","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"start the PM checklist on an assigned job","request":{"inspectionId":"66666666-6666-4666-8666-666666666666","equipmentId":"77777777-7777-4777-8777-777777777777","templateId":"88888888-8888-4888-8888-888888888888","items":[{"responseId":"99999999-9999-4999-8999-999999999999","templateItemId":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}]}}]}},"/work-orders/{workOrderId}/inspections/preview":{"post":{"operationId":"inspection.start.preview","summary":"Start an inspection on a work order — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"inspections","x-thermal-examples":[{"name":"start the PM checklist on an assigned job","request":{"inspectionId":"66666666-6666-4666-8666-666666666666","equipmentId":"77777777-7777-4777-8777-777777777777","templateId":"88888888-8888-4888-8888-888888888888","items":[{"responseId":"99999999-9999-4999-8999-999999999999","templateItemId":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}]}}]}},"/work-orders/{workOrderId}/jha-submissions":{"post":{"operationId":"jha.submit_arrival","summary":"Submit the arrival job hazard analysis","description":"The single atomic submit of a job's arrival JHA. Creates one immutable `jha_submissions` row through the one writer that may create one, enforces the mandatory-question block and picks the hazard stop state; it can never mutate an existing submission. This submission is what clears the arrival start gate — `checkAppointmentStartGate`'s `jha_required` — so the technician can start work and the job's work beats become available. A duplicate delivery under the same `Idempotency-Key` replays the stored result and files no second submission. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The submission this visit now has on file.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"stopState":{"type":"string","enum":["no_stop","stop_work","stop_overridden"]},"startGateCleared":{"type":"boolean","description":"True when this job's arrival JHA requirement is satisfied — the same fact `checkAppointmentStartGate` reads before it lets work start."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","stopState","startGateCleared","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"jha_submissions","x-thermal-examples":[{"name":"submit the arrival checklist for this visit","request":{"templateId":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","appointmentId":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","answers":[{"questionId":"loto","answerValue":"yes"}]}}]}},"/work-orders/{workOrderId}/jha-submissions/approve":{"post":{"operationId":"jha.submit_arrival.approve","summary":"Submit the arrival job hazard analysis — approve","description":"A human approves an exact intent hash; the server issues a one-use permit and applies under the human actor. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"The submission this visit now has on file.","properties":{"id":{"type":"string","description":"The row this operation acted on."},"stopState":{"type":"string","enum":["no_stop","stop_work","stop_overridden"]},"startGateCleared":{"type":"boolean","description":"True when this job's arrival JHA requirement is satisfied — the same fact `checkAppointmentStartGate` reads before it lets work start."},"rowVersion":{"type":"integer","nullable":true,"description":"Always null: this operation's target carries no server-owned row version (see the write-registry header)."},"replayed":{"type":"boolean","description":"True when the idempotency key replayed a stored result and no second effect ran."}},"required":["id","stopState","startGateCleared","rowVersion","replayed"],"additionalProperties":false}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"jha_submissions","x-thermal-examples":[{"name":"submit the arrival checklist for this visit","request":{"templateId":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","appointmentId":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","answers":[{"questionId":"loto","answerValue":"yes"}]}}]}},"/work-orders/{workOrderId}/jha-submissions/preview":{"post":{"operationId":"jha.submit_arrival.preview","summary":"Submit the arrival job hazard analysis — preview","description":"Reads the target, classifies the transition's effective risk, and returns a short-lived single-use proposal. Causes no side effect. Requires Content-Type: application/json, including bodyless DELETE requests.","deprecated":false,"security":[{"clerkSessionJwt":[]}],"parameters":[{"name":"workOrderId","in":"path","required":true,"description":"The workOrderId the operation acts on.","schema":{"type":"string"}},{"name":"Thermal-Client","in":"header","required":false,"description":"Optional. Identifies a first-party client build as `<platform>/<semver>[+<build>]`, e.g. `mobile/1.2.3+45`. A known platform below its minimum supported version is refused with `400 client_upgrade_required`. An absent or unparseable value, or an unknown platform, is never refused.","schema":{"type":"string","examples":["mobile/1.2.3+45"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"201":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","description":"An immutable intent. Preview returns it and causes no side effect; apply presents it back.","properties":{"proposalId":{"type":"string","format":"uuid"},"intentHash":{"type":"string"},"operationId":{"type":"string"},"riskClass":{"type":"string","enum":["low","medium","high","critical"]},"previewRequired":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time"},"effect":{"type":"string","enum":["none"]}},"required":["proposalId","intentHash","operationId","riskClass","previewRequired","expiresAt","effect"],"additionalProperties":true}}}},"400":{"description":"Validation failure. Unknown filter keys and unsupported sort keys are rejected rather than ignored, and a page size above the contract limit is validated, not clamped. Also `client_upgrade_required` when the `Thermal-Client` header names a client below its platform's minimum supported version.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/ClientUpgradeRequired"}]}}}},"401":{"description":"Authentication failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Authorization or tenancy denial. Org and branch scope come from the resolved context, never from a filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Not found, or not visible in the caller's resolved scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict, including a stale row version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"415":{"description":"Unsupported media type. Governed POST and DELETE requests require Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limited. Names the operation class and carries retry headers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Unexpected server failure. Never echoes secrets or raw internal exception text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"504":{"description":"Error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"x-thermal-risk-class":"medium","x-thermal-preview-required":true,"x-thermal-idempotency-required":true,"x-thermal-audit-required":true,"x-thermal-evidence-required":true,"x-thermal-sensitive-read-allowlisted":false,"x-thermal-side-effect":"write","x-thermal-area":"field-work","x-thermal-target-table":"jha_submissions","x-thermal-examples":[{"name":"submit the arrival checklist for this visit","request":{"templateId":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","appointmentId":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","answers":[{"questionId":"loto","answerValue":"yes"}]}}]}}},"components":{"securitySchemes":{"clerkSessionJwt":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"A Clerk session JWT, verified against JWKS. Resolves to the user-session principal (plan D2)."},"oauthClientToken":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"A Clerk OAuth access token, org-scoped and audience-bound (RFC 8707). Resolves to the delegated-OAuth-client principal. Claims are hints; the database is authoritative."},"orgApiKey":{"type":"apiKey","in":"header","name":"Authorization","description":"An org API key. Resolves to the org-API-key principal, never wider than a real role. The delegation class is server-owned and cannot be asserted by the caller."}},"schemas":{"AmbiguousOrganization":{"type":"object","description":"The refusal a credential that may act in more than one organization receives when it names none (HTTP 409). No principal is resolved; send one of `organizations` in the organization header.","properties":{"code":{"type":"string","enum":["ambiguous_organization"],"description":"Always `ambiguous_organization`."},"message":{"type":"string","description":"Human-readable message."},"requestId":{"type":"string","description":"The request id, also recorded on the originating api_activity row."},"organizations":{"type":"array","description":"Every organization the credential may act in, by id.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}}},"required":["code","message","requestId","organizations"],"additionalProperties":false},"ClientUpgradeRequired":{"type":"object","description":"The refusal a first-party client below its platform's minimum supported version receives (HTTP 400). Flat, like the shared error envelope, with the two fields a client needs to prompt an update.","properties":{"code":{"type":"string","enum":["client_upgrade_required"],"description":"Always `client_upgrade_required`."},"message":{"type":"string","description":"Human-readable message naming the minimum version."},"requestId":{"type":"string","description":"The request id, echoed in the `x-request-id` header. No api_activity row is written for this refusal."},"minimum":{"type":"string","description":"The minimum supported version for `platform`, as `x.y.z`."},"platform":{"type":"string","description":"The platform named in the `Thermal-Client` header."}},"required":["code","message","requestId","minimum","platform"],"additionalProperties":false},"ErrorEnvelope":{"type":"object","description":"The one error envelope every Platform API error uses. Never echoes secrets or raw internal exception text.","properties":{"code":{"type":"string","description":"Stable machine-readable code. Safe to branch on."},"message":{"type":"string","description":"Human-readable message. Never carries a secret or a raw exception."},"requestId":{"type":"string","description":"The request id, also recorded on the originating api_activity row."}},"required":["code","message","requestId"],"additionalProperties":false}}}}