Security

Use the smallest key that can do the job.

Publishable keys

Publishable keys (flow_pk_...) are for the Storefront API. They are read-only and safe to include in browser code. They should still be treated as identifiers: avoid logging more than the prefix and last few characters.

Secret keys

Secret keys (flow_sk_...) are for the Management API. They are server-only. Never put a secret key in:

Use a server endpoint you control when your website needs to perform a Management action. The browser calls your server; your server calls Management with the secret key.

Scope hygiene

Give each integration its own key and grant only the scopes it needs.

Scope Operations
classes:read GET /v1/classes
classes:write POST /v1/classes
PATCH /v1/classes/{classId}
DELETE /v1/classes/{classId}
content:read GET /v1/content
content:write PATCH /v1/content/{contentId}
DELETE /v1/content/{contentId}
coupons:read GET /v1/coupons
coupons:write POST /v1/coupons
DELETE /v1/coupons/{couponId}
instructors:read GET /v1/instructors
instructors:write POST /v1/instructors
PATCH /v1/instructors/{instructorId}
locations:read GET /v1/locations
GET /v1/locations/{locationId}/rooms
locations:write POST /v1/locations
PATCH /v1/locations/{locationId}
DELETE /v1/locations/{locationId}
POST /v1/locations/{locationId}/rooms
PATCH /v1/locations/{locationId}/rooms/{roomId}
DELETE /v1/locations/{locationId}/rooms/{roomId}
members:read GET /v1/members
members:write POST /v1/members/invites
PATCH /v1/members/{membershipId}
POST /v1/members/{membershipId}/cancel
plans:read GET /v1/plans
plans:write POST /v1/plans
PATCH /v1/plans/{planId}
DELETE /v1/plans/{planId}
programs:read GET /v1/programs
GET /v1/programs/{programId}
programs:write POST /v1/programs
PATCH /v1/programs/{programId}
schedule:read GET /v1/schedule
schedule:write PATCH /v1/schedule/{occurrenceId}

Rotate keys when people leave, vendors change, or a key might have been exposed. Create the replacement first, deploy it, verify traffic, then revoke the old key.

Member credentials

If you use the embeddable SDK, members sign in inside the hosted widget. Your page receives a short-lived member token over an origin-pinned channel; it never handles member passwords.