•  Playbook Open API  ·  v10.02

Build on the Playbook Platform

The Playbook Open API gives developers programmatic access to registrations, scheduling, payments, user profiles, and more. Integrate sports and recreation management data directly into your own applications and workflows.

Bearer token auth
OpenAPI 3.0.3
QA environment available
REST / JSON
48
Endpoints
9
Tag groups
111
Schemas
2
Token scopes

How it works

Authentication

All endpoints require a Bearer token. Admin tokens are provisioned by your Playbook Success Coach. User-scoped tokens can be minted per session via the auth endpoint.

Two token scopes

Admin tokens have full read access across all data. User-scoped tokens are short-lived and automatically filter responses to a single end-user's records — ideal for member-facing integrations.

Async operations

Write operations (registrations, bookings) return a task ID immediately. Poll GET /open-api/tasks/{id}/ to track completion — no long-running HTTP connections needed.

Sandbox mode

Set is_test: true when minting a token, or pass X-Open-API-Dry-Run: true on any write request. Full validation runs but no data is written, charged, or notified.

Ready to get started?

Contact your Playbook Success Coach to schedule a setup call with our Technical Implementation team.

Contact your Success Coach

API Reference

All endpoints require a valid Bearer token and are scoped to your organization's tenant.
Base URL: https://callplaybook.com/open-api

Health
GET /open-api/health/ API health check
Bearer token required (admin or user-scoped)

Returns the current health status of the API and the league ID for the authenticated tenant. Callable with either an admin or user-scoped Bearer token.

No parameters

200Successful response
{
  "status": "string",
  "league_id": 1
}
Authentication

Inspect the calling identity, mint short-lived user-scoped tokens (admin only), and revoke them. Admin tokens are provisioned out-of-band via shell.

POST /open-api/auth/user-tokens/ Issue a user-scoped token
Admin token required

Mints a short-lived Bearer token that authenticates subsequent requests as the specified end-user (rather than as the tenant admin). Identify the target user by email or user_id — the user must exist in the authenticated league. The default token lifetime is 1 hour; clients should mint a fresh token per session. The raw token value is returned once — only its hash is persisted, so it cannot be retrieved later.

FieldTypeDescription
emailstring(email)Target user email
user_idintegerTarget user ID (alternative to email)
client_labelstringOptional label to identify the issuing client
ttl_secondsintegerToken lifetime in seconds. Defaults to 3600, capped at 28800
is_testbooleanIf true, issues a sandbox token. Write requests are validated but produce no DB writes, payments, or notifications. Read endpoints behave normally
201Token issued
{
  "token": "string",
  "expires_at": "2026-01-01T00:00:00Z",
  "user_id": 1,
  "user_email": "user@example.com",
  "is_test": true
}
POST /open-api/auth/user-tokens/revoke/ Revoke a user-scoped token
Admin token required

Revokes a user-scoped token previously issued via POST /open-api/auth/user-tokens/. The raw token is sent in the request body so it does not appear in webserver access logs. Returns 204 on success or 404 if the token does not belong to the authenticated league.

FieldTypeDescription
tokenrequiredstringThe user-scoped token to revoke
204Token revoked — no body
GET /open-api/auth/whoami/ Identify the caller
Bearer token required (admin or user-scoped)

Returns the identity behind the supplied Bearer token. Useful for clients to verify that a freshly minted user-scoped token is valid before issuing dependent API calls.

No parameters

200Caller identity
{
  "user_id": 1,
  "user_email": "user@example.com",
  "league_id": 1,
  "expires_at": "2026-01-01T00:00:00Z",
  "is_test": true
}
Catalog

Reference data describing what a league offers: programs available for registration, subscription plans, pass types, coupons, waiver definitions, seasons, divisions, teams, and locations.

GET/open-api/programs/List available programs
Bearer token required

Returns all programs currently available for registration, grouped by type. Includes pricing, restrictions (age, grade, gender, membership), capacity, and dates.

ParameterTypeDescription
typestringFilter by program type: class_package, season, club, membership, pass_package
category_idintegerFilter by category ID
200Programs grouped by type
{ "count": 1, "next": null, "previous": null, "results": [] }
GET/open-api/seasons/List seasons
Bearer token required

Returns a paginated list of seasons for the authenticated league. Catalog data: identical results for admin and user tokens.

ParameterTypeDescription
is_activebooleanFilter by active status
sportstringFilter by sport code
start_date_afterstringYYYY-MM-DD
start_date_beforestringYYYY-MM-DD
registration_availablebooleanFilter by registration_available
category_idintegerFilter by category ID
limitintegerPage size
offsetintegerPagination offset
200Paginated list of seasons
{ "count": 1, "results": [{ "id": 1, "league_id": 1, "name": "string", "sport": null, "start_date": "2026-01-01", "end_date": "2026-01-01" }] }
GET/open-api/divisions/List divisions
Bearer token required

Returns a paginated list of internal divisions for the authenticated league. External divisions (synced placeholders) are excluded.

ParameterTypeDescription
season_idintegerFilter by season ID
skill_levelstringFilter by skill_level code
is_defaultbooleanFilter by is_default
limitintegerPage size
offsetintegerPagination offset
200Paginated list of divisions
{ "count": 1, "results": [{ "id": 1, "league_id": 1, "season_id": 1, "name": "string", "skill_level": "NA", "is_default": true }] }
GET/open-api/teams/List teams
Bearer token required

Returns a paginated list of teams for the authenticated league. When called with a user-scoped token, results are auto-filtered to teams whose roster includes one of the acting user's participants (via RosterStatus).

ParameterTypeDescription
season_idintegerFilter by season ID
division_idintegerFilter by division ID
user_idintegerFilter to teams whose roster includes a participant belonging to this user
club_teambooleanFilter by club_team flag
is_externalbooleanFilter teams synced from external systems
limitintegerPage size
200Paginated list of teams
{ "count": 1, "results": [{ "id": 1, "league_id": 1, "name": "string", "skill_level": null, "club_team": true, "is_external": true }] }
GET/open-api/locations/List locations
Bearer token required

Returns a paginated list of league locations (gyms / venues). Catalog data: identical results for admin and user tokens.

ParameterTypeDescription
is_rentablebooleanFilter by is_rentable
neighborhood_idintegerFilter by neighborhood ID
priority_minintegerOnly return priority >= this value
limitintegerPage size
200Paginated list of locations
{ "results": [{ "id": 1, "name": "string", "address": null, "is_rentable": true, "priority": 1 }] }
GET/open-api/pass-types/List pass types
Bearer token required

Returns a paginated list of pass types for the authenticated league. Catalog data: identical results for admin and user tokens.

ParameterTypeDescription
is_activebooleanComputed: inactive when make_pass_expires is false and a stale expiration_date is set
type_of_passstringonetime or duration
make_pass_expiresbooleanFilter by make_pass_expires
limitintegerPage size
200Paginated list of pass types
{ "results": [{ "id": 1, "league_id": 1, "name": "string", "type_of_pass": null, "expiration_type": null }] }
GET/open-api/subscription-plans/List subscription plans
Bearer token required

Returns a paginated catalog of subscription plans (recurring memberships). This is the catalog endpoint; for actual purchases see /open-api/memberships/.

ParameterTypeDescription
intervalstringBilling interval: day, week, month, year
is_activebooleanFilter by is_active
is_unlimitedbooleanFilter by is_unlimited
registration_open_atstringYYYY-MM-DD. Returns only plans whose registration window includes this date
category_idintegerFilter by category ID
limitintegerPage size
200Paginated list of subscription plans
{ "results": [{ "id": 1, "league_id": 1, "title": "string", "cost": "0.00", "num_installments": 1 }] }
GET/open-api/coupons/List coupon codes (admin only)
Admin token required

Returns a paginated list of coupon codes for the authenticated league. Admin-only: user-scoped tokens are rejected.

ParameterTypeDescription
activebooleanFilter by active flag
codestringExact-match coupon code lookup
gender_requiredstringFilter by gender_required code
sport_requiredstringFilter by sport_required code
start_date_afterstringISO 8601 datetime
end_date_beforestringISO 8601 datetime
limitintegerPage size
200Paginated list of coupon codes
{ "results": [{ "id": 1, "code": "string", "dollar_amount": "string", "percent_amount": "0.00", "active": true }] }
GET/open-api/waivers/List waivers
Bearer token required

Returns a paginated list of waivers for the authenticated league. Catalog data: identical results for admin and user tokens.

ParameterTypeDescription
is_defaultbooleanFilter by is_default
limitintegerPage size
offsetintegerPagination offset
200Paginated list of waivers
{ "results": [{ "id": 1, "league_id": 1, "title": "string", "is_default": true, "pdf_url": "string" }] }
Schedule

Chronological feed of events — games, practices, class sessions, and generic events.

GET/open-api/events/List events
Bearer token required

Returns a chronologically ordered feed of events (games, practices, class sessions, generic events). Defaults to the current week when no date range is supplied. Each record includes a type_details object with fields specific to the event type. When called with a user-scoped token, results are auto-filtered to events the user's participants are clocked into.

ParameterTypeDescription
start_datestringInclusive start of range (YYYY-MM-DD, league timezone). Must be paired with end_date
end_datestringInclusive end of range (YYYY-MM-DD)
event_typearrayRepeat to request multiple: game, practice, class_session, generic_event. Omit for all
season_idintegerFilter game, practice, and generic_event results to a single season
participant_idintegerFilter to events the participant is clocked into. User-scoped: must be one of the acting user's participants
class_package_idintegerFilter class_session results to a single ClassPackage
session_block_idintegerFilter class_session results to a given SessionBlock
200Array of events
[{ "id": 1, "type": "string", "name": "string", "start_datetime": "2026-01-01T00:00:00Z", "end_datetime": "2026-01-01T00:00:00Z", "time_is_tba": true, "location": "string", "type_details": {} }]
GET/open-api/bookable-calendar/List bookable rental timeslots
Bearer token required

Returns rentable timeslots currently available for booking. Defaults to the current week. League-level rental restrictions (lead hours, max-days-ahead, is_rentable flags) are applied. When participant_id is supplied, results are filtered by membership eligibility. Capped at 250 timeslots per response.

ParameterTypeDescription
start_datestringInclusive start (YYYY-MM-DD). Must be paired with end_date
end_datestringInclusive end of range
location_idintegerRestrict to a single location
sub_location_idintegerRestrict to a single sub-location
staff_member_idintegerRestrict to a single staff member
resource_typestringlocation, sub_location, or staff_member. Omit for all three
participant_idintegerFilter by membership eligibility. User-token callers must pass one of their own participants
category_idintegerRestrict to timeslots in this category
200Array of available timeslots
[{ "id": 1, "resource_type": "string", "window_start": "2026-01-01T00:00:00Z", "window_end": "2026-01-01T00:00:00Z", "minimum_rental_minutes": 60, "price_per_hour": "string", "available_start_times": [] }]
Users & Participants

Directory reads of user profiles and the participants (children/players) attached to them. Admin tokens see the full league; user tokens see only the acting user.

GET/open-api/user-profiles/List user profiles
Bearer token required

Returns a paginated list of user profiles belonging to the authenticated league. When called with a user-scoped token, only returns the acting user's own profile.

ParameterTypeDescription
emailstringCase-insensitive substring match against email (admin tokens only; ignored for user tokens)
limitintegerPage size
offsetintegerPagination offset
200Paginated list of user profiles
{ "results": [{ "id": 1, "league_id": 1, "email": "user@example.com", "first_name": "string", "last_name": "string", "phone": "string", "birthday": "2026-01-01", "gender": null }] }
GET/open-api/participants/List participants
Bearer token required

Returns a paginated list of participants belonging to the authenticated league. When called with a user-scoped token, only returns participants belonging to the acting user.

ParameterTypeDescription
limitintegerPage size
offsetintegerPagination offset
200Paginated list of participants
{ "results": [{ "id": 1, "user_id": 1, "league_id": 1, "first_name": "string", "last_name": "string", "relation": "ME", "birthday": "2026-01-01" }] }
Financials

Invoices, payment transactions, refunds, and credit movements.

GET/open-api/invoices/List invoices
Bearer token required

Returns a paginated list of invoices for the authenticated league. Supports filtering by payment status, date range, and user. When called with a user-scoped token, results are auto-filtered to the acting user's invoices.

ParameterTypeDescription
statusstringFilter by payment status: PA, NP, PR, RF
user_idintegerFilter by user ID
created_afterstringISO 8601 datetime
created_beforestringISO 8601 datetime
limitintegerPage size
200Paginated list of invoices
{ "results": [{ "id": 1, "user_id": 1, "status": "string", "status_display": "string", "invoice_total": "0.00", "date_created": "2026-01-01T00:00:00Z" }] }
GET/open-api/payments/List payment transactions
Bearer token required

Returns a paginated list of payment transactions. By default only paid transactions are returned. Use status=all to include all statuses. When called with a user-scoped token, results are auto-filtered to the acting user's payments.

ParameterTypeDescription
statusstringFilter by status (defaults to PA). Use all to include all statuses
methodstringPayment method: CC, POS, BA, CH, CA, ET, PS, OT
user_idintegerFilter by user ID
created_afterstringISO 8601 datetime
created_beforestringISO 8601 datetime
limitintegerPage size
200Paginated list of payments
{ "results": [{ "id": 1, "user_id": 1, "invoice_id": 1, "status": null, "method": "CC", "receivable": "0.00", "fee_amount": "0.00" }] }
GET/open-api/refunds/List refund transactions
Bearer token required

Returns a paginated list of refund transactions for the authenticated league. When called with a user-scoped token, results are auto-filtered to the acting user's refunds.

ParameterTypeDescription
invoice_idintegerFilter by invoice ID
payment_transaction_idintegerFilter to refunds against this payment transaction
user_idintegerFilter by invoice owner user ID
created_afterstringISO 8601 datetime
created_beforestringISO 8601 datetime
limitintegerPage size
200Paginated list of refunds
{ "results": [{ "id": 1, "invoice_id": 1, "user_id": 1, "payment_transaction_id": 1, "amount": "0.00", "fee_amount": "0.00" }] }
GET/open-api/credits/List credit transactions
Bearer token required

Returns a paginated list of credit transactions (credits used and discounts applied). When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
invoice_idintegerFilter by invoice ID
is_discountbooleanTrue = only discounts; false = only credits
coupon_code_idintegerFilter to a coupon code
user_idintegerFilter by user ID
created_afterstringISO 8601 datetime
limitintegerPage size
200Paginated list of credit transactions
{ "results": [{ "id": 1, "user_id": 1, "invoice_id": 1, "num_points": 1, "is_discount": true, "coupon_code_id": 1 }] }
Registration History

Historical record of who registered for what: class registrations, season registrations, membership registrations, the unified feed, pass purchases, and waiver submissions.

GET/open-api/registrations/List all registrations (unified)
Bearer token required

Returns a unified, paginated feed of all registration types (class, season, membership). When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
typestringFilter by type: class, season, membership
user_idintegerFilter by user ID
participant_idintegerFilter by participant ID
created_afterstringISO 8601 datetime
created_beforestringISO 8601 datetime
limitintegerPage size
200Paginated unified feed
{ "count": 0, "results": [] }
GET/open-api/season-registrations/List season registrations
Bearer token required

Returns a paginated list of season registrations. When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
season_idintegerFilter by season ID
division_idintegerFilter by division ID
team_idintegerFilter by team ID
user_idintegerFilter by user ID
participant_idintegerFilter by participant ID
created_afterstringISO 8601 datetime
limitintegerPage size
200Paginated list
{ "count": 0, "results": [] }
GET/open-api/class-registrations/List class registrations
Bearer token required

Returns a paginated list of class registrations. Supports filtering by date range, user, participant, class package, and payment status. When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
class_package_idintegerFilter by class package ID
participant_idintegerFilter by participant ID
user_idintegerFilter by user ID
payment_statusstringFilter by payment status
created_afterstringISO 8601 datetime
created_beforestringISO 8601 datetime
limitintegerPage size
200Paginated list
{ "results": [{ "id": 1, "user_id": 1, "participant_id": 1, "class_package_id": 1, "class_package_title": "string", "date_created": "2026-01-01T00:00:00Z" }] }
GET/open-api/memberships/List membership registrations
Bearer token required

Returns a paginated list of membership/credit purchase registrations. Supports filtering by date range, user, participant, credit offer, origin, and active status. When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
credit_offer_idintegerFilter by credit offer ID
is_activebooleanFilter by active status
originstringFilter by registration origin
participant_idintegerFilter by participant ID
user_idintegerFilter by user ID
created_afterstringISO 8601 datetime
limitintegerPage size
200Paginated list
{ "results": [{ "id": 1, "user_id": 1, "credit_offer_id": 1, "credit_offer_title": "string", "date_created": "2026-01-01T00:00:00Z" }] }
GET/open-api/pass-purchases/List pass purchases
Bearer token required

Returns a paginated list of pass purchases (passes a user has acquired). When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
pass_type_idintegerFilter by pass type ID
statusstringComputed status: available, spent, or expired
user_idintegerFilter by user ID
created_afterstringISO 8601 datetime
limitintegerPage size
200Paginated list of pass purchases
{ "results": [{ "id": 1, "user_id": 1, "pass_type_id": 1, "pass_type_name": "string", "expiration_date": "2026-01-01", "status": "string" }] }
GET/open-api/waiver-submissions/List waiver submissions
Bearer token required

Returns a paginated list of waiver submissions for the authenticated league. When called with a user-scoped token, results are auto-filtered to the acting user.

ParameterTypeDescription
waiver_idintegerFilter by waiver ID
user_idintegerFilter by user ID
limitintegerPage size
200Paginated list
{ "count": 0, "results": [] }
Registration (write)
GET/open-api/register/{type}/{id}/fields/Get registration fields
Bearer token required

Returns the custom fields required for a given program registration. Call this before submitting a write registration to know which custom_fields keys are required.

ParameterTypeDescription
typerequiredstringProgram type: class_package, season, club, membership, pass_package
idrequiredintegerProgram ID
200List of required registration fields
[{ "key": "string", "label": "string", "type": "string", "required": true }]
POST/open-api/register/programs/Register for programs
User-scoped token required

Registers the authenticated user (or a participant they manage) into a program. Returns a task_id immediately — poll GET /open-api/tasks/{task_id}/ to track completion. Fetch required fields first via GET /open-api/register/{type}/{id}/fields/.

FieldTypeDescription
program_idrequiredintegerID of the program to register for
participant_idintegerParticipant to register (omit to register the account holder)
coupon_codestringOptional discount coupon
custom_fieldsobjectAnswers to required registration fields (from /fields/ endpoint)
202Registration queued — poll task for result
{ "task_id": "string", "status": "pending" }
GET/open-api/tasks/{task_id}/Poll async task status
Bearer token required

Polls the status of an asynchronous operation. Keep polling until status is complete or failed. Recommended interval: 1–2 seconds.

ParameterTypeDescription
task_idrequiredstringTask ID returned by the write operation
200Task complete
{
  "task_id": "string", "status": "complete",
  "result": { "registration_id": 99, "invoice_id": 12, "pending_waiver_ids": [4, 7] }
}
failedTask failed
{ "task_id": "string", "status": "failed", "error": "Program is full." }
My Account (user-scoped)
GET/open-api/me/Read user profile
User-scoped token required

Returns the profile of the authenticated user — name, email, phone, address, and account preferences.

No parameters

200User profile
{ "id": 1, "email": "user@example.com", "first_name": "string", "last_name": "string", "phone": "string" }
PATCH/open-api/me/Update user profile
User-scoped token required

Partially updates the authenticated user's profile. Only include fields you want to change.

FieldTypeDescription
first_namestringFirst name
last_namestringLast name
phonestringPhone number
addressobjectAddress fields
200Updated user profile
{ "id": 1, "email": "user@example.com", ... }
GET/open-api/me/memberships/List memberships
User-scoped token required

Returns the authenticated user's active and historical memberships, including pause/cancel eligibility flags.

status (active, paused, cancelled), limit, offset

200Paginated list of memberships
{ "count": 0, "results": [] }
POST/open-api/me/memberships/{id}/cancel/Cancel membership
User-scoped token required

Cancels the specified membership. Check can_cancel flag on the membership object before calling. Takes effect at end of billing period unless immediate: true.

FieldTypeDescription
reasonstringCancellation reason (optional)
immediatebooleanCancel immediately vs. end of period. Default: false
200Membership cancelled
{ "status": "cancelled", "effective_date": "2026-07-01" }
POST/open-api/me/memberships/{id}/pause/Pause membership
User-scoped token required

Pauses the membership. Billing is suspended for the pause duration. Check can_pause flag before calling.

FieldTypeDescription
resume_datedateDate to automatically resume (YYYY-MM-DD)
200Membership paused
{ "status": "paused", "resume_date": "2026-08-01" }

Tutorials

Step-by-step walkthroughs for the most common integration scenarios. Click any tutorial to expand it.

Authenticate and make your first API call
Verify credentials, call health, confirm your tenant ID
Beginner
  1. 1
    Get your admin Bearer token

    Your Playbook Technical Implementation team provisions your admin token out-of-band. You'll receive it directly — it does not expire unless manually revoked. Store it securely; treat it like a password.

  2. 2
    Call the health endpoint

    Make a GET request to confirm your token is valid and the API is reachable. Replace YOUR_TOKEN with your admin Bearer token.

    curl -X GET https://callplaybook.com/open-api/health/ \
      -H "Authorization: Bearer YOUR_TOKEN"

    Expected response:

    {
      "status": "ok",
      "league_id": 42
    }
    Note the league_id — this is your organization's tenant identifier. It will appear on every response object.
  3. 3
    Verify your identity with whoami

    Call GET /open-api/auth/whoami/ to confirm the token type and confirm it's scoped to the right tenant.

    curl -X GET https://callplaybook.com/open-api/auth/whoami/ \
      -H "Authorization: Bearer YOUR_TOKEN"

    Expected response for an admin token:

    {
      "user_id": null,
      "user_email": null,
      "league_id": 42,
      "expires_at": null,
      "is_test": false
    }
    user_id: null confirms this is an admin token, not a user-scoped token. is_test: false confirms you're in live mode.
  4. 4
    You're ready

    Your token is valid, your league_id is confirmed, and you can make authenticated requests to any admin-scoped endpoint. For user-facing integrations, proceed to Tutorial 2 to mint user-scoped tokens.

Register a participant in a program
Discover programs, fetch fields, mint a user token, submit and poll
Intermediate
  1. 1
    List available programs

    Fetch the program catalog to find the program ID you want to register into. Use the type filter to narrow results.

    curl -X GET "https://callplaybook.com/open-api/programs/?type=season" \
      -H "Authorization: Bearer ADMIN_TOKEN"

    Note the id of the target program from the results array.

  2. 2
    Fetch required registration fields

    Before registering, call the fields endpoint to know what custom data is required. Replace {type} and {id} with the program type and ID from step 1.

    curl -X GET https://callplaybook.com/open-api/register/season/101/fields/ \
      -H "Authorization: Bearer ADMIN_TOKEN"

    Response is an array of field definitions. Store any required: true fields — you must include them in your registration payload.

  3. 3
    Mint a user-scoped token for the member

    Registration requires a user-scoped token. Use your admin token to mint one for the member by their user_id or email.

    curl -X POST https://callplaybook.com/open-api/auth/user-tokens/ \
      -H "Authorization: Bearer ADMIN_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"user_id": 5821, "ttl_seconds": 3600}'

    Store the token from the response. It expires in 1 hour.

    To test without writing real data, add "is_test": true to the payload. All validation runs but no records are created.
  4. 4
    Submit the registration

    POST to the programs registration endpoint using the user-scoped token. Include program_id, optionally participant_id, and any required custom_fields.

    curl -X POST https://callplaybook.com/open-api/register/programs/ \
      -H "Authorization: Bearer USER_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "program_id": 101,
        "participant_id": 2204,
        "custom_fields": {"jersey_size": "M", "emergency_contact": "555-0100"}
      }'

    The response returns immediately with a task_id and status: "pending".

  5. 5
    Poll the task until complete

    Poll every 1–2 seconds using the task_id from step 4 until status is complete or failed.

    curl -X GET https://callplaybook.com/open-api/tasks/abc123/ \
      -H "Authorization: Bearer USER_TOKEN"

    A completed task returns:

    {
      "task_id": "abc123",
      "status": "complete",
      "result": {
        "registration_id": 9901,
        "invoice_id": 4412,
        "pending_waiver_ids": [7, 8]
      }
    }
    If pending_waiver_ids is non-empty, the member still needs to sign waivers. Submit them via POST /open-api/me/waiver-submissions/ before access is granted.
Pull a member's schedule and event feed
Use a user-scoped token to return only the member's relevant events
Beginner
  1. 1
    Mint a user-scoped token

    Follow step 3 from Tutorial 2 to mint a token for the specific member whose schedule you want to retrieve. The user-scoped token automatically filters event results to that member's registered programs and teams.

  2. 2
    Fetch the member's upcoming events

    Call GET /open-api/events/ with a date range. The user-scoped token means you get back only events the member's participants are clocked into — no filtering logic needed on your side.

    curl -X GET \
      "https://callplaybook.com/open-api/events/?start_date=2026-06-01&end_date=2026-06-30" \
      -H "Authorization: Bearer USER_TOKEN"

    Response is an array of event objects. Each includes type (game, practice, class_session), start_datetime, end_datetime, location, and a type_details object with event-specific fields.

  3. 3
    Filter by event type (optional)

    To return only games, repeat the event_type parameter for each type you want.

    curl -X GET \
      "https://callplaybook.com/open-api/events/?start_date=2026-06-01&end_date=2026-06-30&event_type=game&event_type=practice" \
      -H "Authorization: Bearer USER_TOKEN"
  4. 4
    Handle the time_is_tba flag

    Some events have a confirmed date but no set time yet. Check the time_is_tba boolean on each event before displaying a time in your UI — display "TBA" instead of a time when it's true.

    The API returns datetimes in UTC. Convert to the member's local timezone in your application layer.
Sync payment and invoice data to an external system
Export financial records with pagination and date filters
Intermediate
  1. 1
    Fetch invoices for a date range

    Use your admin token to pull all invoices created within a period. Use created_after and created_before as ISO 8601 datetimes.

    curl -X GET \
      "https://callplaybook.com/open-api/invoices/?created_after=2026-05-01T00:00:00Z&created_before=2026-06-01T00:00:00Z&limit=100" \
      -H "Authorization: Bearer ADMIN_TOKEN"

    Check count in the response. If it exceeds your limit, paginate using the next URL.

  2. 2
    Paginate through all records

    Keep following the next URL in the response until it returns null. This pattern is the same across all list endpoints.

    # First page
    GET /open-api/invoices/?created_after=...&limit=100
    # Response includes:
    "next": "https://callplaybook.com/open-api/invoices/?...&offset=100"
    
    # Follow next until null
    GET /open-api/invoices/?...&offset=100
    GET /open-api/invoices/?...&offset=200
  3. 3
    Pull corresponding payment transactions

    For each invoice, fetch the payment transactions to get method, amount, and fee breakdown.

    curl -X GET \
      "https://callplaybook.com/open-api/payments/?created_after=2026-05-01T00:00:00Z&status=all&limit=100" \
      -H "Authorization: Bearer ADMIN_TOKEN"
    Omitting status=all returns only paid (PA) transactions by default. Pass status=all to include pending, refunded, and failed transactions for a complete audit trail.
  4. 4
    Pull refunds and credits separately

    Refunds and applied credits are on their own endpoints. Fetch them with the same date range and join to invoices via invoice_id.

    GET /open-api/refunds/?created_after=2026-05-01T00:00:00Z&limit=100
    GET /open-api/credits/?created_after=2026-05-01T00:00:00Z&limit=100
  5. 5
    Map to your external system

    Each invoice has a user_id you can join to GET /open-api/user-profiles/ for member details. The status_display field on invoices gives a human-readable status (Paid, Not Paid, Partial, Refunded) suitable for display in your accounting tool.

Book a rental timeslot for a member
Query availability, check eligibility, submit and poll — Beta endpoint
Intermediate  ·  Beta
This tutorial covers a Beta endpoint. Test thoroughly in sandbox mode before enabling in production. Contact your Technical Implementation team before go-live.
  1. 1
    Fetch available rental timeslots

    Call the bookable calendar with a date range and optionally filter by location. Results respect league-configured lead time and max-days-ahead restrictions automatically.

    curl -X GET \
      "https://callplaybook.com/open-api/bookable-calendar/?start_date=2026-06-10&end_date=2026-06-10&location_id=3" \
      -H "Authorization: Bearer USER_TOKEN"

    Each result includes window_start, window_end, minimum_rental_minutes, price_per_hour, and an available_start_times array of valid booking start times.

  2. 2
    Check membership eligibility

    Pass participant_id to filter results to only slots the participant is eligible to book based on their membership. If no participant_id is passed, all timeslots are returned regardless of eligibility.

    curl -X GET \
      "https://callplaybook.com/open-api/bookable-calendar/?start_date=2026-06-10&end_date=2026-06-10&participant_id=2204" \
      -H "Authorization: Bearer USER_TOKEN"
  3. 3
    Dry-run the booking first

    Before submitting a real booking, validate your payload with the dry-run header. The server runs all validation but writes nothing.

    curl -X POST https://callplaybook.com/open-api/register/bookable-calendar/ \
      -H "Authorization: Bearer USER_TOKEN" \
      -H "Content-Type: application/json" \
      -H "X-Open-API-Dry-Run: true" \
      -d '{
        "timeslot_id": 88,
        "participant_id": 2204,
        "start_time": "2026-06-10T10:00:00Z",
        "duration_minutes": 60
      }'

    A 202 response with no errors means your payload is valid. Remove the dry-run header to submit for real.

  4. 4
    Poll the task for confirmation

    The booking endpoint returns a task_id immediately. Poll GET /open-api/tasks/{task_id}/ until status is complete. The result will include the registration_id and invoice_id for the booking.

Manage membership lifecycle
Read eligibility flags, then pause, resume, or cancel a membership
Intermediate
  1. 1
    Fetch the member's memberships

    Using a user-scoped token, call GET /open-api/me/memberships/ to retrieve the member's current memberships. Each object includes status (active, paused, cancelled) and permission flags.

    curl -X GET https://callplaybook.com/open-api/me/memberships/ \
      -H "Authorization: Bearer USER_TOKEN"
  2. 2
    Check eligibility flags before acting

    Each membership object includes can_pause and can_cancel booleans. Always check these before displaying options to the member or submitting a request — they reflect the league's configured rules for that membership plan.

    {
      "id": 331,
      "status": "active",
      "credit_offer_title": "Monthly Unlimited",
      "can_pause": true,
      "can_cancel": true
    }
    Only show "Pause" or "Cancel" buttons in your UI when the corresponding flag is true. If a member can't pause, the API will reject the request — don't let users attempt it.
  3. 3
    Pause the membership

    POST to the pause endpoint with an optional resume_date. Billing is suspended from the pause date until resumption.

    curl -X POST https://callplaybook.com/open-api/me/memberships/331/pause/ \
      -H "Authorization: Bearer USER_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"resume_date": "2026-08-01"}'

    Response confirms the new status and resume date.

  4. 4
    Cancel the membership

    POST to the cancel endpoint. By default cancellation takes effect at the end of the current billing period. Pass "immediate": true to cancel instantly.

    curl -X POST https://callplaybook.com/open-api/me/memberships/331/cancel/ \
      -H "Authorization: Bearer USER_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"reason": "Moving out of area", "immediate": false}'

    Response includes status: "cancelled" and effective_date confirming when the cancellation takes effect.

  5. 5
    Resume a paused membership

    If a membership was paused without a resume_date, or you want to resume early, POST to the resume endpoint.

    curl -X POST https://callplaybook.com/open-api/me/memberships/331/resume/ \
      -H "Authorization: Bearer USER_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{}'

Need a custom integration walkthrough?

Our Technical Implementation team can guide you through your specific use case on a setup call.

Talk to our team

Frequently Asked Questions

Common questions about integrating with the Playbook Open API. Can't find what you need? Contact your Playbook Success Coach.

How do I get access to the API?
API access is provisioned by Playbook's Technical Implementation team. Reach out to your Playbook Success Coach to schedule a setup call. They'll provision your admin Bearer token, walk you through your first authenticated request, and confirm which endpoints are enabled for your organization.
What is the difference between an admin token and a user-scoped token?
An admin token is provisioned out-of-band and has read access across your entire organization's data — all users, registrations, financials, and scheduling. A user-scoped token is minted on demand via POST /open-api/auth/user-tokens/ and automatically filters every response to a single end-user's records. User-scoped tokens expire after 1 hour by default (max 8 hours) and are designed for member-facing applications where you want each user to see only their own data.
How do I test my integration without affecting live data?
Pass is_test: true when minting a token to issue a sandbox token. Every write request authenticated by a sandbox token runs full server-side validation — registration rules, payment logic, waiver requirements — but produces no database changes, charges, or notification emails. You can also add the X-Open-API-Dry-Run: true header on any individual write request to sandbox just that call without changing the token.
Why do write operations return a task ID instead of a result immediately?
Registration and booking operations involve multi-step business logic — payment authorization, invoice generation, waiver assignment, confirmation emails — that can't safely complete within a single synchronous HTTP request. The API returns a task_id immediately so your application stays responsive. Poll GET /open-api/tasks/{task_id}/ every 1–2 seconds until status is complete or failed. A completed task includes the full result — registration ID, invoice ID, and any pending waiver IDs that still need to be submitted.
Does the API have rate limits?
Rate limits are applied per token. Sandbox tokens are subject to a lower threshold to protect the testing environment. Admin tokens used for bulk data sync (e.g. nightly exports of registrations or payments) should use the limit and offset pagination parameters rather than issuing high-frequency parallel requests. Contact your Technical Implementation team if your integration pattern requires elevated throughput.
How does pagination work on list endpoints?
All list endpoints return a standard envelope: count (total records matching your filters), next (full URL for the next page, or null if you're on the last page), previous, and results. Control page size with the limit parameter (default: 20) and position with offset. To page through all records, keep following the next URL until it returns null.
What does league_id mean in API responses?
league_id is the internal identifier for your organization's tenant in the Playbook platform. It appears in response objects to confirm which tenant the data belongs to. You never need to pass it in requests — your Bearer token determines tenant scope automatically. If you call GET /open-api/auth/whoami/ you can confirm the league_id your token is scoped to.
Which endpoints are marked Beta, and can I use them in production?
Club registration, subscription registration, pass package purchase, and rental booking (POST /open-api/register/bookable-calendar/) are currently in Beta. They are fully supported in sandbox mode and have been tested against common workflows, but edge cases may exist. We recommend coordinating with the Technical Implementation team before enabling Beta endpoints in a production user flow. Non-Beta endpoints are stable and production-ready.
How do I handle required registration fields before submitting a registration?
Call GET /open-api/register/{type}/{id}/fields/ before any write registration. This returns the list of custom fields the specific program requires, including field keys, labels, types, and whether they're required. Pass the answers as a custom_fields object in your registration POST body. Skipping this step will result in a validation error if required fields are missing.
Can I use the API to build a member-facing app or portal?
Yes — that's a primary use case. The pattern is: authenticate your backend with an admin token, mint a short-lived user-scoped token for each member session via POST /open-api/auth/user-tokens/, and pass that token to your client application. The user-scoped token automatically filters all reads to that member's data and can register them into programs, manage their memberships, and submit waivers. Revoke the token on logout via POST /open-api/auth/user-tokens/revoke/.

Still have questions?

Our Technical Implementation team is available to help with any integration questions not covered here.

Contact your Success Coach

Support

Get help with your integration or escalate a technical issue. All API access is set up through your Playbook Success Coach.

Success Coach

Your Playbook Success Coach is your primary point of contact for API access setup, integration planning, and coordinating with our Technical Implementation team. Reach out at customersuccess@callplaybook.com to get started.

Technical Implementation

For complex integrations, our Technical Implementation team can join a call to review your architecture, help you reach production faster, and connect you with our sales team.

API Reference

Browse all 48 endpoints, request and response schemas, and parameter definitions in the full API Reference section of this portal.

View API reference →

Tutorials

Step-by-step guides for authentication, registration, scheduling, payment sync, and membership lifecycle management.

Browse tutorials →

When to contact us

Getting started

To request API credentials, set up your first integration, or provision a QA environment — start with your Playbook Success Coach.

Production issues

For unexpected errors, authentication failures, or data discrepancies in production, contact your Success Coach and include the endpoint path, relevant request details, and any task IDs or error messages.

Feature requests

Have a use case the current API doesn't support? Let your Success Coach know — our Technical Implementation team reviews integration feedback regularly.