Planning Center People API

The system of record for people in a Planning Center account. Read and write people, their emails, addresses, phone numbers, households, field data, lists, forms, and workflows. This is the shared people directory that the other products reference.

OpenAPI Specification

planning-center-openapi.yml Raw ↑
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