Authentication
Every request to the Planning Center API is made on behalf of a user. Permissions are dependent on the access of this user. This also means that when the access a user is granted has changed, their permission in the API will change as well.
There are two ways to authenticate with the API: Personal Access Token and OAuth.
Personal Access Token and OAuth secrets should never be posted publicly. If you need to revoke your tokens, visit your developer account and delete the impacted tokens. If at any time they are found to be publicly available they will be disabled automatically.
Personal Access Token
A Personal Access Token (PAT) allows you to use the API from your own account. This is useful if you are writing a script that runs on your own computer or a server you control. These tokens cannot be used in client-side requests from a web page.
You may not use a Personal Access Token if you are integrating with multiple churches—instead use OAuth (see below).
Visit your developer account.
Create a new "Personal Access Token"
Pass your token and secret in every request using HTTP Basic Auth.
You can pass your personal access token with curl like this:
curl -u app_id:secret https://api.planningcenteronline.com/people/v2/people
OAuth 2.0
If you are distributing your app to multiple churches, you should use OAuth version 2.0.
First, your company needs to have a Planning Center account, which represents your organization. You can create one here. This feels a little funny at first, because it is like you are signing up as a church for Planning Center. But having a Planning Center account with a login gives you a place to manage your OAuth application. The name you give your Planning Center account (the "church" name) can just be your company name.
Once you are logged into your Planning Center account, visit api.planningcenteronline.com to create an OAuth application. This client ID and secret will only be created once, and will be reused for every church that signs up for your integration.
Make sure your app conforms to the OAuth 2.0 specification. Generally, to authenticate a user, follow these steps:
-
Redirect the user's browser to
https://api.planningcenteronline.com/oauth/authorize?client_id=CLIENT_ID&redirect_uri=https://example.com/auth/complete&response_type=code&scope=people(replaceCLIENT_IDandhttps://example.com/auth/completewith your actual redirect URI).If you need different scopes, replace
scope=peopleappropriately (see "Application Scopes" section below). Planning Center will redirect the user's browser back to the given redirect URI with a code param.
-
Send a POST request in the background to
https://api.planningcenteronline.com/oauth/tokenwith the following params:{"grant_type": "authorization_code", "code": "CODE_FROM_STEP_2", "client_id": "CLIENT_ID", "client_secret": "CLIENT_SECRET", "redirect_uri": "https://example.com/auth/complete"}(replace
CLIENT_ID,CLIENT_SECRET,CODE_FROM_STEP_2, and the redirect URI appropriately).curl -X POST https://api.planningcenteronline.com/oauth/token \ -F grant_type=authorization_code \ -F code=1234567890 \ -F client_id=2345678901 \ -F client_secret=3456789012 \ -F redirect_uri=https://example.com/auth/complete -
The response you get back will contain the access token and other information.
{ "access_token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", "token_type": "bearer", "expires_in": 7200, "refresh_token": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", "scope": "people", "created_at": 1469553476 } -
Use the access token for all API requests by passing it in the
Authorizationheader, using theBearerauthentication scheme.curl -H 'Authorization: Bearer 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' https://api.planningcenteronline.com/people/v2/people
OAuth access tokens expire after 2 hours from the time they are issued, but we also provide a refresh token you can use to get a new access token at any time, even after the access token expires, without forcing the user to re-authorize.
We will honor refresh tokens for up to 90 days after the date its associated access token was issued. This means that, if your app does not issue a refresh for 90 days, then your user will need to re-authorize.
Application Scopes
Each Planning Center product is a distinct OAuth scope.
| Product | Scope |
|---|---|
| API | api |
| Calendar | calendar |
| Check-Ins | check_ins |
| Giving | giving |
| Groups | groups |
| People | people |
| Publishing | publishing |
| Registrations | registrations |
| Services | services |
Note that accessing Webhooks endpoints do not require an OAuth scope.
Authorization URL is https://api.planningcenteronline.com/oauth/authorize
Token URL is https://api.planningcenteronline.com/oauth/token
When authorizing, you can request scopes using the scope parameter. The value should be a space-separated list of scopes. The value for response_type should be code.
Refreshing a token
You can refresh an expired Oauth token by using the refresh_token returned when you generated the token.
curl -X "POST" "https://api.planningcenteronline.com/oauth/token" \
-H 'Content-Type: application/json' \
-d {
"client_id": "<your application client id>",
"client_secret": "<your application secret>",
"refresh_token": "<your access token refresh token>",
"grant_type": "refresh_token"
}'
The response body will look like this:
{
"access_token": "<new access token>",
"token_type": "bearer",
"expires_in": 7200,
"refresh_token": "<new refresh token>",
"created_at": 1540325919
}
Revoking a token
You can revoke an access token or refresh token by sending a POST request to the revocation endpoint. This is useful when a user disconnects your integration or you want to clean up tokens that are no longer needed.
curl -X "POST" "https://api.planningcenteronline.com/oauth/revoke" \
-F token=<your access token> \
-F token_type_hint=access_token \
-F client_id=<your application client id> \
-F client_secret=<your application secret>
A successful revocation returns an HTTP 200 response with an empty JSON body. The endpoint will return 200 even if the token has already been revoked or is otherwise invalid.
You can also revoke a refresh token by passing token_type_hint=refresh_token and providing the refresh token as the token value. Revoking a refresh token will also invalidate its associated access token.
Token introspection
You can check whether a token is still active and retrieve its metadata by sending a POST request to the introspection endpoint.
curl -X "POST" "https://api.planningcenteronline.com/oauth/introspect" \
-F token=<your access token> \
-F client_id=<your application client id> \
-F client_secret=<your application secret>
For an active token, the response will look like this:
{
"active": true,
"scope": "people",
"client_id": "<your application client id>",
"token_type": "Bearer",
"exp": 1469560676,
"iat": 1469553476
}
If the token is inactive, expired, or has been revoked, the response will be:
{
"active": false
}
Current User
To identify the current user, you can use the /me endpoint in any application API or the /current/v2/me endpoint from the Current API. For example:
curl https://api.planningcenteronline.com/people/v2/me -H 'Authorization: Bearer ...'
curl https://api.planningcenteronline.com/current/v2/me -H 'Authorization: Bearer ...'
When using an application API, the /me endpoint requires the application's OAuth scope and enforces the current user's access and permissions within that application. The /current/v2/me endpoint, however, is available to all OAuth applications without requiring any scopes and without imposing any access or permission rules to the user account.
Proof Key for Code Exchange (PKCE)
Planning Center supports the OAuth 2.0 PKCE extension for both confidential and public OAuth applications. PKCE adds parameters to the OAuth flow that allows the OAuth server (Planning Center in this case) to ensure the OAuth application that starts the flow is the same one that finishes it.
It's recommended for all applications and is required by OAuth 2.1. Currently, we recommend PKCE for confidential apps and require it for public apps.
OAuth Application Types
OAuth defines two types of applications: confidential and public.
Confidential applications are able to keep their registered client_secret safe and use it to authenticate with the authorization server (Planning Center). Generally, that requires requests for access tokens to originate from a web server you own.
Public applications are unable to use a registered client_secret, usually because they're running in the browser or on a mobile device.
PKCE Workflow
-
Generate a
code_verifierand derive acode_challengeusing SHA-256. Per RFC 7636, thecode_verifieris a high-entropy random string using unreserved URL characters, 43-128 characters long. -
Redirect the user to the authorization endpoint with the normal parameters plus
code_challengeandcode_challenge_method=S256https://api.planningcenteronline.com/oauth/authorize?client_id=CLIENT_ID \ &code_challenge=CODE_CHALLENGE \ &code_challenge_method=S256 &redirect_uri=https://example.com/auth/complete \ &response_type=code \ &scope=people -
Planning Center will redirect the user's browser back to the given redirect URI with a
codeparam. -
Send a POST request in the background to
https://api.planningcenteronline.com/oauth/tokenwith the normal params as well as the originalcode_verifierfrom step 1:curl -X POST https://api.planningcenteronline.com/oauth/token \ -F grant_type=authorization_code \ -F code=1234567890 \ -F code_verifier=CODE_VERIFIER_FROM_STEP_1 \ -F client_id=2345678901 \ -F client_secret=3456789012 \ -F redirect_uri=https://example.com/auth/complete
OpenID Connect (OIDC)
OpenID Connect is an authentication layer on top of OAuth 2.0 that allows users of your applications to authenticate using their Planning Center account.
The OIDC flow is very similar to the typical OAuth 2.0 flow, but requires requesting an additional openid scope. In fact, the openid scope can be requested alongside other application scopes (see the previous "Application Scopes" section).
When requesting the openid scope, you'll receive an id_token (a JWT) in addition to the standard OAuth 2.0 access_token. ID Tokens contain identity claim assertions for the currently logged in user.
ID tokens will expire after 1 hour from the time they are issued.
OIDC Discovery
Planning Center supports OIDC discovery through the standard OpenID configuration endpoint:
https://api.planningcenteronline.com/.well-known/openid-configuration
This endpoint provides all the necessary configuration information (including supported scopes, token endpoints, and token signing information) and simplifies the configuration process for OIDC clients that support server discovery.
Additional OIDC Request Parameters
When initiating the OIDC authorization flow, the following request parameters are optional but strongly recommended, and should be used in addition to the standard OAuth flow request parameters:
state- A unique, unguessable string used to prevent CSRF attacks. Your application should verify this value matches the originally sent value when the user is redirected back to your application.prompt- Defines what the login process will look like for the user.select_accountis recommended to allow users to verify which account they will be signing in as and allow them to switch accounts. Alternativelyloginwill log users out of their current Planning Center session and force them to login again.nonce- A unique string that will be included in the ID token to prevent replay attacks. If provided, your application should verify this value matches what was originally sent.
OIDC Workflow:
-
Follow steps 1-3 from the "OAuth 2.0" section above to initiate the authorization flow, but include the
openidscope and the additional recommended OIDC parameters.Redirect the user's browser to
https://api.planningcenteronline.com/oauth/authorize?client_id=CLIENT_ID&redirect_uri=https://example.com/auth/complete&response_type=code&scope=openid&state=RANDOM_STATE_VALUE&nonce=RANDOM_NONCE_VALUE&prompt=select_account(replaceCLIENT_ID,RANDOM_NONCE_VALUE,RANDOM_STATE_VALUEandhttps://example.com/auth/completewith your actual application's values).If you need additional scopes, add them to
scope=openidappropriately (see the "Application Scopes" section above). -
After exchanging the authorization code for tokens, you'll receive an
access_token,refresh_token, andid_token. Theid_tokenis a JWT that contains basic user and organization information for the currently logged in user:{ "iss": "https://api.planningcenteronline.com", "sub": "1234567890", "aud": "<your client id>", "name": "John Doe", "email": "john.doe@planningcenter.com", "organization_id": 123456, "organization_name": "Test Church", "nonce": "<your originally passed nonce value>", "exp": 1755801744, "iat": 1755798144 } -
Refetch user data: To get the most up-to-date current user information, make a request to the
/oauth/userinfoendpoint:curl -H 'Authorization: Bearer ACCESS_TOKEN' https://api.planningcenteronline.com/oauth/userinfoThis will return the same users identity claims as the
id_token:{ "sub": "1234567890", "name": "John Doe", "email": "john.doe@planningcenter.com", "organization_id": 123456, "organization_name": "Test Church" } -
An expired
id_tokencan be refreshed to extend a user's session (see Refresh Tokens).
Sample OAuth and OIDC Applications
Below are example applications that demonstrate how to obtain and use access tokens and refresh tokens with OAuth's Authorization Code Flow and the PKCE extension. They also show how to use OpenID Connect (OIDC) to authenticate users and retrieve their profile information.
- Flask + Python
-
Sinatra + Ruby
- Also includes a fully client-side OAuth + PKCE demo implemented directly in a script tag on this page.
- Slim + PHP
Specifying a User-Agent header
All API requests must include a User-Agent header. We recommend using a value that uniquely identifies your application—typically your application's name plus a link to your application or your email address. For example:
My Planning Center App (https://pcapp.example.com/contact)PCO Demo (me@pcodemo.example.com)
Note: If you don't supply a User-Agent header that meets these requirements, your requests may result in a 403 Forbidden response.