← Back to Documentation Home

Integration Summary

Church Management Platform provides a fully integrated, two-way API connection with Planning Center Online (PCO), a widely-used church management platform. This integration synchronizes people, families, and groups between both systems, ensuring data stays consistent regardless of where changes originate.

2-Way
Sync Direction
6
Inbound Sync Types
4
Outbound Push Types
3
Webhook Events
Full Replacement Capability This integration is designed to fully replace Planning Center as the primary people and group management system. Church Management Platform serves as the system of record, with PCO maintained as a synchronized mirror. All people, families, and group membership data flows bidirectionally, while check-in operations happen natively in Church Management Platform.

What Gets Synced

DataInbound (PCO → Local)Outbound (Local → PCO)
People (demographics, contacts) Pull Push
Families / Households Pull Push
Groups Pull Read-Only in PCO
Group Memberships Pull Push
Check-In Records Read Not Writable
Calendar Events Read Not Writable

PCO API Overview

Planning Center Online exposes a REST API conforming to the JSON:API 1.0 specification. Each PCO product module has its own versioned API endpoint. The API supports sideloading related resources (?include=), field-level filtering (?where[field]=value), ordering, and cursor-based pagination (max 100 per page).

6
API Modules
100
Requests / Minute
JSON:API
Spec Format
PAT + OAuth
Auth Methods

Key Query Features

  • Sideloading: ?include=emails,phone_numbers — fetch related resources in a single request.
  • Filtering: ?where[first_name]=John or ?where[updated_at][gte]=... for incremental sync.
  • Search: ?where[search_name_or_email_or_phone_number]=... — combined search.
  • Ordering: ?order=last_name or ?order=-created_at (descending).
  • Pagination: ?per_page=100 (max 100). Follow links.next URL for next page.

Base URLs

ModuleBase URLAPI VersionUsed By Integration
Peoplehttps://api.planningcenteronline.com/people/v2/2022-07-14Read/Write
Check-Inshttps://api.planningcenteronline.com/check-ins/v2/2019-07-17Read
Groupshttps://api.planningcenteronline.com/groups/v2/2018-08-01Read/Write
Calendarhttps://api.planningcenteronline.com/calendar/v2/2021-07-20Read
Serviceshttps://api.planningcenteronline.com/services/v2/Not Used
Givinghttps://api.planningcenteronline.com/giving/v2/Not Used

Authentication

The integration uses Personal Access Tokens (PAT) for server-to-server authentication via HTTP Basic Auth. Credentials are configured per-church in appsettings.json under the PlanningCenter section.

  • Auth method: HTTP Basic Auth with AppId:Secret
  • Token type: Personal Access Token (never expires until revoked)
  • Scope: Full read/write access to the organization's PCO data
  • Configuration: PlanningCenter:AppId and PlanningCenter:Secret in appsettings

OAuth 2.0 is also supported by PCO for multi-tenant SaaS deployments (access tokens expire after 2 hours with long-lived refresh tokens). The current single-church integration uses PAT for simplicity.

Write Capabilities Matrix

PCO's API is heavily read-biased. The People module is fully writable, Groups support membership writes only, and Check-Ins/Calendar are entirely read-only.

ResourceModuleCreateUpdateDeleteNotes
PersonPeople Yes Yes Yes remote_id field stores our people.id
EmailPeople Yes Yes Yes Scoped to person: /people/{id}/emails
Phone NumberPeople Yes Yes Yes PCO auto-normalizes to E.164
AddressPeople Yes Yes Yes On Person (not Household)
HouseholdPeople Yes Yes Yes Maps to our families table
Household MembershipPeople Yes Yes Yes No relationship role — just member
Group MembershipGroups Yes Yes No Role: "leader" or "member" only
GroupGroups Read-Only Read-Only No Groups created in PCO admin only
Check-In RecordCheck-Ins Read-Only Read-Only No Check-ins performed locally stay local
Calendar EventCalendar Read-Only Read-Only No Events managed in PCO Calendar admin

Read Capabilities Matrix

All PCO modules provide comprehensive read access. The integration uses read endpoints for inbound sync, data comparison, and admin-facing read-only views.

ResourceModuleListGetSideloadFilter
PeoplePeople Yes Yes emails, phone_numbers, addresses name, email, phone, updated_at
HouseholdsPeople Yes Yes people (members) name, updated_at
GroupsGroups Yes Yes memberships name, enrollment_status
Group TypesGroups Yes Yes
Group MembershipsGroups Yes Yes person role
Check-InsCheck-Ins Yes Yes event, person, locations date, event
Check-In LocationsCheck-Ins Yes Yes kind, age/grade range
Calendar EventsCalendar Yes Yes future, starts_at
Event InstancesCalendar Yes Yes future, starts_at, recurrence
← Back to Documentation Home

All Endpoints Used

Complete list of PCO API endpoints consumed by the Church Management Platform integration.

People Module (Read/Write)

MethodEndpointPurpose
GET/people/v2/peopleList all people (paginated, with sideloaded contacts)
GET/people/v2/people/{id}Get single person by PCO ID
POST/people/v2/peopleCreate person (outbound push)
PATCH/people/v2/people/{id}Update person demographics
GET/people/v2/people/{id}/emailsList person's emails
POST/people/v2/people/{id}/emailsAdd email to person
GET/people/v2/people/{id}/phone_numbersList person's phone numbers
POST/people/v2/people/{id}/phone_numbersAdd phone to person
GET/people/v2/people/{id}/addressesList person's addresses
GET/people/v2/householdsList all households (with sideloaded members)
POST/people/v2/householdsCreate household (outbound push)
POST/people/v2/households/{id}/household_membershipsAdd person to household

Groups Module (Read + Membership Write)

MethodEndpointPurpose
GET/groups/v2/groupsList all groups
GET/groups/v2/groups/{id}Get single group
GET/groups/v2/group_typesList group types
GET/groups/v2/groups/{id}/membershipsList group members
POST/groups/v2/groups/{id}/membershipsAdd member to group (outbound push)
PATCH/groups/v2/groups/{id}/memberships/{mid}Update membership role

Check-Ins Module (Read-Only)

MethodEndpointPurpose
GET/check-ins/v2/check_insList check-in records
GET/check-ins/v2/eventsList check-in events
GET/check-ins/v2/stationsList check-in stations
GET/check-ins/v2/labelsList label templates
GET/check-ins/v2/headcountsAggregate attendance counts

Calendar Module (Read-Only)

MethodEndpointPurpose
GET/calendar/v2/eventsList calendar events
GET/calendar/v2/event_instancesList event occurrences (supports future filter)

Inbound Sync (Pull from PCO)

Inbound sync pulls data from Planning Center into the local database. The sync service (PcoSyncService) supports four sync types that can be triggered individually or as a full sync.

Sync Types

Sync TypeWhat It Does
peopleStreams all PCO people (with emails + phones), matches by pco_id → email → name+dob, upserts demographics and contacts
familiesStreams PCO households (with members), creates/updates families and family_members, syncs addresses
groupsStreams PCO groups, creates under auto-created "PCO Groups" department in church_group hierarchy
fullRuns people → families → groups in sequence

Matching Logic

When pulling people from PCO, the sync service uses a three-tier matching strategy:

  1. pco_id match — if a local person already has a pco_id matching the PCO record, update in place.
  2. Email match — if no pco_id match, search local person_emails for a matching email address.
  3. Name + DOB match — if no email match, compare first_name + last_name + date of birth as a fallback.
  4. Create new — if no match found, create a new local person record with the PCO data.

Data Ownership

  • PCO authoritative for: demographics (first_name, last_name, gender, dob), contact info (emails, phones, addresses)
  • Local authoritative for: operational data (allergies, photo_url, is_verified, group memberships, check-in records)
Admin triggers sync
via PCO Sync page
PcoApiClient streams
PCO records (paginated)
PcoSyncService matches
pco_id → email → name
Upsert local DB
Track progress in pco_sync_log

Outbound Push (Local → PCO)

Outbound push sends locally-created or modified records to Planning Center. The push service supports four push types.

Push Types

Push TypeWhat It Does
peoplePushes local people (without pco_id) to PCO, creates Person + Email + Phone records, stores PCO ID back on local record
familiesPushes local families to PCO as Households, creates HouseholdMembership records for members
group-membershipsPushes local group memberships to PCO Groups (creates membership, maps leader status to PCO role)
fullRuns people → families → group-memberships in sequence
Admin triggers push
via PCO Sync page
Find local records
without pco_id
POST to PCO API
(rate-limited)
Store PCO ID
on local record

Real-Time Webhooks

PCO pushes real-time change notifications via webhooks, reducing the need for polling. Church Management Platform receives and processes these events at POST /api/pco/webhook.

Supported Webhook Events

EventAction
person.createdCreates a new local person record with PCO demographics and pco_id
person.updatedUpdates local person demographics from PCO data
person.destroyedMarks local person as inactive (is_active=false)

Security

  • Webhook payloads are verified via X-PCO-Webhooks-Authenticity header using HMAC-SHA256
  • Webhook secret is configured in PlanningCenter:WebhookSecret
  • PCO retries up to 16 times with exponential backoff over 5+ days on delivery failure
← Back to Documentation Home

Read-Only Data Endpoints

The admin UI exposes several read-only views of PCO data for comparison and verification purposes.

EndpointReturns
GET /api/pco/checkinsRecent PCO check-in records (name, security code, kind, timestamps)
GET /api/pco/calendar-eventsPCO calendar event instances (name, description, dates, recurrence, location)
GET /api/pco/group-typesPCO group types (name, description, church center visibility)
GET /api/pco/checkin-locationsPCO check-in locations (name, kind, age/grade range, capacity)

Entity Mapping

How Church Management Platform entities map to Planning Center equivalents. The pco_id column on local tables stores the corresponding PCO record ID for bidirectional lookup.

Church Management PlatformPCO EquivalentSync DirectionMapping Key
peoplePerson (People API)Push & Pullpeople.pco_id + PCO remote_id
person_emailsEmail (People API)Push & PullMatched by email address
person_phonesPhoneNumber (People API)Push & PullBoth E.164 normalized
familiesHousehold (People API)Push & Pullfamilies.pco_id
family_membersHouseholdMembershipPush & PullVia person + household pco_ids
church_groupGroup (Groups API)Pull Onlychurch_group.pco_id
group_membershipMembership (Groups API)Push & PullVia person + group pco_ids
eventsEventInstance (Calendar)Pull Onlyevents.pco_id
locationsLocation (Check-Ins)Pull Onlylocations.pco_id
checkinsCheckIn (Check-Ins)Read OnlyCheck-ins stay local

Model Differences

Key structural differences between Church Management Platform and Planning Center data models.

Families / Households

  • PCO HouseholdMembership has no relationship role (no Parent/Child/Spouse). Child status comes from Person's child boolean.
  • PCO addresses are on Person (not Household). Our system stores addresses on families.
  • Our authorized_pickup_ids and relationships table have no PCO equivalent.

Groups

  • Our 3-level hierarchy (Department → Area → Group) is richer than PCO's flat GroupType → Group structure.
  • PCO membership role is only "leader" or "member" — no Coach/Other from our small_group_leader_type.
  • Our small group metadata (meeting day, frequency, area, childcare) has no PCO equivalent. PCO stores schedule as freetext.

Check-Ins

  • PCO uses a Station model (physical iPads) vs. our software-based kiosk.
  • PCO resolves children to rooms via Location age/grade filters. Our system uses hierarchical group-based event resolution.
  • Check-ins performed in Church Management Platform cannot be pushed to PCO (API limitation).

Rate Limits & Performance

PCO enforces 100 requests per minute per organization. The integration uses several strategies to work within this constraint.

Rate Limit Mitigation

  • SemaphoreSlim rate limiter in PcoApiClient — throttles at 90 req/min to stay safely under the 100/min limit
  • Sideloading?include=emails,phone_numbers fetches contacts in one request instead of per-person calls
  • IAsyncEnumerable pagination — streams results page-by-page without loading all data into memory
  • Incremental sync?where[updated_at][gte]=... pulls only records changed since last sync
  • Webhooks — real-time person change notifications eliminate polling for People module

Bulk Operation Timing

OperationAPI CallsEstimated Time
List 5,000 people (with contacts)~50 GET requests~30 seconds
Push 5,000 people + contacts~15,000 requests~2.5 hours
Full initial sync~25,000+ requests~4+ hours
← Back to Documentation Home

Admin UI

The integration is managed through the PCO Sync page at /admin/pco-sync, accessible to ADMIN users via the sidebar and dashboard.

Features

  • Connection status — shows whether PCO credentials are configured, with "Test Connection" button
  • Sync actions — buttons for People, Families, Groups, and Full Sync (inbound pull)
  • Push actions — buttons for People, Families, Group Memberships, and Full Push (outbound)
  • Live progress — running sync/push shows real-time created/updated/skipped counters (polled every 3 seconds)
  • Sync history — table of last 20 runs with type, status badge, timing, and record counts
  • Webhook config — shows webhook URL, secret status, and subscription count

Configuration

All PCO integration settings are in appsettings.json under the PlanningCenter section. Each church deployment configures its own PCO credentials — no code changes required.

// appsettings.json
{
  "PlanningCenter": {
    "AppId": "",          // PCO Personal Access Token App ID
    "Secret": "",         // PCO Personal Access Token Secret
    "WebhookSecret": ""  // HMAC-SHA256 secret for webhook verification
  }
}

Database Schema Support

  • pco_id TEXT column on people, families, locations, events, church_group (with partial unique indexes)
  • pco_sync_log table tracks all sync/push runs (type, status, timing, record counts, error messages)
  • PCO webhook controller at POST /api/pco/webhook (HMAC-SHA256 verified, no authentication required)

Backend Components

ComponentLocationPurpose
IPcoApiClientAPI/Services/HTTP client with rate limiting, pagination, JSON:API parsing
IPcoSyncServiceAPI/Services/Sync orchestrator (people, families, groups, push)
PcoControllerAPI/Controllers/Admin endpoints for config, sync, push, status, history
PcoWebhookControllerAPI/Controllers/Webhook receiver with HMAC verification
PcoSyncLogCore/Entities/Entity for sync run tracking
PcoModels/Shared/JSON:API response models for PCO data
← Back to Documentation Home