{"openapi":"3.1.0","info":{"title":"Swim Ops Platform API","version":"2.0.0","description":"Programmatic + bulk access to your club's platform data, generated from the operation registry. Authenticate with `Authorization: Bearer opp_…` (scoped API key, created by an admin at /admin/api-keys). All money values are integer cents. Every operation is listed at `GET /api/v1/ops/<name>` (Tier 1 `list`/`get` ops) or documented as `POST /api/v1/ops/<name>` below: there is no other `/api/v1` surface."},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key (opp_…)"}},"schemas":{"OpsHouseholdsListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"status":{"type":"string"},"membershipTier":{"anyOf":[{"type":"string"},{"type":"null"}]},"primaryContactEmail":{"anyOf":[{"type":"string"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","status","membershipTier","tags","balanceCents"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsHouseholdsGetOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"status":{"type":"string"},"membershipTier":{"anyOf":[{"type":"string"},{"type":"null"}]},"primaryContactEmail":{"anyOf":[{"type":"string"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"street":{"anyOf":[{"type":"string"},{"type":"null"}]},"city":{"anyOf":[{"type":"string"},{"type":"null"}]},"state":{"anyOf":[{"type":"string"},{"type":"null"}]},"zip":{"anyOf":[{"type":"string"},{"type":"null"}]},"districtResident":{"type":"boolean"},"memberSince":{"anyOf":[{"type":"string"},{"type":"null"}]},"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"firstName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"lastName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"email":{"anyOf":[{"type":"string"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"role":{"type":"string"},"isPrimaryContact":{"type":"boolean"}},"required":["id","firstName","lastName","role","isPrimaryContact"],"additionalProperties":false}},"dependents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"firstName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"lastName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"birthDate":{"anyOf":[{"type":"string"},{"type":"null"}]},"kind":{"type":"string"}},"required":["id","firstName","lastName","birthDate","kind"],"additionalProperties":false}}},"required":["id","name","status","membershipTier","tags","balanceCents","street","city","state","zip","districtResident","memberSince","members","dependents"],"additionalProperties":false},"OpsHouseholdsCreateOutput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"},"portalAccessProvisioned":{"type":"boolean"},"awaitingSignIn":{"type":"boolean"}},"required":["householdId","userId","status","portalAccessProvisioned","awaitingSignIn"],"additionalProperties":false},"OpsHouseholdsCreateInput":{"type":"object","properties":{"householdName":{"type":"string","minLength":1,"maxLength":200,"description":"e.g. \"The Smith Family\"."},"firstName":{"type":"string","minLength":1,"maxLength":100,"description":"Primary contact's first name."},"lastName":{"type":"string","minLength":1,"maxLength":100},"email":{"type":"string","minLength":3,"maxLength":320,"description":"Primary contact's email. Arrives unconfirmed — nothing is sent to it here."},"phone":{"type":"string","maxLength":40},"street":{"type":"string","maxLength":200},"city":{"type":"string","maxLength":100},"state":{"type":"string","maxLength":40},"zip":{"type":"string","maxLength":20},"districtResident":{"type":"boolean","description":"Whether the household qualifies for the club's residency priority."},"tier":{"description":"Membership tier key. Omit for a household that is not a member yet.","type":"string","maxLength":40}},"required":["householdName","firstName","lastName","email","districtResident"],"additionalProperties":false},"OpsHouseholdsUpdateOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"status":{"type":"string"},"membershipTier":{"anyOf":[{"type":"string"},{"type":"null"}]},"primaryContactEmail":{"anyOf":[{"type":"string"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","status","membershipTier","tags","balanceCents"],"additionalProperties":false},"OpsHouseholdsUpdateInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1},"street":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"districtResident":{"type":"boolean"},"memberSince":{"description":"YYYY-MM-DD, or omit to clear.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},"required":["householdId","name","districtResident"],"additionalProperties":false},"OpsHouseholdsAddTagOutput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tags":{"type":"array","items":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}}},"required":["userId","tags"],"additionalProperties":false},"OpsHouseholdsAddTagInput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tag":{"type":"string","minLength":1,"maxLength":64}},"required":["userId","tag"],"additionalProperties":false},"OpsHouseholdsRemoveTagOutput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tags":{"type":"array","items":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}}},"required":["userId","tags"],"additionalProperties":false},"OpsHouseholdsRemoveTagInput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tag":{"type":"string","minLength":1,"maxLength":64}},"required":["userId","tag"],"additionalProperties":false},"OpsHouseholdsAddNoteOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"body":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","householdId","body","createdAt"],"additionalProperties":false},"OpsHouseholdsAddNoteInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"body":{"type":"string","minLength":1,"maxLength":4000}},"required":["householdId","body"],"additionalProperties":false},"OpsHouseholdsBulkAddTagOutput":{"type":"object","properties":{"groupId":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["householdId","ok"],"additionalProperties":false}}},"required":["groupId","results"],"additionalProperties":false},"OpsHouseholdsBulkAddTagInput":{"type":"object","properties":{"householdIds":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"tag":{"type":"string","minLength":1,"maxLength":80}},"required":["householdIds","tag"],"additionalProperties":false},"OpsHouseholdsBulkRemoveTagOutput":{"type":"object","properties":{"groupId":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["householdId","ok"],"additionalProperties":false}}},"required":["groupId","results"],"additionalProperties":false},"OpsHouseholdsBulkRemoveTagInput":{"type":"object","properties":{"householdIds":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"tag":{"type":"string","minLength":1,"maxLength":80}},"required":["householdIds","tag"],"additionalProperties":false},"OpsHouseholdsBulkUpdateOutput":{"type":"object","properties":{"groupId":{"type":"string"},"results":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["userId","ok"],"additionalProperties":false}}},"required":["groupId","results"],"additionalProperties":false},"OpsHouseholdsBulkUpdateInput":{"type":"object","properties":{"items":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tags":{"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"emailOptIn":{"type":"boolean"},"smsOptIn":{"type":"boolean"}},"required":["userId"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"OpsHouseholdsUpdateEmailOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsUpdateEmailInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["householdId","userId","email"],"additionalProperties":false},"OpsHouseholdsProvisionPortalAccessOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsProvisionPortalAccessInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId","userId"],"additionalProperties":false},"OpsHouseholdsUnbindSmsLoginOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsUnbindSmsLoginInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId","userId"],"additionalProperties":false},"OpsHouseholdsSetPrimaryContactOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsSetPrimaryContactInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId","userId"],"additionalProperties":false},"OpsHouseholdsTransferOwnerOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsTransferOwnerInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId","userId"],"additionalProperties":false},"OpsHouseholdsInviteAdultOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsInviteAdultInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1}},"required":["householdId","email","firstName","lastName"],"additionalProperties":false},"OpsHouseholdsRevokeInvitationOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsRevokeInvitationInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invitationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId","invitationId"],"additionalProperties":false},"OpsHouseholdsMoveAdultOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsMoveAdultInput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sourceHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["userId","sourceHouseholdId","destinationHouseholdId"],"additionalProperties":false},"OpsHouseholdsConsolidateProspectOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsConsolidateProspectInput":{"type":"object","properties":{"sourceHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["sourceHouseholdId","destinationHouseholdId"],"additionalProperties":false},"OpsHouseholdsMergeOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsMergeInput":{"type":"object","properties":{"sourceHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["sourceHouseholdId","destinationHouseholdId"],"additionalProperties":false},"OpsHouseholdsReverseMergeOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsReverseMergeInput":{"type":"object","properties":{"sourceHouseholdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["sourceHouseholdId"],"additionalProperties":false},"OpsHouseholdsGrantExtensionOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsGrantExtensionInput":{"type":"object","properties":{"membershipYearId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"extendedTo":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"YYYY-MM-DD"},"reason":{"type":"string","minLength":1}},"required":["membershipYearId","extendedTo","reason"],"additionalProperties":false},"OpsHouseholdsRevokeExtensionOutput":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["ok","message"],"additionalProperties":false},"OpsHouseholdsRevokeExtensionInput":{"type":"object","properties":{"extensionId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["extensionId"],"additionalProperties":false},"OpsHouseholdsCreateInvoiceOutput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"number":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["invoiceId","number","totalCents"],"additionalProperties":false},"OpsHouseholdsCreateInvoiceInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"dueDate":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"memo":{"type":"string","maxLength":2000},"lines":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"object","properties":{"description":{"type":"string","minLength":1},"unitAmountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"glCategory":{"type":"string","enum":["misc","dues","initiation","camp","merch","facility","events","lessons","caregiver_pass","late_fee","credit","refund"]}},"required":["description","unitAmountCents","glCategory"],"additionalProperties":false}}},"required":["householdId","lines"],"additionalProperties":false},"OpsHouseholdsIssueCreditOutput":{"type":"object","properties":{"creditId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["creditId","amountCents"],"additionalProperties":false},"OpsHouseholdsIssueCreditInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"reason":{"type":"string","minLength":1},"source":{"type":"string","enum":["refund_to_credit","goodwill","migration","overpayment"]}},"required":["householdId","amountCents","reason","source"],"additionalProperties":false},"OpsHouseholdsCreatePayableOutput":{"type":"object","properties":{"payableId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["payableId","amountCents"],"additionalProperties":false},"OpsHouseholdsCreatePayableInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"payeeName":{"type":"string","minLength":1},"mailingAddress":{"type":"string","minLength":1},"memo":{"type":"string","maxLength":2000}},"required":["householdId","amountCents","payeeName","mailingAddress"],"additionalProperties":false},"OpsHouseholdsAddToWaitlistOutput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["entryId"],"additionalProperties":false},"OpsHouseholdsAddToWaitlistInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"notes":{"type":"string","maxLength":2000}},"required":["householdId"],"additionalProperties":false},"OpsHouseholdsUpdateMemberOutput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["userId"],"additionalProperties":false},"OpsHouseholdsUpdateMemberInput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1},"emailOptIn":{"type":"boolean"},"smsOptIn":{"type":"boolean"}},"required":["userId","householdId","firstName","lastName","emailOptIn","smsOptIn"],"additionalProperties":false},"OpsHouseholdsUpdateDependentOutput":{"type":"object","properties":{"dependentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["dependentId"],"additionalProperties":false},"OpsHouseholdsUpdateDependentInput":{"type":"object","properties":{"dependentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1},"birthDate":{"type":"string","minLength":1},"kind":{"type":"string","minLength":1},"ccEmail":{"type":"boolean"},"ccSms":{"type":"boolean"}},"required":["dependentId","householdId","firstName","lastName","birthDate","kind","ccEmail","ccSms"],"additionalProperties":false},"OpsHouseholdsUpdateMemberPhoneOutput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["userId"],"additionalProperties":false},"OpsHouseholdsUpdateMemberPhoneInput":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]}},"required":["userId","householdId","phone"],"additionalProperties":false},"OpsHouseholdsSetEmailOptInOutput":{"type":"object","properties":{"groupId":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["householdId","ok"],"additionalProperties":false}}},"required":["groupId","results"],"additionalProperties":false},"OpsHouseholdsSetEmailOptInInput":{"type":"object","properties":{"householdIds":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"value":{"type":"boolean"}},"required":["householdIds","value"],"additionalProperties":false},"OpsHouseholdsSetSmsOptInOutput":{"type":"object","properties":{"groupId":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"userId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ok":{"type":"boolean"},"error":{"type":"string"}},"required":["householdId","ok"],"additionalProperties":false}}},"required":["groupId","results"],"additionalProperties":false},"OpsHouseholdsSetSmsOptInInput":{"type":"object","properties":{"householdIds":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"value":{"type":"boolean"}},"required":["householdIds","value"],"additionalProperties":false},"OpsAccountsSuspendOutput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["householdId","message"],"additionalProperties":false},"OpsAccountsSuspendInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reason":{"type":"string","maxLength":2000},"until":{"description":"YYYY-MM-DD. The pause auto-lifts after this civil date, or omit for indefinite.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},"required":["householdId"],"additionalProperties":false},"OpsAccountsUnsuspendOutput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["householdId","message"],"additionalProperties":false},"OpsAccountsUnsuspendInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId"],"additionalProperties":false},"OpsAccountsCloseOutput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["householdId","message"],"additionalProperties":false},"OpsAccountsCloseInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reason":{"type":"string","maxLength":2000}},"required":["householdId"],"additionalProperties":false},"OpsAccountsReopenOutput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"message":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["householdId","message"],"additionalProperties":false},"OpsAccountsReopenInput":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["householdId"],"additionalProperties":false},"OpsInvoicesListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"number":{"type":"string"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"status":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"issuedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"dueAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"kind":{"type":"string"},"seasonYear":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"subtotalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"creditAppliedCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"paidAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","number","householdId","householdName","status","totalCents","balanceCents","issuedAt","dueAt"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsInvoicesGetOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"number":{"type":"string"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"status":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"issuedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"dueAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"kind":{"type":"string"},"seasonYear":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"subtotalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"creditAppliedCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"paidAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"memo":{"anyOf":[{"type":"string"},{"type":"null"}]},"voidedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"lines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unitAmountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"glCategory":{"type":"string"}},"required":["id","description","quantity","unitAmountCents","amountCents","glCategory"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"method":{"type":"string"},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"},"receivedAt":{"type":"string"},"settledAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","method","amountCents","status","receivedAt","settledAt"],"additionalProperties":false}},"issuedCredits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"remainingCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reason":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","amountCents","remainingCents","reason","createdAt"],"additionalProperties":false}}},"required":["id","number","householdId","householdName","status","totalCents","balanceCents","issuedAt","dueAt","kind","subtotalCents","creditAppliedCents","paidAt","memo","voidedAt","lines","payments","issuedCredits"],"additionalProperties":false},"OpsInvoicesRecordCheckOutput":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invoiceNumber":{"type":"string"},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"checkNumber":{"type":"string"},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["paymentId","invoiceId","invoiceNumber","amountCents","checkNumber","balanceCents"],"additionalProperties":false},"OpsInvoicesRecordCheckInput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"checkNumber":{"type":"string","minLength":1,"maxLength":32},"receivedOn":{"description":"The date the check was actually received, if different from today.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"memo":{"type":"string","maxLength":500}},"required":["invoiceId","amountCents","checkNumber"],"additionalProperties":false},"OpsInvoicesApplyCreditOutput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invoiceNumber":{"type":"string"},"status":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["invoiceId","invoiceNumber","status","totalCents","balanceCents"],"additionalProperties":false},"OpsInvoicesApplyCreditInput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"creditId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["invoiceId","creditId","amountCents"],"additionalProperties":false},"OpsInvoicesAddAdjustmentOutput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invoiceNumber":{"type":"string"},"status":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["invoiceId","invoiceNumber","status","totalCents","balanceCents"],"additionalProperties":false},"OpsInvoicesAddAdjustmentInput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":{"type":"string","minLength":1,"maxLength":500},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"glCategory":{"type":"string","enum":["misc","dues","initiation","camp","merch","facility","events","lessons","caregiver_pass","late_fee","credit","refund"]}},"required":["invoiceId","description","amountCents","glCategory"],"additionalProperties":false},"OpsInvoicesVoidOutput":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invoiceNumber":{"type":"string"},"status":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["invoiceId","invoiceNumber","status","totalCents","balanceCents"],"additionalProperties":false},"OpsInvoicesVoidInput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The invoice id."}},"required":["id"],"additionalProperties":false},"OpsInvoicesRefundOutput":{"type":"object","properties":{"refundId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["refundId","paymentId","amountCents","status"],"additionalProperties":false},"OpsInvoicesRefundInput":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"reason":{"type":"string","maxLength":500}},"required":["paymentId"],"additionalProperties":false},"OpsInvoicesBulkCreateOutput":{"type":"object","properties":{"groupId":{"type":"string"},"results":{"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ok":{"type":"boolean"},"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"error":{"type":"string"}},"required":["householdId","ok"],"additionalProperties":false}}},"required":["groupId","results"],"additionalProperties":false},"OpsInvoicesBulkCreateInput":{"type":"object","properties":{"items":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"memo":{"type":"string","maxLength":500},"lines":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":200},"amountCents":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"glCategory":{"type":"string","enum":["misc","dues","initiation","camp","merch","facility","events","lessons","caregiver_pass","late_fee","credit","refund"]}},"required":["description","amountCents","glCategory"],"additionalProperties":false}}},"required":["householdId","lines"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"OpsPayablesListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"payeeName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"},"createdAt":{"type":"string"},"approvedByUserId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"checkSentAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string"},"checkNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"clearedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","householdName","payeeName","amountCents","status","createdAt","approvedByUserId","checkSentAt"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsRelinquishmentsListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"},"effectiveSeasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"suggestedPenaltyCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bondCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"latePenaltyCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"noticeReceivedAt":{"anyOf":[{"type":"string"},{"type":"null"}]},"reviewerNotes":{"anyOf":[{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},{"type":"null"}]},"refundPayableId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"requestedPayeeName":{"anyOf":[{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},{"type":"null"}]},"requestedMailingAddress":{"anyOf":[{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},{"type":"null"}]}},"required":["id","status","effectiveSeasonYear","householdId","householdName","suggestedPenaltyCents","bondCents"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data"],"additionalProperties":false},"OpsRelinquishmentsApproveOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"netRefundCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"payeeName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["id","status","householdId","netRefundCents","payeeName"],"additionalProperties":false},"OpsRelinquishmentsApproveInput":{"type":"object","properties":{"relinquishmentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"latePenaltyCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"payeeName":{"type":"string","minLength":1,"maxLength":200},"mailingAddress":{"type":"string","minLength":1,"maxLength":500},"reviewerNotes":{"type":"string","maxLength":1000}},"required":["relinquishmentId","latePenaltyCents","payeeName","mailingAddress"],"additionalProperties":false},"OpsRelinquishmentsDenyOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","status","householdId"],"additionalProperties":false},"OpsRelinquishmentsDenyInput":{"type":"object","properties":{"relinquishmentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reviewerNotes":{"type":"string","minLength":1,"maxLength":1000}},"required":["relinquishmentId","reviewerNotes"],"additionalProperties":false},"OpsMembershipsListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"tierLabel":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string"},"renewalState":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"balanceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tier":{"type":"string"},"joinedAt":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["householdId","householdName","tierLabel","status","renewalState","seasonYear","balanceCents"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsWaitlistListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"residencyLabel":{"type":"string"},"status":{"type":"string"},"appliedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"offerExpiresAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"districtResident":{"type":"boolean"},"source":{"type":"string"},"notes":{"anyOf":[{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},{"type":"null"}]},"offerId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","position","householdName","residencyLabel","status","appliedAt","offerExpiresAt"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsWaitlistReorderOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["id","position","householdName"],"additionalProperties":false},"OpsWaitlistReorderInput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"newPosition":{"type":"integer","minimum":1,"maximum":9007199254740991,"description":"The new 1-based queue position."}},"required":["entryId","newPosition"],"additionalProperties":false},"OpsWaitlistOfferOutput":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"offerUrl":{"type":"string"}},"required":["offerId","entryId","expiresAt"],"additionalProperties":false},"OpsWaitlistOfferInput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["entryId"],"additionalProperties":false},"OpsWaitlistOfferBatchOutput":{"type":"object","properties":{"requestedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offers":{"type":"array","items":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["offerId","entryId","householdName"],"additionalProperties":false}},"failed":{"type":"array","items":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false}},"required":["entryId","householdName"],"additionalProperties":false}}},"required":["requestedCount","offers","failed"],"additionalProperties":false},"OpsWaitlistOfferBatchInput":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":50,"description":"How many households, starting from the top of the waiting list, to offer a spot to."},"expectedEntryIds":{"description":"Entry ids the confirmation listed, in order. The offer is refused if the queue has changed.","type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["count"],"additionalProperties":false},"OpsWaitlistResendOfferOutput":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["offerId","expiresAt"],"additionalProperties":false},"OpsWaitlistResendOfferInput":{"type":"object","properties":{"offerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["offerId"],"additionalProperties":false},"OpsCampWeeksListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"startsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"endsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"registeredCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"waitlistCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"minAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"priceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"registrationsCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","label","startsOn","endsOn","capacity","registeredCount","waitlistCount","status"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsCampWeeksGetOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"endsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"},"registered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"registrations":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","label","seasonYear","startsOn","endsOn","minAge","maxAge","capacity","priceCents","status","registered","registrations"],"additionalProperties":false},"OpsCampRegistrationsListOutput":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"childName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"householdName":{"type":"object","properties":{"untrusted":{"type":"boolean","const":true},"text":{"type":"string"}},"required":["untrusted","text"],"additionalProperties":false},"age":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"status":{"type":"string"},"paid":{"type":"boolean"},"intakeCompleted":{"type":"boolean"}},"required":["id","childName","householdName","age","status","paid","intakeCompleted"],"additionalProperties":false}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","nextCursor"],"additionalProperties":false},"OpsCampWeeksCreateOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"endsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["id","label","seasonYear","startsOn","endsOn","minAge","maxAge","capacity","priceCents","status"],"additionalProperties":false},"OpsCampWeeksCreateInput":{"type":"object","properties":{"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"label":{"type":"string","minLength":1,"maxLength":200},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date YYYY-MM-DD."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":1,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["seasonYear","label","startDate","endDate","capacity","priceCents"],"additionalProperties":false},"OpsCampWeeksUpdateOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"endsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["id","label","seasonYear","startsOn","endsOn","minAge","maxAge","capacity","priceCents","status"],"additionalProperties":false},"OpsCampWeeksUpdateInput":{"type":"object","properties":{"weekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string","minLength":1,"maxLength":200},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date YYYY-MM-DD."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":1,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["weekId","label","startDate","endDate","capacity","priceCents"],"additionalProperties":false},"OpsCampWeeksSetStatusOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"endsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["id","label","seasonYear","startsOn","endsOn","minAge","maxAge","capacity","priceCents","status"],"additionalProperties":false},"OpsCampWeeksSetStatusInput":{"type":"object","properties":{"weekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["open","closed"],"description":"The service only accepts \"open\"/\"closed\" here: cancel and archive have their own dedicated, confirmation-heavier flows."}},"required":["weekId","status"],"additionalProperties":false},"OpsCampWeeksArchiveOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"seasonYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"startsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"endsOn":{"type":"string","description":"Civil date YYYY-MM-DD."},"minAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxAge":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"priceCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"}},"required":["id","label","seasonYear","startsOn","endsOn","minAge","maxAge","capacity","priceCents","status"],"additionalProperties":false},"OpsCampWeeksArchiveInput":{"type":"object","properties":{"weekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"confirmation":{"type":"string","minLength":1}},"required":["weekId","confirmation"],"additionalProperties":false},"OpsCampAttendanceSetOutput":{"type":"object","properties":{"registrationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"date":{"type":"string","description":"Civil date YYYY-MM-DD."},"present":{"type":"boolean"}},"required":["registrationId","date","present"],"additionalProperties":false},"OpsCampAttendanceSetInput":{"type":"object","properties":{"registrationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date YYYY-MM-DD, must fall within the registration's week."},"present":{"type":"boolean"}},"required":["registrationId","date","present"],"additionalProperties":false},"OpsCampWaitlistReorderOutput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["entryId","position"],"additionalProperties":false},"OpsCampWaitlistReorderInput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"newPosition":{"type":"integer","minimum":1,"maximum":9007199254740991},"expectedPlace":{"description":"The place the entry was shown at when the move was chosen. The move is refused with state_changed when its live place differs.","type":"integer","minimum":1,"maximum":9007199254740991}},"required":["entryId","newPosition"],"additionalProperties":false},"OpsCampWeeksCancelOutput":{"type":"object","properties":{"canceledRegistrations":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"refundedCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"creditedCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"refundFailures":{"type":"array","items":{"type":"string"}},"remainingRegistrations":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"waitlistRemoved":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["canceledRegistrations","refundedCents","creditedCents","refundFailures","remainingRegistrations","waitlistRemoved"],"additionalProperties":false},"OpsCampWeeksCancelInput":{"type":"object","properties":{"weekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"confirmation":{"type":"string","minLength":1},"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Required: emailed to every affected household."}},"required":["weekId","confirmation","reason"],"additionalProperties":false},"OpsCampRegistrationsCreateOutput":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"campWeekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"dependentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"},"source":{"type":"string"},"depositCents":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"refundEligibleUntil":{"anyOf":[{"type":"string"},{"type":"null"}]},"partialRefundUntil":{"anyOf":[{"type":"string"},{"type":"null"}]},"invoiceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"invoice":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"number":{"type":"string"},"status":{"type":"string"},"totalCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","number","status","totalCents"],"additionalProperties":false},{"type":"null"}]}},"required":["id","campWeekId","dependentId","householdId","status","source","invoice"],"additionalProperties":false},"OpsCampRegistrationsCreateInput":{"type":"object","properties":{"campWeekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"dependentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"householdId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"intake":{"type":"object","properties":{"emergencyContactName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"emergencyContactPhone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"medicalNotes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"authorizedPickup":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}]}},"additionalProperties":false}},"required":["campWeekId","dependentId","householdId"],"additionalProperties":false},"OpsCampRegistrationsCancelOutput":{"type":"object","properties":{"registrationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"outcome":{"type":"string","enum":["voided","credited","none","refunded"]},"refundedCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"creditedCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tier":{"type":"string","enum":["full","partial","none"]},"refundableBps":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"paidCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"depositWithheldCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cashFeeWithheldCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"amountCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"creditGatedOnBackfill":{"type":"boolean"},"gatedCreditCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["registrationId","outcome","tier","refundableBps","paidCents","depositWithheldCents","cashFeeWithheldCents","amountCents","creditGatedOnBackfill","gatedCreditCents"],"additionalProperties":false},"OpsCampRegistrationsCancelInput":{"type":"object","properties":{"registrationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reason":{"type":"string","maxLength":500},"refund":{"description":"Cash refund via Stripe instead of account credit. Requires reason.","type":"boolean"},"expected":{"description":"The refund figures shown to the person confirming. The cancel is refused with state_changed when the live quote differs.","type":"object","properties":{"tier":{"type":"string","enum":["full","partial","none"]},"creditCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"cashCents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["tier","creditCents"],"additionalProperties":false}},"required":["registrationId"],"additionalProperties":false},"OpsCampRegistrationsTransferOutput":{"type":"object","properties":{"registrationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"delta":{"type":"string","enum":["credit","invoice","none"]},"deltaCents":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["registrationId","delta","deltaCents"],"additionalProperties":false},"OpsCampRegistrationsTransferInput":{"type":"object","properties":{"registrationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"toWeekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["registrationId","toWeekId"],"additionalProperties":false},"OpsCampWaitlistPromoteOutput":{"type":"object","properties":{"offered":{"type":"boolean"}},"required":["offered"],"additionalProperties":false},"OpsCampWaitlistPromoteInput":{"type":"object","properties":{"weekId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["weekId"],"additionalProperties":false},"OpsCampWaitlistRemoveOutput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string"}},"required":["entryId","status"],"additionalProperties":false},"OpsCampWaitlistRemoveInput":{"type":"object","properties":{"entryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["entryId"],"additionalProperties":false}}},"paths":{"/api/v1/openapi.json":{"get":{"summary":"This document","responses":{"200":{"description":"OK"}}}},"/api/v1/runs/{id}":{"get":{"operationId":"getRunStatus","summary":"Check on an async operation's run","security":[{"bearerAuth":[]}],"description":"Returns the durable status of one async operation call: queued, running, done (with its result), or failed (with its error). 404 when the id doesn't exist in this key's org.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Run status","content":{"application/json":{"schema":{"type":"object","properties":{"runId":{"type":"string","format":"uuid"},"operation":{"type":"string"},"status":{"type":"string","enum":["queued","running","done","failed"]},"result":{},"error":{"type":"string","nullable":true}},"required":["runId","operation","status","result","error"]}}}},"404":{"description":"No run found for that id"}}}},"/api/v1/ops/households.list":{"get":{"operationId":"ops.households.list","summary":"List households","description":"Search or list households (member families) in this club, with their status, membership tier, and balance.","security":[{"bearerAuth":[]}],"parameters":[{"name":"query","in":"query","required":false,"schema":{"description":"Free text matched against household name, street, member name/email/phone.","type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.get":{"get":{"operationId":"ops.households.get","summary":"Get a household","description":"Look up one household by id: status, membership tier, primary contact, tags, and balance.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The household id."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsGetOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.create":{"post":{"operationId":"ops.households.create","summary":"Add a household","description":"Create a household and its primary member by hand — the family who phoned in, or one row a CSV import got wrong. Sends nothing: the email address arrives unconfirmed, exactly as an imported one does, and no member hears from the club until somebody proves they hold that inbox. A membership tier is optional and creates no invoice, no bond and no renewal year. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.create/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.create/preview":{"post":{"operationId":"ops.households.create.preview","summary":"Preview: Add a household","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update":{"post":{"operationId":"ops.households.update","summary":"Update a household","description":"Update a household's name, mailing address, residency flag, and member-since date. Never touches email, phone, or login. Those are separate, more sensitive operations. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.update/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update/preview":{"post":{"operationId":"ops.households.update.preview","summary":"Preview: Update a household","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.add_tag":{"post":{"operationId":"ops.households.add_tag","summary":"Add a member tag","description":"Add an ad-hoc tag to a household member. Adding a tag that's already there is a harmless no-op. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.add_tag/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddTagInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddTagOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.add_tag/preview":{"post":{"operationId":"ops.households.add_tag.preview","summary":"Preview: Add a member tag","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddTagInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.remove_tag":{"post":{"operationId":"ops.households.remove_tag","summary":"Remove a member tag","description":"Remove an ad-hoc tag from a household member. Removing a tag that isn't there is a harmless no-op. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.remove_tag/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRemoveTagInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRemoveTagOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.remove_tag/preview":{"post":{"operationId":"ops.households.remove_tag.preview","summary":"Preview: Remove a member tag","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRemoveTagInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.add_note":{"post":{"operationId":"ops.households.add_note","summary":"Add a household note","description":"Add an append-only staff CRM note to a household. There is no edit or delete. A wrong note gets a correcting note. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.add_note/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddNoteInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddNoteOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.add_note/preview":{"post":{"operationId":"ops.households.add_note.preview","summary":"Preview: Add a household note","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddNoteInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.bulk_add_tag":{"post":{"operationId":"ops.households.bulk_add_tag","summary":"Bulk add a tag","description":"Add a tag to every member of up to 200 selected households in one audited batch (directory bulk bar). Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.bulk_add_tag/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkAddTagInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkAddTagOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.bulk_add_tag/preview":{"post":{"operationId":"ops.households.bulk_add_tag.preview","summary":"Preview: Bulk add a tag","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkAddTagInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.bulk_remove_tag":{"post":{"operationId":"ops.households.bulk_remove_tag","summary":"Bulk remove a tag","description":"Remove a tag from every member of up to 200 selected households in one audited batch (directory bulk bar). Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.bulk_remove_tag/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkRemoveTagInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkRemoveTagOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.bulk_remove_tag/preview":{"post":{"operationId":"ops.households.bulk_remove_tag.preview","summary":"Preview: Bulk remove a tag","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkRemoveTagInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.bulk_update":{"post":{"operationId":"ops.households.bulk_update","summary":"Bulk update members","description":"Add or remove ad-hoc tags for up to 500 household members in one audited batch, sharing one audit group id. Phone and email/SMS opt-in are contact fields and are refused here. Use households.update_member_phone / households.set_email_opt_in / households.set_sms_opt_in instead. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.bulk_update/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkUpdateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkUpdateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.bulk_update/preview":{"post":{"operationId":"ops.households.bulk_update.preview","summary":"Preview: Bulk update members","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsBulkUpdateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_email":{"post":{"operationId":"ops.households.update_email","summary":"Change a member's sign-in email","description":"Change the email address a household member uses to sign in. This is a credential change. Changes how the member signs in and is emailed to both the old and new address. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.update_email/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateEmailInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateEmailOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_email/preview":{"post":{"operationId":"ops.households.update_email.preview","summary":"Preview: Change a member's sign-in email","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateEmailInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.provision_portal_access":{"post":{"operationId":"ops.households.provision_portal_access","summary":"Provision portal login","description":"Create (or link) a sign-in identity for a household adult who can't yet sign in to the member portal. A login-provisioning action, so it needs approval even though it sends no message itself. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.provision_portal_access/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsProvisionPortalAccessInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsProvisionPortalAccessOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.provision_portal_access/preview":{"post":{"operationId":"ops.households.provision_portal_access.preview","summary":"Preview: Provision portal login","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsProvisionPortalAccessInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.unbind_sms_login":{"post":{"operationId":"ops.households.unbind_sms_login","summary":"Unlink text sign-in","description":"Unlink a member's verified phone number from text (SMS) sign-in. This is a login-credential change. They will need to re-verify a number from their portal to sign in by text again. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.unbind_sms_login/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUnbindSmsLoginInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUnbindSmsLoginOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.unbind_sms_login/preview":{"post":{"operationId":"ops.households.unbind_sms_login.preview","summary":"Preview: Unlink text sign-in","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUnbindSmsLoginInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.set_primary_contact":{"post":{"operationId":"ops.households.set_primary_contact","summary":"Set primary contact","description":"Change which household member is the primary contact for billing statements and default correspondence. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.set_primary_contact/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetPrimaryContactInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetPrimaryContactOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.set_primary_contact/preview":{"post":{"operationId":"ops.households.set_primary_contact.preview","summary":"Preview: Set primary contact","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetPrimaryContactInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.transfer_owner":{"post":{"operationId":"ops.households.transfer_owner","summary":"Transfer household ownership","description":"Transfer household ownership (the account-management adult) to a different member of the same household. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.transfer_owner/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsTransferOwnerInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsTransferOwnerOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.transfer_owner/preview":{"post":{"operationId":"ops.households.transfer_owner.preview","summary":"Preview: Transfer household ownership","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsTransferOwnerInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.invite_adult":{"post":{"operationId":"ops.households.invite_adult","summary":"Invite an adult to the household","description":"Email an adult an invitation link to join this household's portal account. Messages a new address, so it needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.invite_adult/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsInviteAdultInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsInviteAdultOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.invite_adult/preview":{"post":{"operationId":"ops.households.invite_adult.preview","summary":"Preview: Invite an adult to the household","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsInviteAdultInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.revoke_invitation":{"post":{"operationId":"ops.households.revoke_invitation","summary":"Revoke a household invitation","description":"Revoke a pending household invitation before it's accepted, so the invite link stops working. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.revoke_invitation/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRevokeInvitationInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRevokeInvitationOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.revoke_invitation/preview":{"post":{"operationId":"ops.households.revoke_invitation.preview","summary":"Preview: Revoke a household invitation","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRevokeInvitationInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.move_adult":{"post":{"operationId":"ops.households.move_adult","summary":"Move an adult to another household","description":"Move an adult member from one household to another, keeping their login and history but changing which household they belong to. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.move_adult/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsMoveAdultInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsMoveAdultOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.move_adult/preview":{"post":{"operationId":"ops.households.move_adult.preview","summary":"Preview: Move an adult to another household","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsMoveAdultInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.consolidate_prospect":{"post":{"operationId":"ops.households.consolidate_prospect","summary":"Consolidate a prospect household","description":"Fold a duplicate prospect (waitlist-only, never a paying member) household into another, leaving the source as an audited redirect. Financial consequence: any waitlist position moves to the destination. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.consolidate_prospect/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsConsolidateProspectInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsConsolidateProspectOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.consolidate_prospect/preview":{"post":{"operationId":"ops.households.consolidate_prospect.preview","summary":"Preview: Consolidate a prospect household","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsConsolidateProspectInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.merge":{"post":{"operationId":"ops.households.merge","summary":"Merge two households","description":"Merge one household into another, preserving both households' financial history on the original rows. The source becomes an audited redirect to the survivor. A financial-history-affecting change. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.merge/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsMergeInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsMergeOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.merge/preview":{"post":{"operationId":"ops.households.merge.preview","summary":"Preview: Merge two households","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsMergeInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.reverse_merge":{"post":{"operationId":"ops.households.reverse_merge","summary":"Undo a household merge","description":"Reverse a previous household merge. People move back and the redirect clears. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.reverse_merge/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsReverseMergeInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsReverseMergeOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.reverse_merge/preview":{"post":{"operationId":"ops.households.reverse_merge.preview","summary":"Preview: Undo a household merge","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsReverseMergeInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.grant_extension":{"post":{"operationId":"ops.households.grant_extension","summary":"Grant a renewal extension","description":"Grant a household a later renewal deadline for one membership year. Changes their renewal entitlement and emails the household. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.grant_extension/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsGrantExtensionInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsGrantExtensionOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.grant_extension/preview":{"post":{"operationId":"ops.households.grant_extension.preview","summary":"Preview: Grant a renewal extension","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsGrantExtensionInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.revoke_extension":{"post":{"operationId":"ops.households.revoke_extension","summary":"Revoke a renewal extension","description":"Revoke a previously granted renewal extension. Changes the household's renewal entitlement back. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.revoke_extension/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRevokeExtensionInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRevokeExtensionOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.revoke_extension/preview":{"post":{"operationId":"ops.households.revoke_extension.preview","summary":"Preview: Revoke a renewal extension","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsRevokeExtensionInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.create_invoice":{"post":{"operationId":"ops.households.create_invoice","summary":"Create an ad-hoc invoice","description":"Create a miscellaneous invoice for a household with up to three line items. Moves money: needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.create_invoice/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreateInvoiceInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreateInvoiceOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.create_invoice/preview":{"post":{"operationId":"ops.households.create_invoice.preview","summary":"Preview: Create an ad-hoc invoice","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreateInvoiceInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.issue_credit":{"post":{"operationId":"ops.households.issue_credit","summary":"Issue a credit","description":"Issue an account credit to a household, to be applied against a future invoice. Moves money: needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.issue_credit/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsIssueCreditInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsIssueCreditOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.issue_credit/preview":{"post":{"operationId":"ops.households.issue_credit.preview","summary":"Preview: Issue a credit","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsIssueCreditInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.create_payable":{"post":{"operationId":"ops.households.create_payable","summary":"Queue a bond refund payable","description":"Queue a bond-refund check payable for a household; the treasurer approves and sends it separately. Moves money: needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.create_payable/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreatePayableInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreatePayableOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.create_payable/preview":{"post":{"operationId":"ops.households.create_payable.preview","summary":"Preview: Queue a bond refund payable","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsCreatePayableInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.add_to_waitlist":{"post":{"operationId":"ops.households.add_to_waitlist","summary":"Add a household to the waitlist","description":"Add a household to the membership waitlist. No member is notified by this action alone. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.add_to_waitlist/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddToWaitlistInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddToWaitlistOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.add_to_waitlist/preview":{"post":{"operationId":"ops.households.add_to_waitlist.preview","summary":"Preview: Add a household to the waitlist","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsAddToWaitlistInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_member":{"post":{"operationId":"ops.households.update_member","summary":"Update a member's profile","description":"Update a household member's name and email/SMS opt-in flags. Never touches phone, email, or login. Those are separate, more sensitive operations. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.update_member/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateMemberInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateMemberOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_member/preview":{"post":{"operationId":"ops.households.update_member.preview","summary":"Preview: Update a member's profile","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateMemberInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_dependent":{"post":{"operationId":"ops.households.update_dependent","summary":"Update a family member's details","description":"Correct a family member's (dependent's) name, birth date, relationship and copy-on-household-message flags. Never touches their email or phone. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/households.update_dependent/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateDependentInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateDependentOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_dependent/preview":{"post":{"operationId":"ops.households.update_dependent.preview","summary":"Preview: Update a family member's details","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateDependentInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_member_phone":{"post":{"operationId":"ops.households.update_member_phone","summary":"Change a member's phone number","description":"Change the phone number on file for a household member. A contact-destination change. Needs approval even though it sends no message itself. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.update_member_phone/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateMemberPhoneInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateMemberPhoneOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.update_member_phone/preview":{"post":{"operationId":"ops.households.update_member_phone.preview","summary":"Preview: Change a member's phone number","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsUpdateMemberPhoneInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.set_email_opt_in":{"post":{"operationId":"ops.households.set_email_opt_in","summary":"Bulk set email opt-in","description":"Set every member of up to 200 selected households' email opt-in flag on or off in one audited batch (directory bulk bar). Governs future marketing/member email. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.set_email_opt_in/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetEmailOptInInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetEmailOptInOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.set_email_opt_in/preview":{"post":{"operationId":"ops.households.set_email_opt_in.preview","summary":"Preview: Bulk set email opt-in","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetEmailOptInInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.set_sms_opt_in":{"post":{"operationId":"ops.households.set_sms_opt_in","summary":"Bulk set SMS opt-in","description":"Set every member of up to 200 selected households' SMS opt-in flag on or off in one audited batch (directory bulk bar). Governs future member texting. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/households.set_sms_opt_in/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetSmsOptInInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetSmsOptInOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/households.set_sms_opt_in/preview":{"post":{"operationId":"ops.households.set_sms_opt_in.preview","summary":"Preview: Bulk set SMS opt-in","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsHouseholdsSetSmsOptInInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.suspend":{"post":{"operationId":"ops.accounts.suspend","summary":"Suspend an account","description":"Pause a household's account: they can't sign in and receive no member messages until reactivated. Also disconnects any agent-access connection the household holds. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/accounts.suspend/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsSuspendInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsSuspendOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.suspend/preview":{"post":{"operationId":"ops.accounts.suspend.preview","summary":"Preview: Suspend an account","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsSuspendInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.unsuspend":{"post":{"operationId":"ops.accounts.unsuspend","summary":"Reactivate a suspended account","description":"Lift a suspension so the household can sign in and receive member messages again. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/accounts.unsuspend/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsUnsuspendInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsUnsuspendOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.unsuspend/preview":{"post":{"operationId":"ops.accounts.unsuspend.preview","summary":"Preview: Reactivate a suspended account","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsUnsuspendInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.close":{"post":{"operationId":"ops.accounts.close","summary":"Close an account","description":"Close a household's account for good (after any owed bond refund has been sent): no sign-in, no member messages of any kind. Reversible via reopen. Also disconnects any agent-access connection. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/accounts.close/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsCloseInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsCloseOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.close/preview":{"post":{"operationId":"ops.accounts.close.preview","summary":"Preview: Close an account","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsCloseInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.reopen":{"post":{"operationId":"ops.accounts.reopen","summary":"Reopen a closed account","description":"Reopen a closed household account so it can sign in and receive member messages again. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/accounts.reopen/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsReopenInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsReopenOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/accounts.reopen/preview":{"post":{"operationId":"ops.accounts.reopen.preview","summary":"Preview: Reopen a closed account","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsAccountsReopenInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.list":{"get":{"operationId":"ops.invoices.list","summary":"List invoices","description":"Search or list invoices in this club, optionally filtered to one household, with status, totals, and remaining balance.","security":[{"bearerAuth":[]}],"parameters":[{"name":"householdId","in":"query","required":false,"schema":{"description":"Restrict to one household's invoices.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"status","in":"query","required":false,"schema":{"description":"Invoice status filter.","type":"string","enum":["draft","open","processing","paid","void","uncollectible"]}},{"name":"kind","in":"query","required":false,"schema":{"description":"Invoice kind filter.","type":"string","enum":["dues","initiation","camp","merch","facility","event","misc","waitlist_fee","lesson"]}},{"name":"seasonYear","in":"query","required":false,"schema":{"description":"Filter to one season year.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},{"name":"query","in":"query","required":false,"schema":{"description":"Free text matched against invoice number or household name.","type":"string"}},{"name":"order","in":"query","required":false,"schema":{"default":"newest","description":"\"newest\" (default, most-recently-created first) or \"id\" (ascending, stable keyset paging).","type":"string","enum":["newest","id"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.get":{"get":{"operationId":"ops.invoices.get","summary":"Get an invoice","description":"Look up one invoice by id: status, totals, balance, line items, recorded payments, and credits issued from it.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The invoice id."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesGetOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.record_check":{"post":{"operationId":"ops.invoices.record_check","summary":"Record a check payment","description":"Record an offline check payment against an open invoice, up to its remaining balance. The check number is required so two genuinely different checks are never confused with a retried request. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/invoices.record_check/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesRecordCheckInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesRecordCheckOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.record_check/preview":{"post":{"operationId":"ops.invoices.record_check.preview","summary":"Preview: Record a check payment","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesRecordCheckInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.apply_credit":{"post":{"operationId":"ops.invoices.apply_credit","summary":"Apply a household credit to an invoice","description":"Apply an existing household account credit to a draft or open invoice, reducing the total due by the applied amount. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/invoices.apply_credit/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesApplyCreditInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesApplyCreditOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.apply_credit/preview":{"post":{"operationId":"ops.invoices.apply_credit.preview","summary":"Preview: Apply a household credit to an invoice","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesApplyCreditInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.add_adjustment":{"post":{"operationId":"ops.invoices.add_adjustment","summary":"Add an adjustment line to an invoice","description":"Append a correction line to a draft or open invoice (negative = waiver). Corrections are new lines, never edits. The total can't drop below zero or below what's already been paid. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/invoices.add_adjustment/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesAddAdjustmentInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesAddAdjustmentOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.add_adjustment/preview":{"post":{"operationId":"ops.invoices.add_adjustment.preview","summary":"Preview: Add an adjustment line to an invoice","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesAddAdjustmentInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.void":{"post":{"operationId":"ops.invoices.void","summary":"Void an invoice","description":"Void a draft or open invoice. Members can no longer pay a voided invoice. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/invoices.void/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesVoidInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesVoidOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.void/preview":{"post":{"operationId":"ops.invoices.void.preview","summary":"Preview: Void an invoice","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesVoidInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.refund":{"post":{"operationId":"ops.invoices.refund","summary":"Refund a Stripe payment","description":"Refund a succeeded card/ACH payment back to the member via Stripe. Dues and initiation/bond payments are blocked here. Those go back as an account credit or a check payable instead. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/invoices.refund/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesRefundInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesRefundOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.refund/preview":{"post":{"operationId":"ops.invoices.refund.preview","summary":"Preview: Refund a Stripe payment","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesRefundInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.bulk_create":{"post":{"operationId":"ops.invoices.bulk_create","summary":"Bulk create ad-hoc invoices","description":"Create a miscellaneous invoice for up to 200 households in one audited batch, each with up to 20 line items. Moves money: needs approval. A failed item does not abort the rest of the batch. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/invoices.bulk_create/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesBulkCreateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesBulkCreateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/invoices.bulk_create/preview":{"post":{"operationId":"ops.invoices.bulk_create.preview","summary":"Preview: Bulk create ad-hoc invoices","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsInvoicesBulkCreateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/payables.list":{"get":{"operationId":"ops.payables.list","summary":"List refund payables","description":"List the treasurer's refund-check queue (bond refunds and other payables), with amount, status, and check-sent date.","security":[{"bearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"description":"Payable status filter.","type":"string","enum":["pending","approved","check_sent","cleared","void"]}},{"name":"order","in":"query","required":false,"schema":{"default":"newest","description":"\"newest\" (default, most-recently-created first) or \"id\" (ascending, stable keyset paging).","type":"string","enum":["newest","id"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsPayablesListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/relinquishments.list":{"get":{"operationId":"ops.relinquishments.list","summary":"List relinquishments","description":"List membership relinquishment requests with status, effective season, and bond on deposit.","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/relinquishments.approve":{"post":{"operationId":"ops.relinquishments.approve","summary":"Approve a relinquishment","description":"Approve a membership relinquishment: voids the unpaid dues invoice, forfeits any late penalty from the bond, and queues the net refund as a check payable. Emails the household. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/relinquishments.approve/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsApproveInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsApproveOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/relinquishments.approve/preview":{"post":{"operationId":"ops.relinquishments.approve.preview","summary":"Preview: Approve a relinquishment","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsApproveInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/relinquishments.deny":{"post":{"operationId":"ops.relinquishments.deny","summary":"Deny a relinquishment","description":"Deny a membership relinquishment request. The membership year resumes dunning on its still-open dues invoice. Sends no email. Same as the admin console action; the household is told by staff, not auto-mailed. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/relinquishments.deny/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsDenyInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsDenyOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/relinquishments.deny/preview":{"post":{"operationId":"ops.relinquishments.deny.preview","summary":"Preview: Deny a relinquishment","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsRelinquishmentsDenyInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/memberships.list":{"get":{"operationId":"ops.memberships.list","summary":"List memberships","description":"List households' current memberships with tier, status, and this renewal period's state (upcoming, invoiced, paid, delinquent, and so on).","security":[{"bearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"description":"Filter to one membership status.","type":"string","enum":["pending","active","lapsed","relinquished","terminated"]}},{"name":"renewalState","in":"query","required":false,"schema":{"description":"Filter to one renewal state for the current period.","type":"string","enum":["upcoming","invoiced","reminding","processing_payment","paid","relinquish_notice","bond_payable","closed_relinquished","delinquent","terminated"]}},{"name":"tier","in":"query","required":false,"schema":{"description":"Filter to one membership tier key.","type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsMembershipsListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.list":{"get":{"operationId":"ops.waitlist.list","summary":"List the waitlist","description":"List the ordered join-waitlist: household, position, residency, status, when they applied, and any pending offer's expiry.","security":[{"bearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"description":"Filter to one waitlist status.","type":"string","enum":["waiting","offered","accepted","declined","expired","withdrawn","removed"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.reorder":{"post":{"operationId":"ops.waitlist.reorder","summary":"Reorder the waitlist","description":"Move one waitlist entry to an explicit new position. Every reorder is audited with before/after. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/waitlist.reorder/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistReorderInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistReorderOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.reorder/preview":{"post":{"operationId":"ops.waitlist.reorder.preview","summary":"Preview: Reorder the waitlist","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistReorderInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.offer":{"post":{"operationId":"ops.waitlist.offer","summary":"Offer a waitlist spot","description":"Make a membership offer to the next household on the waitlist. Emails (and, if configured, texts) the household with the accept link. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/waitlist.offer/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistOfferInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistOfferOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.offer/preview":{"post":{"operationId":"ops.waitlist.offer.preview","summary":"Preview: Offer a waitlist spot","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistOfferInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.offer_batch":{"post":{"operationId":"ops.waitlist.offer_batch","summary":"Send offers to the top of the waitlist","description":"Make a membership offer to the top N households waiting in line, in position order, emailing (and, if configured, texting) each one — the same as sending one offer, repeated. Offers fewer than N if fewer households are waiting; never sends nothing without saying so. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/waitlist.offer_batch/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistOfferBatchInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistOfferBatchOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.offer_batch/preview":{"post":{"operationId":"ops.waitlist.offer_batch.preview","summary":"Preview: Send offers to the top of the waitlist","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistOfferBatchInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.resend_offer":{"post":{"operationId":"ops.waitlist.resend_offer","summary":"Resend a waitlist offer","description":"Resend a pending waitlist offer email with a freshly-minted accept link; the previously-emailed link stops working: needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/waitlist.resend_offer/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistResendOfferInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistResendOfferOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/waitlist.resend_offer/preview":{"post":{"operationId":"ops.waitlist.resend_offer.preview","summary":"Preview: Resend a waitlist offer","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsWaitlistResendOfferInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.list":{"get":{"operationId":"ops.camp.weeks.list","summary":"List camp weeks","description":"List this club's camp weeks with dates, capacity, how many are registered, how many are waitlisted, and status.","security":[{"bearerAuth":[]}],"parameters":[{"name":"seasonYear","in":"query","required":false,"schema":{"description":"Filter to one season year; omit for every season.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.get":{"get":{"operationId":"ops.camp.weeks.get","summary":"Get a camp week","description":"Look up one camp week by id: dates, age range, capacity, price, status, and live/all-time registration counts.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The camp week's id."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksGetOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.list":{"get":{"operationId":"ops.camp.registrations.list","summary":"List camp week registrations","description":"List the roster for one camp week: swimmer and household name, age, registration status, payment status, and whether intake is complete.","security":[{"bearerAuth":[]}],"parameters":[{"name":"weekId","in":"query","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":500}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsListOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.create":{"post":{"operationId":"ops.camp.weeks.create","summary":"Create a camp week","description":"Create a new camp week (draft status) with dates, age range, capacity, and price. Registration opens once the week is set to open. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/camp.weeks.create/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksCreateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksCreateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.create/preview":{"post":{"operationId":"ops.camp.weeks.create.preview","summary":"Preview: Create a camp week","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksCreateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.update":{"post":{"operationId":"ops.camp.weeks.update","summary":"Update a camp week","description":"Edit a camp week's label, dates, age range, capacity, and price. Price changes apply only to future registrations. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/camp.weeks.update/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksUpdateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksUpdateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.update/preview":{"post":{"operationId":"ops.camp.weeks.update.preview","summary":"Preview: Update a camp week","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksUpdateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.set_status":{"post":{"operationId":"ops.camp.weeks.set_status","summary":"Open or close a camp week","description":"Move a camp week between draft/open/closed (registration open/closed). Canceling or archiving a week are separate, more heavily confirmed operations. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/camp.weeks.set_status/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksSetStatusInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksSetStatusOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.set_status/preview":{"post":{"operationId":"ops.camp.weeks.set_status.preview","summary":"Preview: Open or close a camp week","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksSetStatusInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.archive":{"post":{"operationId":"ops.camp.weeks.archive","summary":"Archive a completed camp week","description":"Archive a closed, already-ended camp week to preserve its roster and financial history while removing it from active operations. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/camp.weeks.archive/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksArchiveInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksArchiveOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.archive/preview":{"post":{"operationId":"ops.camp.weeks.archive.preview","summary":"Preview: Archive a completed camp week","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksArchiveInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.attendance.set":{"post":{"operationId":"ops.camp.attendance.set","summary":"Mark camp attendance","description":"Mark one camp registration present or absent for one day of its week. Never visible to members. Trivia, executes immediately. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/camp.attendance.set/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampAttendanceSetInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampAttendanceSetOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.attendance.set/preview":{"post":{"operationId":"ops.camp.attendance.set.preview","summary":"Preview: Mark camp attendance","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampAttendanceSetInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.waitlist.reorder":{"post":{"operationId":"ops.camp.waitlist.reorder","summary":"Reorder a camp waitlist entry","description":"Move one household to a new position in a camp week's waitlist queue. Silent: no household is notified of a reorder. Tier 2: if a two-step confirm is required, first call `POST /api/v1/ops/camp.waitlist.reorder/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistReorderInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistReorderOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.waitlist.reorder/preview":{"post":{"operationId":"ops.camp.waitlist.reorder.preview","summary":"Preview: Reorder a camp waitlist entry","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistReorderInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.cancel":{"post":{"operationId":"ops.camp.weeks.cancel","summary":"Cancel a camp week","description":"Cancel an entire camp week: closes registration, refunds or credits every registered household, and closes the waitlist. Emails every affected household. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/camp.weeks.cancel/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksCancelInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksCancelOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.weeks.cancel/preview":{"post":{"operationId":"ops.camp.weeks.cancel.preview","summary":"Preview: Cancel a camp week","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWeeksCancelInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.create":{"post":{"operationId":"ops.camp.registrations.create","summary":"Register a swimmer for camp","description":"Register a household's dependent for a camp week, creating an invoice for the seat. Confirms by email to the household: needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/camp.registrations.create/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsCreateInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsCreateOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.create/preview":{"post":{"operationId":"ops.camp.registrations.create.preview","summary":"Preview: Register a swimmer for camp","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsCreateInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.cancel":{"post":{"operationId":"ops.camp.registrations.cancel","summary":"Cancel a camp registration","description":"Cancel one household's camp registration and refund or credit them per the cancellation policy. Emails the household: needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/camp.registrations.cancel/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsCancelInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsCancelOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.cancel/preview":{"post":{"operationId":"ops.camp.registrations.cancel.preview","summary":"Preview: Cancel a camp registration","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsCancelInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.transfer":{"post":{"operationId":"ops.camp.registrations.transfer","summary":"Transfer a camp registration to another week","description":"Move one household's camp registration to a different week, issuing a credit or invoice for the price difference. Emails the household. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/camp.registrations.transfer/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsTransferInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsTransferOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.registrations.transfer/preview":{"post":{"operationId":"ops.camp.registrations.transfer.preview","summary":"Preview: Transfer a camp registration to another week","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampRegistrationsTransferInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.waitlist.promote":{"post":{"operationId":"ops.camp.waitlist.promote","summary":"Offer the next camp waitlist spot","description":"Offer an open camp week spot to the next household on the waitlist. Emails the household. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/camp.waitlist.promote/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistPromoteInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistPromoteOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.waitlist.promote/preview":{"post":{"operationId":"ops.camp.waitlist.promote.preview","summary":"Preview: Offer the next camp waitlist spot","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistPromoteInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.waitlist.remove":{"post":{"operationId":"ops.camp.waitlist.remove","summary":"Remove a household from a camp waitlist","description":"Remove one household from a camp week's waitlist. If the entry currently holds an offer, removing it can auto-advance and email the next household. Needs approval. Tier 3: if a two-step confirm is required, first call `POST /api/v1/ops/camp.waitlist.remove/preview` (same body) to get a preview and a confirmation token, then resend this request with `confirmationToken` set.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on every ops write. Retrying with the same key and an identical body replays the original response without re-executing; reusing a key with a different body returns 409 (`conflict`). The key is claimed before the work runs, so a duplicate sent while the first request is still running returns 409 (`in_progress`) with `Retry-After` instead of executing twice: retry with the same key to collect the stored response. If the original request's executor is abandoned mid-execution (worker eviction, request abort), the claim is marked failed rather than silently re-run. Further requests with that key return 409 (`stale_claim`); inspect state and retry with a *new* Idempotency-Key."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistRemoveInput"}}}},"responses":{"200":{"description":"OK, or { status: \"needs_confirmation\", preview, confirmationToken } for a tier-2 op's first call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistRemoveOutput"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}},"/api/v1/ops/camp.waitlist.remove/preview":{"post":{"operationId":"ops.camp.waitlist.remove.preview","summary":"Preview: Remove a household from a camp waitlist","description":"Tier >= 2, confirm:\"token\" only. Returns a human-readable preview and a confirmationToken bound to this input's hash and this credential. Single-use and valid for 10 minutes. Pass both the original body and the token to the non-preview route to execute; a `confirm:\"preview-only\"` operation has no separate preview step and 404s here. Never messages a member or moves anything itself.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsCampWaitlistRemoveInput"}}}},"responses":{"200":{"description":"{ summary, digest, confirmationToken }","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"invalid_input: the request body/query didn't match the operation's schema."},"401":{"description":"Missing/invalid API key."},"403":{"description":"scope_denied or role_denied. The key/grant lacks the scope, or the caller's role can't run this operation."},"404":{"description":"not_found: no such operation is exposed on /api/v1, or the entity id doesn't exist."},"409":{"description":"tier_confirmation_required. This operation needs a two-step confirm (POST /ops/<name>/preview first) or a batch approval; also the Idempotency-Key conflict/in_progress/stale_claim triad on writes."},"429":{"description":"Rate limit exceeded for this API key; see `Retry-After`."},"500":{"description":"internal: something failed inside the operation; never leaks internals."}}}}}}