Planning Center Calendar API
Manage church calendaring and facility scheduling - events and their event instances, room and equipment resources, resource requests, conflicts, and tags. Read the public event feed and manage room bookings.
Manage church calendaring and facility scheduling - events and their event instances, room and equipment resources, resource requests, conflicts, and tags. Read the public event feed and manage room bookings.
openapi: 3.0.3
info:
title: Planning Center API
description: >-
A representative OpenAPI description of the Planning Center suite of church
management APIs. Planning Center exposes a documented public REST API for each
of its products - People, Services, Giving, Groups, Check-Ins, Calendar,
Registrations, Publishing - plus a cross-product Webhooks API, all under the
shared base host https://api.planningcenteronline.com. Every product is
versioned under its own path prefix (for example /people/v2, /services/v2,
/giving/v2). All responses conform to the JSON:API 1.0 specification: resource
objects are wrapped in a top-level `data` member (an object or an array), each
with `id`, `type`, `attributes`, and `relationships`, and collections support
`include`, `where[]` filtering, `order`, and offset-based pagination via
`per_page` and `offset`. Authenticate with HTTP Basic using a Personal Access
Token (application id / secret) or with an OAuth 2.0 bearer token. A
`User-Agent` header is required on every request.
Endpoint coverage: the resource collections and base paths modeled here are
grounded in Planning Center's published documentation. Individual method/path
combinations are a representative CRUD-shaped subset; consult the live API
reference at developer.planning.center for the authoritative, exhaustive list
and per-resource attributes.
version: '2.0'
contact:
name: Planning Center Developers
url: https://developer.planning.center/docs/
license:
name: Proprietary
url: https://www.planningcenter.com/terms
servers:
- url: https://api.planningcenteronline.com
description: Planning Center API (all products)
security:
- basicAuth: []
- oauth2:
- people
- services
- giving
- groups
- check_ins
- calendar
- registrations
- publishing
tags:
- name: People
description: People, households, contact info, lists, forms, and workflows.
- name: Services
description: Service planning - service types, plans, songs, teams.
- name: Giving
description: Donations, funds, batches, payment sources, and pledges.
- name: Groups
description: Small groups, memberships, and group events.
- name: Check-Ins
description: Attendance, events, locations, and stations.
- name: Calendar
description: Church calendaring, events, and facility resources.
- name: Registrations
description: Event signups, attendees, categories, and campuses.
- name: Publishing
description: Sermon channels, series, episodes, and speakers (read-only).
- name: Webhooks
description: Cross-product event subscriptions and deliveries.
paths:
# ---------------- People ----------------
/people/v2/people:
get:
operationId: listPeople
tags: [People]
summary: List people
description: Lists people in the account. Supports include, where[] filters, order, and offset pagination.
parameters:
- $ref: '#/components/parameters/PerPage'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Include'
responses:
'200':
$ref: '#/components/responses/Collection'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimited'
post:
operationId: createPerson
tags: [People]
summary: Create a person
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'201':
$ref: '#/components/responses/Resource'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/UnprocessableEntity'
/people/v2/people/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getPerson
tags: [People]
summary: Get a person
responses:
'200':
$ref: '#/components/responses/Resource'
'404':
$ref: '#/components/responses/NotFound'
patch:
operationId: updatePerson
tags: [People]
summary: Update a person
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'200':
$ref: '#/components/responses/Resource'
'422':
$ref: '#/components/responses/UnprocessableEntity'
delete:
operationId: deletePerson
tags: [People]
summary: Delete a person
responses:
'204':
description: Deleted.
/people/v2/people/{id}/emails:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: listPersonEmails
tags: [People]
summary: List a person's emails
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/emails:
get:
operationId: listEmails
tags: [People]
summary: List email addresses
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/addresses:
get:
operationId: listAddresses
tags: [People]
summary: List addresses
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/phone_numbers:
get:
operationId: listPhoneNumbers
tags: [People]
summary: List phone numbers
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/households:
get:
operationId: listHouseholds
tags: [People]
summary: List households
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/lists:
get:
operationId: listLists
tags: [People]
summary: List people lists
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/field_definitions:
get:
operationId: listFieldDefinitions
tags: [People]
summary: List custom field definitions
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/forms:
get:
operationId: listForms
tags: [People]
summary: List forms
responses:
'200':
$ref: '#/components/responses/Collection'
/people/v2/workflows:
get:
operationId: listWorkflows
tags: [People]
summary: List workflows
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Services ----------------
/services/v2/service_types:
get:
operationId: listServiceTypes
tags: [Services]
summary: List service types
responses:
'200':
$ref: '#/components/responses/Collection'
/services/v2/service_types/{service_type_id}/plans:
parameters:
- name: service_type_id
in: path
required: true
schema: { type: string }
get:
operationId: listPlans
tags: [Services]
summary: List plans for a service type
responses:
'200':
$ref: '#/components/responses/Collection'
/services/v2/service_types/{service_type_id}/plans/{plan_id}:
parameters:
- name: service_type_id
in: path
required: true
schema: { type: string }
- name: plan_id
in: path
required: true
schema: { type: string }
get:
operationId: getPlan
tags: [Services]
summary: Get a plan
responses:
'200':
$ref: '#/components/responses/Resource'
/services/v2/songs:
get:
operationId: listSongs
tags: [Services]
summary: List songs
responses:
'200':
$ref: '#/components/responses/Collection'
post:
operationId: createSong
tags: [Services]
summary: Create a song
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'201':
$ref: '#/components/responses/Resource'
/services/v2/teams:
get:
operationId: listTeams
tags: [Services]
summary: List teams
responses:
'200':
$ref: '#/components/responses/Collection'
/services/v2/people:
get:
operationId: listServicesPeople
tags: [Services]
summary: List people in Services
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Giving ----------------
/giving/v2/donations:
get:
operationId: listDonations
tags: [Giving]
summary: List donations
responses:
'200':
$ref: '#/components/responses/Collection'
post:
operationId: createDonation
tags: [Giving]
summary: Create a donation
description: Create a donation, including its designations to one or more funds and a payment source.
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'201':
$ref: '#/components/responses/Resource'
'422':
$ref: '#/components/responses/UnprocessableEntity'
/giving/v2/donations/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getDonation
tags: [Giving]
summary: Get a donation
responses:
'200':
$ref: '#/components/responses/Resource'
/giving/v2/donations/{id}/issue_refund:
parameters:
- $ref: '#/components/parameters/Id'
post:
operationId: issueRefund
tags: [Giving]
summary: Issue a refund for a donation
responses:
'200':
$ref: '#/components/responses/Resource'
/giving/v2/funds:
get:
operationId: listFunds
tags: [Giving]
summary: List funds
responses:
'200':
$ref: '#/components/responses/Collection'
/giving/v2/batches:
get:
operationId: listBatches
tags: [Giving]
summary: List batches
responses:
'200':
$ref: '#/components/responses/Collection'
post:
operationId: createBatch
tags: [Giving]
summary: Create a batch
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'201':
$ref: '#/components/responses/Resource'
/giving/v2/payment_sources:
get:
operationId: listPaymentSources
tags: [Giving]
summary: List payment sources
responses:
'200':
$ref: '#/components/responses/Collection'
/giving/v2/recurring_donations:
get:
operationId: listRecurringDonations
tags: [Giving]
summary: List recurring donations
responses:
'200':
$ref: '#/components/responses/Collection'
/giving/v2/pledges:
get:
operationId: listPledges
tags: [Giving]
summary: List pledges
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Groups ----------------
/groups/v2/groups:
get:
operationId: listGroups
tags: [Groups]
summary: List groups
responses:
'200':
$ref: '#/components/responses/Collection'
/groups/v2/groups/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getGroup
tags: [Groups]
summary: Get a group
responses:
'200':
$ref: '#/components/responses/Resource'
/groups/v2/group_types:
get:
operationId: listGroupTypes
tags: [Groups]
summary: List group types
responses:
'200':
$ref: '#/components/responses/Collection'
/groups/v2/groups/{group_id}/memberships:
parameters:
- name: group_id
in: path
required: true
schema: { type: string }
get:
operationId: listGroupMemberships
tags: [Groups]
summary: List memberships for a group
responses:
'200':
$ref: '#/components/responses/Collection'
post:
operationId: createGroupMembership
tags: [Groups]
summary: Add a member to a group
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'201':
$ref: '#/components/responses/Resource'
/groups/v2/events:
get:
operationId: listGroupEvents
tags: [Groups]
summary: List group events
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Check-Ins ----------------
/check-ins/v2/check_ins:
get:
operationId: listCheckIns
tags: [Check-Ins]
summary: List check-ins
responses:
'200':
$ref: '#/components/responses/Collection'
/check-ins/v2/events:
get:
operationId: listCheckInEvents
tags: [Check-Ins]
summary: List check-in events
responses:
'200':
$ref: '#/components/responses/Collection'
/check-ins/v2/events/{event_id}/event_times:
parameters:
- name: event_id
in: path
required: true
schema: { type: string }
get:
operationId: listEventTimes
tags: [Check-Ins]
summary: List event times for an event
responses:
'200':
$ref: '#/components/responses/Collection'
/check-ins/v2/locations:
get:
operationId: listCheckInLocations
tags: [Check-Ins]
summary: List check-in locations
responses:
'200':
$ref: '#/components/responses/Collection'
/check-ins/v2/stations:
get:
operationId: listStations
tags: [Check-Ins]
summary: List stations
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Calendar ----------------
/calendar/v2/events:
get:
operationId: listCalendarEvents
tags: [Calendar]
summary: List calendar events
responses:
'200':
$ref: '#/components/responses/Collection'
/calendar/v2/event_instances:
get:
operationId: listEventInstances
tags: [Calendar]
summary: List event instances
responses:
'200':
$ref: '#/components/responses/Collection'
/calendar/v2/resources:
get:
operationId: listResources
tags: [Calendar]
summary: List resources (rooms and equipment)
responses:
'200':
$ref: '#/components/responses/Collection'
/calendar/v2/resource_bookings:
get:
operationId: listResourceBookings
tags: [Calendar]
summary: List resource bookings
responses:
'200':
$ref: '#/components/responses/Collection'
/calendar/v2/conflicts:
get:
operationId: listConflicts
tags: [Calendar]
summary: List scheduling conflicts
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Registrations ----------------
/registrations/v2/signups:
get:
operationId: listSignups
tags: [Registrations]
summary: List signups
responses:
'200':
$ref: '#/components/responses/Collection'
/registrations/v2/signups/{signup_id}/attendees:
parameters:
- name: signup_id
in: path
required: true
schema: { type: string }
get:
operationId: listAttendees
tags: [Registrations]
summary: List attendees for a signup
responses:
'200':
$ref: '#/components/responses/Collection'
/registrations/v2/categories:
get:
operationId: listCategories
tags: [Registrations]
summary: List categories
responses:
'200':
$ref: '#/components/responses/Collection'
/registrations/v2/campuses:
get:
operationId: listCampuses
tags: [Registrations]
summary: List campuses
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Publishing ----------------
/publishing/v2/channels:
get:
operationId: listChannels
tags: [Publishing]
summary: List channels
responses:
'200':
$ref: '#/components/responses/Collection'
/publishing/v2/channels/{channel_id}/episodes:
parameters:
- name: channel_id
in: path
required: true
schema: { type: string }
get:
operationId: listEpisodes
tags: [Publishing]
summary: List episodes for a channel
responses:
'200':
$ref: '#/components/responses/Collection'
/publishing/v2/series:
get:
operationId: listSeries
tags: [Publishing]
summary: List series
responses:
'200':
$ref: '#/components/responses/Collection'
/publishing/v2/speakers:
get:
operationId: listSpeakers
tags: [Publishing]
summary: List speakers
responses:
'200':
$ref: '#/components/responses/Collection'
# ---------------- Webhooks ----------------
/webhooks/v2/subscriptions:
get:
operationId: listWebhookSubscriptions
tags: [Webhooks]
summary: List webhook subscriptions
responses:
'200':
$ref: '#/components/responses/Collection'
post:
operationId: createWebhookSubscription
tags: [Webhooks]
summary: Create a webhook subscription
description: Subscribe to an available event. Deliveries are outbound HTTPS POST to the subscription URL.
requestBody:
$ref: '#/components/requestBodies/JsonApiBody'
responses:
'201':
$ref: '#/components/responses/Resource'
/webhooks/v2/subscriptions/{id}:
parameters:
- $ref: '#/components/parameters/Id'
get:
operationId: getWebhookSubscription
tags: [Webhooks]
summary: Get a webhook subscription
responses:
'200':
$ref: '#/components/responses/Resource'
delete:
operationId: deleteWebhookSubscription
tags: [Webhooks]
summary: Delete a webhook subscription
responses:
'204':
description: Deleted.
/webhooks/v2/available_events:
get:
operationId: listAvailableEvents
tags: [Webhooks]
summary: List available webhook events
responses:
'200':
$ref: '#/components/responses/Collection'
/webhooks/v2/subscriptions/{subscription_id}/events:
parameters:
- name: subscription_id
in: path
required: true
schema: { type: string }
get:
operationId: listWebhookDeliveries
tags: [Webhooks]
summary: List delivered events for a subscription
responses:
'200':
$ref: '#/components/responses/Collection'
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
description: HTTP Basic auth using a Personal Access Token - application id as the username and secret as the password.
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://api.planningcenteronline.com/oauth/authorize
tokenUrl: https://api.planningcenteronline.com/oauth/token
scopes:
people: Access the People product
services: Access the Services product
giving: Access the Giving product
groups: Access the Groups product
check_ins: Access the Check-Ins product
calendar: Access the Calendar product
registrations: Access the Registrations product
publishing: Access the Publishing product
parameters:
Id:
name: id
in: path
required: true
schema: { type: string }
description: The resource ID.
PerPage:
name: per_page
in: query
required: false
schema: { type: integer, default: 25, maximum: 100 }
description: Number of records per page (JSON:API pagination).
Offset:
name: offset
in: query
required: false
schema: { type: integer, default: 0 }
description: Zero-based offset for pagination. Offsets above 30,000 are subject to a stricter rate limit.
Include:
name: include
in: query
required: false
schema: { type: string }
description: Comma-separated list of related resources to sideload (JSON:API include).
requestBodies:
JsonApiBody:
required: true
description: A JSON:API single-resource document.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiResourceDocument'
responses:
Resource:
description: A single JSON:API resource.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiResourceDocument'
Collection:
description: A JSON:API collection of resources.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiCollectionDocument'
Unauthorized:
description: Missing or invalid credentials.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiErrorDocument'
NotFound:
description: Resource not found.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiErrorDocument'
UnprocessableEntity:
description: Validation failed.
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiErrorDocument'
RateLimited:
description: Rate limit exceeded (100 requests per 20 seconds per user).
headers:
Retry-After:
schema: { type: integer }
description: Seconds to wait before retrying.
X-PCO-API-Request-Rate-Limit:
schema: { type: integer }
X-PCO-API-Request-Rate-Period:
schema: { type: integer }
X-PCO-API-Request-Rate-Count:
schema: { type: integer }
content:
application/json:
schema:
$ref: '#/components/schemas/JsonApiErrorDocument'
schemas:
JsonApiResource:
type: object
description: A JSON:API resource object.
properties:
id:
type: string
type:
type: string
attributes:
type: object
additionalProperties: true
relationships:
type: object
additionalProperties: true
links:
type: object
additionalProperties: true
JsonApiResourceDocument:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/JsonApiResource'
included:
type: array
items:
$ref: '#/components/schemas/JsonApiResource'
JsonApiCollectionDocument:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/JsonApiResource'
included:
type: array
items:
$ref: '#/components/schemas/JsonApiResource'
meta:
type: object
properties:
total_count:
type: integer
count:
type: integer
links:
type: object
properties:
self:
type: string
next:
type: string
JsonApiErrorDocument:
type: object
properties:
errors:
type: array
items:
type: object
properties:
status:
type: string
title:
type: string
detail:
type: string