{"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"},"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"},"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"},"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"},"status":{"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"},"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"},"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"},"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"},"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"},"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"]}},"/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/{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"]}},"/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"]}},"/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"]}},"/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"]}},"/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","name":"Follow-ups"},{"description":"Scope: volunteers:read / volunteers:write","name":"Volunteers"},{"description":"Scope: house_fellowships:read","name":"House Fellowships"},{"description":"Scope: tasks:read / tasks:write","name":"Tasks"}]}
