> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fitsociety.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Public API Authentication

> Authenticate with OAuth client credentials and Bearer tokens.

The Public API uses OAuth client credentials for server-to-server access. This
matches the Jortt-style pattern: use `client_id` and `client_secret` at the token
endpoint, then call API resources with a Bearer token.

<Note>
  Setting up for the first time? The [Quickstart](/public-api/quickstart) walks
  through credential creation, token exchange, and a first call step by step.
</Note>

<Warning>
  Public API resource calls do not accept `x-api-key`. The `x-api-key` header is
  not part of the new Public API auth model.
</Warning>

<Note>
  `/public/v1/access/*` uses a separate device-key contract for gates and
  scanners. It does not use OAuth scopes or `fspt_...` Bearer tokens. See
  [Access Devices](/access-devices/overview) for `x-device-key` authentication.
</Note>

## 1. Create an OAuth client

A coach creates a Public API OAuth client from the authenticated FITsociety app
API:

```http theme={null}
POST /app/v1/integrations/public-api/clients
Authorization: Bearer <coach_token>
Content-Type: application/json
```

```json theme={null}
{
  "name": "Zapier sync",
  "scopes": ["clients:read", "clients:write", "bookings:read"],
  "defaultAssignedCoachId": "66f7b8b1e13c8d25f4d3d90a",
  "consents": { "healthData": false, "privateCommunication": false }
}
```

The response includes `clientSecret` once. Store it securely. FITsociety stores
only a hash of the secret.

### Consent-gated scopes

Some scopes expose health data or private communication. Granting them requires
an explicit consent in the optional `consents` object:

* Scopes marked `requiresConsent: "health"` in the
  [scope catalog](/public-api/platform) (measurements, progress summaries and
  photos, intakes, checkups, form assignments, habits, goals, documents) require
  `"consents": { "healthData": true }`. Otherwise creation fails with
  `400 PUBLIC_API_HEALTH_CONSENT_REQUIRED`.
* Scopes marked `requiresConsent: "private_communication"` (messages, client
  notes) require `"consents": { "privateCommunication": true }`. Otherwise
  creation fails with `400 PUBLIC_API_PRIVATE_COMM_CONSENT_REQUIRED`.

Accepted consents are stored on the client with the acceptance timestamp and
accepting coach. At runtime, tokens for a client without the matching accepted
consent receive `403 scopes.health_consent_required` or
`403 scopes.private_communication_consent_required` on consent-gated endpoints,
even when the scope itself was granted. `GET /public/v1/scopes` marks each
consent-gated scope with a `requiresConsent` field.

## 2. Request an access token

Exchange the client credentials for an access token:

```bash theme={null}
curl -X POST \
  -u "<client_id>:<client_secret>" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&scope=clients:write" \
  https://api.fitsociety.io/public/v1/oauth/token
```

Response:

```json theme={null}
{
  "access_token": "fspt_0123456789abcdef0123456789abcdef0123456789abcdef",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "clients:write"
}
```

If `scope` is omitted, FITsociety issues all scopes assigned to the client.
Requested scopes must be a subset of the client's assigned scopes.

### Current company access

Each resource request checks whether Public API access is currently available
for the company bound to the token. Removing that company from a private
provider's allowlist, or disabling the provider globally, blocks the next
request with `403 auth.provider_unavailable`, including requests with an
unexpired token. Re-enabling access allows otherwise valid tokens to work
again. Revoking an OAuth client cannot be undone and returns
`401 auth.invalid_client` (or `401 auth.invalid_token` for revoked tokens).

## Available scopes

| Scope | Purpose |
| :- | :- |
| `platform:read` | Read the authenticated API client profile, capabilities, and scope catalog. |
| `audit_logs:read` | Read redacted Public API audit logs. |
| `company_catalog:read` | Read company profile, facilities, services, and policy metadata. |
| `locations:read` | Read company locations. |
| `locations:write` | Create, update, and archive company locations. |
| `clients:read` | Read Core CRM clients and client tags. |
| `clients:write` | Create, update, archive, and assign safe Core CRM client fields. |
| `client_onboarding:write` | Send portal invites and approve or reject pending client relationships. |
| `client_custom_fields:read` | Read company custom field definitions and client custom field values. |
| `client_custom_fields:write` | Update client custom field values. |
| `client_timeline:read` | Read sanitized client lifecycle timeline events. |
| `client_notes:read` | Read client notes. Consent-gated (private communication). |
| `client_notes:write` | Create, update, and delete client notes. Consent-gated (private communication). |
| `coaches:read` | Read coaches. |
| `coach_availability:read` | Read coach availability templates. |
| `coach_availability:write` | Replace coach availability templates. |
| `calendar_events:read` | Read calendar events. |
| `event_types:read` | Read event type labels used by event templates. |
| `event_types:write` | Create, update, and archive event type labels. |
| `event_templates:read` | Read event templates used by calendar availability and bookings. |
| `event_templates:write` | Create, update, and archive event templates. |
| `recurring_bookings:read` | Read recurring booking chains. |
| `recurring_bookings:write` | Update safe recurring booking settings and cancel chains. |
| `calendar_tasks:read` | Read blocking calendar tasks. |
| `calendar_tasks:write` | Create, update, and cancel blocking calendar tasks. |
| `booking_requests:read` | Read booking requests. |
| `booking_requests:write` | Approve or reject pending booking requests. |
| `location_availability:read` | Read location availability templates. |
| `location_availability:write` | Replace location availability templates. |
| `availability_rules:read` | Read availability closure metadata. |
| `availability_rules:write` | Replace availability closure metadata. |
| `availability:read` | Read bookable availability slots and short-lived booking tokens. |
| `bookings:read` | Read bookings and booking cancellation context. |
| `bookings:write` | Create bookings, update attendance, and cancel bookings. |
| `finance_invoices:read` | Read invoice metadata and line items. |
| `finance_invoice_pdfs:read` | Read existing invoice PDF download metadata. |
| `finance_payments:read` | Read transaction metadata. |
| `finance_payment_requests:read` | Read payment request metadata. |
| `finance_payment_requests:write` | Create and cancel guarded payment requests. |
| `finance_chargebacks:read` | Read chargeback metadata. |
| `finance_invoice_messages:write` | Send invoice reminders and invoice copies for eligible invoices. |
| `finance_products:read` | Read product metadata. |
| `finance_products:write` | Assign/revoke supported products with finance guards. |
| `finance_subscriptions:read` | Read subscriptions. |
| `finance_subscription_actions:write` | Create subscription pause and cancellation requests for review. |
| `finance_memberships:write` | Assign membership products with finance guards. |
| `finance_credits:read` | Read credits and credit mutations. |
| `finance_credits:write` | Adjust client credits. |
| `measurements:read` | Read measurement types and entries. Consent-gated (health). |
| `measurements:write` | Create, update, and soft-archive measurement entries. Consent-gated (health). |
| `progress_summaries:read` | Read aggregated measurement progress summaries. Consent-gated (health). |
| `progress_photos:read` | Read progress photo metadata and short-lived signed image URLs. Consent-gated (health). |
| `habits:read` | Read client habits and habit entries. Consent-gated (health). |
| `habits:write` | Create, update, and archive habit entries. Consent-gated (health). |
| `goals:read` | Read public-safe client goal summaries. Consent-gated (health). |
| `goals:write` | Update public-safe client goal fields. Consent-gated (health). |
| `forms:read` | Read form metadata and sanitized form detail. |
| `forms:write` | Create, update and archive company form templates. |
| `form_assignments:write` | Assign intake forms. Consent-gated (health). |
| `intakes:read` | Read current intake assignment status and submitted intake forms. Consent-gated (health). |
| `checkups:read` | Read checkups and submitted checkup forms. Consent-gated (health). |
| `checkups:write` | Assign and cancel checkup schedules. Consent-gated (health). |
| `documents:read` | Read document and folder metadata. Consent-gated (health). |
| `documents:write` | Link, update, and archive external document metadata. Consent-gated (health). |
| `attendance_summaries:read` | Read aggregate booking attendance summaries. |
| `revenue_summaries:read` | Read aggregate invoice revenue summaries. |
| `retention_summaries:read` | Read aggregate client relationship summaries. |
| `webhooks:read` | List and read outbound webhook subscriptions. |
| `webhooks:write` | Create, update, delete, and test outbound webhook subscriptions. |
| `webhook_deliveries:read` | List and inspect outbound webhook delivery attempts. |

## 3. Call a resource

Use the access token in the `Authorization` header:

```http theme={null}
Authorization: Bearer fspt_...
```

Example:

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer <access_token>" \
  -H "Idempotency-Key: create-client-jane-2026-07-14" \
  -H "Content-Type: application/json" \
  -d '{"firstName":"Jane","email":"jane@example.com"}' \
  https://api.fitsociety.io/public/v1/clients
```

Write requests require a stable `Idempotency-Key` header. Reuse the same key
only when retrying the exact same request.

## Token lifetime

| Credential | Prefix | Lifetime |
| :- | :- | :- |
| Client ID | `fspc_` | Until revoked |
| Client secret | `fsps_` | Until rotated or revoked |
| Access token | `fspt_` | 1 hour |

Rotating a client secret revokes existing access tokens for that client.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.