{"components":{"schemas":{"ActionItem":{"properties":{"created_at":{"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"id":{"type":"integer"},"program_id":{"type":"integer"},"status":{"enum":["backlog","in_progress","review","done"],"type":"string"},"title":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"AttendanceRecord":{"properties":{"adults":{"type":"integer"},"children":{"type":"integer"},"context":{"enum":["service","hf"],"type":"string"},"fellowship":{"nullable":true,"type":"string"},"id":{"type":"integer"},"newcomers":{"type":"integer"},"record_date":{"format":"date","type":"string"},"service_type":{"nullable":true,"type":"string"},"teens":{"type":"integer"}},"type":"object"},"AttendanceRecordInput":{"properties":{"adults":{"default":0,"type":"integer"},"children":{"default":0,"type":"integer"},"context":{"enum":["service","hf"],"type":"string"},"fellowship":{"description":"Required when context is 'hf'","type":"string"},"newcomers":{"default":0,"type":"integer"},"note":{"type":"string"},"record_date":{"format":"date","type":"string"},"service_type":{"description":"Required when context is 'service'","type":"string"},"teens":{"default":0,"type":"integer"}},"required":["context","record_date"],"type":"object"},"Collection":{"properties":{"amount_cents":{"type":"integer"},"currency":{"type":"string"},"donor_name":{"description":"Present only with collections:donor scope","nullable":true,"type":"string"},"fund_id":{"nullable":true,"type":"integer"},"id":{"type":"integer"},"is_anonymous":{"type":"boolean"},"method":{"nullable":true,"type":"string"},"service_date":{"format":"date","type":"string"},"status":{"type":"string"}},"type":"object"},"DirectoryPerson":{"properties":{"address":{"description":"directory:address scope","nullable":true,"type":"string"},"anniversary_mmdd":{"description":"directory:sensitive scope","nullable":true,"type":"string"},"birthday_mmdd":{"description":"directory:sensitive scope","nullable":true,"type":"string"},"created_at":{"format":"date-time","nullable":true,"type":"string"},"department":{"nullable":true,"type":"string"},"email":{"description":"directory:contact scope","nullable":true,"type":"string"},"first_name":{"nullable":true,"type":"string"},"gender":{"nullable":true,"type":"string"},"house_fellowship_id":{"nullable":true,"type":"integer"},"household_id":{"description":"directory:sensitive scope","nullable":true,"type":"integer"},"id":{"type":"integer"},"last_name":{"nullable":true,"type":"string"},"phone":{"description":"directory:contact scope","nullable":true,"type":"string"}},"type":"object"},"DirectoryPersonInput":{"properties":{"address":{"type":"string"},"anniversary_mmdd":{"description":"Format DD-MM","type":"string"},"birthday_mmdd":{"description":"Format DD-MM, e.g. '25-12'","type":"string"},"department":{"type":"string"},"email":{"type":"string"},"first_name":{"type":"string"},"gender":{"type":"string"},"house_fellowship_id":{"type":"integer"},"last_name":{"type":"string"},"notes":{"type":"string"},"phone":{"type":"string"}},"required":["first_name","last_name"],"type":"object"},"Error":{"properties":{"error":{"type":"string"},"message":{"nullable":true,"type":"string"},"missing_scopes":{"items":{"type":"string"},"nullable":true,"type":"array"}},"type":"object"},"Expense":{"properties":{"amount_cents":{"type":"integer"},"category_id":{"nullable":true,"type":"integer"},"currency":{"type":"string"},"expense_date":{"nullable":true,"type":"string"},"fund_id":{"nullable":true,"type":"integer"},"id":{"type":"integer"},"method":{"nullable":true,"type":"string"},"paid_at":{"format":"date-time","nullable":true,"type":"string"},"payee_name":{"nullable":true,"type":"string"},"status":{"description":"Free-text, human-set. Confirmed values in use: approved, rejected, void, paid -- not a fixed enum.","type":"string"},"vendor_id":{"nullable":true,"type":"integer"}},"type":"object"},"FollowUp":{"properties":{"assigned_to":{"nullable":true,"type":"string"},"category":{"nullable":true,"type":"string"},"created_at":{"format":"date-time","type":"string"},"email":{"nullable":true,"type":"string"},"id":{"type":"integer"},"name":{"type":"string"},"note":{"nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"stage":{"description":"Canonical stage bucket. Note: 'pastor_spoke' is displayed as \u201cContacted\u201d everywhere in the ChurchOps UI.","enum":["open","in_progress","pastor_spoke","promoted","closed","archived"],"type":"string"},"status":{"description":"Raw status value stored in ChurchOps","type":"string"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"FollowUpInput":{"properties":{"assigned_to":{"type":"string"},"category":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"note":{"type":"string"},"phone":{"type":"string"},"status":{"default":"open","type":"string"}},"required":["name"],"type":"object"},"FollowUpStageEvent":{"properties":{"followup_id":{"type":"integer"},"from_stage":{"description":"Null for the initial creation event","nullable":true,"type":"string"},"moved_at":{"format":"date-time","type":"string"},"to_stage":{"type":"string"}},"type":"object"},"HouseFellowship":{"properties":{"address":{"nullable":true,"type":"string"},"area":{"nullable":true,"type":"string"},"id":{"type":"integer"},"leader_name":{"nullable":true,"type":"string"},"leader_phone":{"nullable":true,"type":"string"},"name":{"type":"string"}},"type":"object"},"KnowledgePage":{"properties":{"created_at":{"nullable":true,"type":"string"},"created_by":{"nullable":true,"type":"string"},"id":{"type":"integer"},"space_id":{"type":"integer"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"nullable":true,"type":"string"},"updated_by":{"nullable":true,"type":"string"},"visibility_scope":{"description":"PRIVATE pages are excluded entirely, never returned","enum":["CAMPUS","TENANT","PUBLIC_LINK"],"type":"string"}},"type":"object"},"KnowledgeSpace":{"properties":{"created_at":{"nullable":true,"type":"string"},"description":{"nullable":true,"type":"string"},"id":{"type":"integer"},"name":{"type":"string"},"space_key":{"nullable":true,"type":"string"},"updated_at":{"nullable":true,"type":"string"}},"type":"object"},"NamedLookup":{"properties":{"id":{"type":"integer"},"is_active":{"type":"boolean"},"name":{"type":"string"}},"type":"object"},"Program":{"properties":{"created_at":{"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"end_date":{"format":"date","nullable":true,"type":"string"},"id":{"type":"integer"},"start_date":{"format":"date","nullable":true,"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"ResourceAsset":{"properties":{"asset_tag":{"nullable":true,"type":"string"},"category":{"type":"string"},"condition":{"type":"string"},"custodian":{"nullable":true,"type":"string"},"id":{"type":"integer"},"location":{"nullable":true,"type":"string"},"name":{"type":"string"},"purchase_cost":{"nullable":true,"type":"number"},"purchase_date":{"nullable":true,"type":"string"},"serial_number":{"nullable":true,"type":"string"},"status":{"enum":["AVAILABLE","IN_USE","UNDER_REPAIR","MISSING","RETIRED"],"type":"string"}},"type":"object"},"ResourceCheckout":{"properties":{"asset_id":{"type":"integer"},"checked_in_at":{"format":"date-time","nullable":true,"type":"string"},"checked_out_at":{"format":"date-time","type":"string"},"checked_out_to":{"nullable":true,"type":"string"},"due_back_at":{"description":"Always null -- never written by ChurchOps","format":"date-time","nullable":true,"type":"string"},"id":{"type":"integer"},"needed_date":{"nullable":true,"type":"string"},"purpose":{"nullable":true,"type":"string"},"status":{"enum":["OUT","RETURNED"],"type":"string"}},"type":"object"},"ResourceMaintenance":{"properties":{"asset_id":{"type":"integer"},"closed_at":{"format":"date-time","nullable":true,"type":"string"},"cost":{"nullable":true,"type":"number"},"id":{"type":"integer"},"issue":{"type":"string"},"opened_at":{"format":"date-time","type":"string"},"status":{"enum":["OPEN","CLOSED"],"type":"string"},"vendor":{"nullable":true,"type":"string"}},"type":"object"},"ResourceRequest":{"properties":{"created_at":{"format":"date-time","type":"string"},"department":{"type":"string"},"event_title":{"nullable":true,"type":"string"},"id":{"type":"integer"},"needed_date":{"type":"string"},"needed_end_time":{"nullable":true,"type":"string"},"needed_start_time":{"nullable":true,"type":"string"},"requested_by":{"type":"string"},"status":{"enum":["SUBMITTED","APPROVED","FULFILLED","CLOSED","REJECTED"],"type":"string"}},"type":"object"},"ResourceSupply":{"properties":{"approval_threshold":{"nullable":true,"type":"number"},"category":{"type":"string"},"current_stock":{"type":"number"},"id":{"type":"integer"},"is_low":{"description":"Computed: current_stock <= min_stock","type":"boolean"},"min_stock":{"type":"number"},"name":{"type":"string"},"storage_location":{"nullable":true,"type":"string"},"unit":{"type":"string"},"unit_price":{"nullable":true,"type":"number"}},"type":"object"},"ResourceSupplyMovement":{"properties":{"department":{"nullable":true,"type":"string"},"id":{"type":"integer"},"item_id":{"type":"integer"},"movement_type":{"enum":["RECEIVE","ISSUE","ADJUST"],"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"quantity":{"description":"Positive for RECEIVE, negative for ISSUE, either for ADJUST","type":"number"},"unit":{"nullable":true,"type":"string"}},"type":"object"},"Survey":{"properties":{"closed_at":{"format":"date-time","nullable":true,"type":"string"},"created_at":{"format":"date-time","nullable":true,"type":"string"},"id":{"type":"integer"},"identification_mode":{"enum":["anonymous","optional","required"],"type":"string"},"is_template":{"description":"True if saved as a reusable template (global or personal). Still one of the tenant's own forms either way.","type":"boolean"},"published_at":{"format":"date-time","nullable":true,"type":"string"},"question_count":{"type":"integer"},"response_count":{"type":"integer"},"slug":{"type":"string"},"status":{"enum":["draft","published","closed"],"type":"string"},"title":{"type":"string"},"updated_at":{"format":"date-time","nullable":true,"type":"string"}},"type":"object"},"SurveyResponse":{"properties":{"id":{"type":"integer"},"respondent_email":{"description":"surveys:respondent scope","nullable":true,"type":"string"},"respondent_name":{"description":"Present only with surveys:respondent scope, and only if the form's identification_mode isn't anonymous","nullable":true,"type":"string"},"respondent_phone":{"description":"surveys:respondent scope","nullable":true,"type":"string"},"submitted_at":{"format":"date-time","nullable":true,"type":"string"},"survey_id":{"type":"integer"}},"type":"object"},"Task":{"properties":{"action_item_id":{"type":"integer"},"completed":{"type":"boolean"},"created_at":{"format":"date-time","type":"string"},"id":{"type":"integer"},"status":{"enum":["backlog","in_progress","review","done"],"type":"string"},"title":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"TaskInput":{"properties":{"action_item_id":{"type":"integer"},"status":{"default":"backlog","type":"string"},"title":{"type":"string"}},"required":["title","action_item_id"],"type":"object"},"TransportRequest":{"properties":{"id":{"type":"integer"},"party_size":{"type":"integer"},"postal_fsa":{"nullable":true,"type":"string"},"self_arranged":{"type":"boolean"},"service_datetime":{"type":"string"},"service_label":{"nullable":true,"type":"string"},"status":{"enum":["new","partial","allocated","self_arranged"],"type":"string"},"volunteer_driver":{"type":"boolean"}},"type":"object"},"TransportVehicle":{"properties":{"active":{"type":"boolean"},"driver_name":{"nullable":true,"type":"string"},"id":{"type":"integer"},"label":{"type":"string"},"seat_capacity":{"type":"integer"}},"type":"object"},"Volunteer":{"properties":{"departments":{"items":{"type":"string"},"type":"array"},"email":{"nullable":true,"type":"string"},"first_name":{"type":"string"},"id":{"type":"integer"},"last_name":{"type":"string"},"phone":{"nullable":true,"type":"string"},"role":{"nullable":true,"type":"string"},"status":{"enum":["Active","Inactive"],"type":"string"},"title":{"nullable":true,"type":"string"}},"type":"object"},"VolunteerApplication":{"properties":{"approved_at":{"format":"date-time","nullable":true,"type":"string"},"created_at":{"format":"date-time","type":"string"},"id":{"type":"integer"},"preferred_departments":{"items":{"type":"string"},"type":"array"},"status":{"description":"Free-vocabulary in practice: new, pending, contacted, accepted, approved, rejected, update_request.","type":"string"},"updated_at":{"format":"date-time","nullable":true,"type":"string"}},"type":"object"},"VolunteerInput":{"properties":{"departments":{"items":{"type":"string"},"type":"array"},"email":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"phone":{"type":"string"},"role":{"type":"string"},"status":{"default":"Active","type":"string"},"title":{"type":"string"}},"required":["first_name","last_name"],"type":"object"}},"securitySchemes":{"bearerAuth":{"description":"API key generated from Settings \u2192 API & Webhooks. Each key is limited to the scopes chosen when it was created.","scheme":"bearer","type":"http"}}},"info":{"description":"Self-serve REST API for ChurchOps tenants. Keep your existing membership/giving system and pull ChurchOps-only data (Action Items, Attendance, Directory, Follow-ups, Volunteers, Tasks, Programs, Collections, House Fellowships) into Zapier, Google Sheets, or your own tools -- or push data back in.\n\nGenerate an API key from **Settings \u2192 API & Webhooks** inside ChurchOps, then send it as `Authorization: Bearer <key>` on every request. See the Quickstart at /developers for copy-paste examples in curl, JavaScript, and Python.","title":"ChurchOps API","version":"v1"},"openapi":"3.0.3","paths":{"/action-items":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ActionItem"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List action items","tags":["Action Items"]},"post":{"description":"Requires `action_items:write`. Fires an `action_item.created` webhook.","requestBody":{"content":{"application/json":{"schema":{"properties":{"description":{"type":"string"},"program_id":{"type":"integer"},"status":{"default":"backlog","type":"string"},"title":{"type":"string"}},"required":["title","program_id"],"type":"object"}}},"required":true},"responses":{"201":{"description":"Created"},"400":{"description":"Validation error"}},"summary":"Create an action item","tags":["Action Items"]}},"/action-items/{item_id}":{"get":{"parameters":[{"in":"path","name":"item_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one action item","tags":["Action Items"]},"patch":{"description":"Requires `action_items:write`. Fires `action_item.status_updated` if `status` changes.","parameters":[{"in":"path","name":"item_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"description":{"type":"string"},"status":{"type":"string"},"title":{"type":"string"}},"type":"object"}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Update an action item","tags":["Action Items"]}},"/attendance":{"get":{"description":"Aggregate service/house-fellowship counts only -- no individual names.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AttendanceRecord"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List attendance records","tags":["Attendance"]},"post":{"description":"Requires `attendance:write`. No update endpoint -- a duplicate (same date/service/fellowship) is rejected with 409 rather than overwritten. Fires `attendance.recorded`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttendanceRecordInput"}}},"required":true},"responses":{"201":{"description":"Created"},"409":{"description":"A record already exists for this date/service"}},"summary":"Log a new attendance record","tags":["Attendance"]}},"/collections":{"get":{"description":"Requires `collections:read`. Add `collections:donor` to include the donor's display name (respects anonymous giving).","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Collection"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List giving records","tags":["Collections & Giving"]}},"/collections/{collection_id}":{"get":{"parameters":[{"in":"path","name":"collection_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one giving record","tags":["Collections & Giving"]}},"/directory":{"get":{"description":"Requires `directory:basic`. Add `directory:contact`, `directory:address`, or `directory:sensitive` to include those fields.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DirectoryPerson"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key is missing a required scope"}},"summary":"List directory people","tags":["Directory"]},"post":{"description":"Requires `directory:write`. Fires a `directory.created` webhook.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectoryPersonInput"}}},"required":true},"responses":{"201":{"description":"Created"},"400":{"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing or invalid API key"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Key is missing a required scope"}},"summary":"Add a person to the directory","tags":["Directory"]}},"/directory/{person_id}":{"get":{"parameters":[{"in":"path","name":"person_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one directory person","tags":["Directory"]},"patch":{"description":"Requires `directory:write`. Fires a `directory.updated` webhook. Send only the fields you want to change.","parameters":[{"in":"path","name":"person_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirectoryPersonInput"}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Update a directory person","tags":["Directory"]}},"/expense-categories":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/NamedLookup"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List expense categories","tags":["Expenses"]}},"/expenses":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Expense"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List expenses","tags":["Expenses"]}},"/followups":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/FollowUp"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List follow-ups","tags":["Follow-ups"]},"post":{"description":"Requires `followups:write`. Fires `followup.created`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FollowUpInput"}}},"required":true},"responses":{"201":{"description":"Created"},"400":{"description":"Validation error"}},"summary":"Create a follow-up","tags":["Follow-ups"]}},"/followups/stage-history":{"get":{"description":"Requires `followups:history`. Every recorded stage transition (e.g. open \u2192 pastor_spoke, shown as \u201cContacted\u201d in ChurchOps) with a real timestamp -- use this instead of created_at/updated_at to compute accurate time-in-stage metrics.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/FollowUpStageEvent"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"Real stage-change timestamps","tags":["Follow-ups"]}},"/followups/{followup_id}":{"get":{"parameters":[{"in":"path","name":"followup_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one follow-up","tags":["Follow-ups"]},"patch":{"description":"Requires `followups:write`. Fires `followup.status_updated` if `status` changes.","parameters":[{"in":"path","name":"followup_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FollowUpInput"}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Update a follow-up","tags":["Follow-ups"]}},"/funds":{"get":{"description":"Also usable to resolve Collection.fund_id to a real fund name.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/NamedLookup"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List funds","tags":["Expenses"]}},"/house-fellowships":{"get":{"description":"Read-only. No pagination -- house fellowship counts are small.","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/HouseFellowship"},"type":"array"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List active house fellowships","tags":["House Fellowships"]}},"/knowledge/pages":{"get":{"description":"Requires `knowledge:read`. Excludes PRIVATE-visibility pages -- an API key isn't a specific logged-in person, so there's no correct owner check to apply to personal notes.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/KnowledgePage"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List knowledge base pages","tags":["Knowledge Base"]}},"/knowledge/spaces":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/KnowledgeSpace"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List knowledge base spaces","tags":["Knowledge Base"]}},"/programs":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Program"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List programs","tags":["Programs"]}},"/programs/{program_id}":{"get":{"parameters":[{"in":"path","name":"program_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one program","tags":["Programs"]}},"/resources/assets":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ResourceAsset"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List assets","tags":["Resources"]}},"/resources/checkouts":{"get":{"description":"Checkout history. `due_back_at` exists on the table but is never populated by ChurchOps, so it is always null -- don't build overdue logic on it.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ResourceCheckout"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List asset checkouts","tags":["Resources"]}},"/resources/maintenance":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ResourceMaintenance"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List maintenance tickets","tags":["Resources"]}},"/resources/requests":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ResourceRequest"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List resource requests","tags":["Resources"]}},"/resources/supplies":{"get":{"description":"Includes a computed `is_low` flag (current_stock <= min_stock), matching how ChurchOps's own Supplies page flags low stock.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ResourceSupply"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List supply items","tags":["Resources"]}},"/resources/supply-movements":{"get":{"description":"RECEIVE / ISSUE / ADJUST history with real timestamps -- lets a consumer compute consumption rate and project stockout dates, which current_stock alone can't show.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ResourceSupplyMovement"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List stock movements","tags":["Resources"]}},"/surveys":{"get":{"description":"Requires `surveys:read`. Includes the tenant's own personal templates (is_template: true) alongside regular forms, matching how ChurchOps's own Forms list shows them.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Survey"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List forms","tags":["Forms & Surveys"]}},"/surveys/responses":{"get":{"description":"Requires `surveys:read`. Add `surveys:respondent` to include respondent_name/email/phone (only ever populated for forms with identification_mode other than anonymous). Individual question answers are never included, regardless of scope.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SurveyResponse"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List responses across all forms","tags":["Forms & Surveys"]}},"/surveys/{survey_id}":{"get":{"parameters":[{"in":"path","name":"survey_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one form","tags":["Forms & Surveys"]}},"/tasks":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Task"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List tasks","tags":["Tasks"]},"post":{"description":"Requires `tasks:write`. Fires `task.created`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskInput"}}},"required":true},"responses":{"201":{"description":"Created"},"400":{"description":"Validation error"}},"summary":"Create a task under an action item","tags":["Tasks"]}},"/tasks/{task_id}":{"get":{"parameters":[{"in":"path","name":"task_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one task","tags":["Tasks"]},"patch":{"description":"Requires `tasks:write`. Setting status to 'done' also marks `completed: true`. Fires `task.status_updated` if `status` changes.","parameters":[{"in":"path","name":"task_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"status":{"type":"string"},"title":{"type":"string"}},"type":"object"}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Update a task","tags":["Tasks"]}},"/transport/requests":{"get":{"description":"Home address, phone, and email are deliberately excluded -- only area-level (postal FSA) location is included.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TransportRequest"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List ride requests","tags":["Transport"]}},"/transport/vehicles":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TransportVehicle"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List vehicles","tags":["Transport"]}},"/vendors":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/NamedLookup"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List vendors","tags":["Expenses"]}},"/volunteer-applications":{"get":{"description":"The recruitment pipeline feeding the Volunteer roster. Status is free-vocabulary in practice (new, pending, contacted, accepted, approved, rejected, update_request), confirmed against the real validation code, not the model's stale inline comment.","parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/VolunteerApplication"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List volunteer applications","tags":["Volunteer Applications"]}},"/volunteers":{"get":{"parameters":[{"in":"query","name":"page","schema":{"default":1,"type":"integer"}},{"in":"query","name":"per_page","schema":{"default":50,"maximum":200,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Volunteer"},"type":"array"},"page":{"type":"integer"},"per_page":{"type":"integer"},"total":{"type":"integer"}},"type":"object"}}},"description":"OK"}},"summary":"List volunteers","tags":["Volunteers"]},"post":{"description":"Requires `volunteers:write`. Fires `volunteer.created`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolunteerInput"}}},"required":true},"responses":{"201":{"description":"Created"},"400":{"description":"Validation error"}},"summary":"Add a volunteer","tags":["Volunteers"]}},"/volunteers/{volunteer_id}":{"get":{"parameters":[{"in":"path","name":"volunteer_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Get one volunteer","tags":["Volunteers"]},"patch":{"description":"Requires `volunteers:write`. Fires `volunteer.updated`.","parameters":[{"in":"path","name":"volunteer_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolunteerInput"}}}},"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}},"summary":"Update a volunteer","tags":["Volunteers"]}}},"security":[{"bearerAuth":[]}],"servers":[{"url":"/api/v1"}],"tags":[{"description":"Scope: directory:basic (+contact/address/sensitive/write)","name":"Directory"},{"description":"Scope: action_items:read / action_items:write","name":"Action Items"},{"description":"Scope: attendance:read / attendance:write","name":"Attendance"},{"description":"Scope: programs:read","name":"Programs"},{"description":"Scope: collections:read (+collections:donor)","name":"Collections & Giving"},{"description":"Scope: followups:read / followups:write / followups:history","name":"Follow-ups"},{"description":"Scope: volunteers:read / volunteers:write","name":"Volunteers"},{"description":"Scope: volunteers:read","name":"Volunteer Applications"},{"description":"Scope: house_fellowships:read","name":"House Fellowships"},{"description":"Scope: knowledge:read","name":"Knowledge Base"},{"description":"Scope: resources:read","name":"Resources"},{"description":"Scope: transport:read","name":"Transport"},{"description":"Scope: expenses:read","name":"Expenses"},{"description":"Scope: tasks:read / tasks:write","name":"Tasks"},{"description":"Scope: surveys:read (+surveys:respondent). Individual question answers are never exposed via the API, regardless of scope.","name":"Forms & Surveys"}]}
