PlayaOS Developer Docs

Quickstart

Build a camp website with public embeds and authenticated server-side data.

Choose the integration

Use @playaos/api-client on your server for authenticated REST data. Public application forms use @playaos/react and the browser-safe camp key from the Embed origins section. The React hooks Provider accepts a client; the separate @playaos/sdk widget Provider accepts widget configuration. They are not interchangeable.

Create an org API key on Developer → API Keys. Its freshly generated setup prompt contains the key. Generate the confidential SDK client on the same page or Developer → SDK setup; the prompt fills in its ID and secret immediately. Previously generated secrets cannot be retrieved: paste your saved API key or use the secret you stored when provisioning.

Environment variables

# Server-only
PLAYAOS_API_KEY=pk_live_YOUR_CAMP_KEY
PLAYAOS_API_BASE_URL=https://api.playaos.app
PLAYAOS_EMBED_BASE_URL=https://your-camp.playaos.app
PLAYAOS_CLIENT_SECRET=<saved confidential SDK client secret>
PLAYAOS_ORG_ID=<org UUID>

# Public configuration
NEXT_PUBLIC_PLAYAOS_CLIENT_ID=<Camp portal public client ID>
NEXT_PUBLIC_PLAYAOS_CONFIDENTIAL_CLIENT_ID=<matching confidential SDK client ID>
NEXT_PUBLIC_PLAYAOS_ORG_SLUG=your-camp
NEXT_PUBLIC_PLAYAOS_AUTH_BASE_URL=https://auth.playaos.app
NEXT_PUBLIC_PLAYAOS_EMBED_KEY=pk_live_YOUR_EMBED_CAMP_KEY

createClient appends /api/v1 itself: pass the origin as baseUrl. Its embedBaseUrl is the camp portal origin. An org API key must never appear in a browser bundle, browser Provider, URL, or public env variable.

Authenticated server data

pnpm add @playaos/api-client
import { createClient } from "@playaos/api-client";

const client = createClient({
  apiKey: process.env.PLAYAOS_API_KEY!,
  baseUrl: process.env.PLAYAOS_API_BASE_URL!,
  embedBaseUrl: process.env.PLAYAOS_EMBED_BASE_URL!,
});

// Use the acting member's verified Supabase session JWT on each request.
const memberClient = client.withMember(memberSessionJwt);
const dues = await memberClient.dues.list();

Resolve memberSessionJwt from the signed-in user's session in your server code. Member-scoped reads and admin writes require that identity in addition to the org key; the authentication guide explains both credentials. Render server-fetched data through your own UI.

Public application form

Install React 19+ and the React integration:

pnpm add @playaos/react @playaos/api-client @tanstack/react-query

Use your separately provisioned camp embed key and allow your website origin in the platform's Developer page. This key is deliberately public and separate from the server's org API key.

"use client";

import { createClient } from "@playaos/api-client";
import { ApplicationForm, PlayaOSProvider } from "@playaos/react";

const client = createClient({
  apiKey: process.env.NEXT_PUBLIC_PLAYAOS_EMBED_KEY!,
  baseUrl: "https://api.playaos.app",
  embedBaseUrl: "https://your-camp.playaos.app",
});

export default function ApplyPage() {
  return (
    <PlayaOSProvider client={client}>
      <ApplicationForm orgId="your-org-uuid" />
    </PlayaOSProvider>
  );
}

See the application form guide for its props and custom fields.

OAuth session persistence

Use the confidential SDK client ID and its matching secret for server-side code exchange and refresh. The separate public Camp portal client uses browser PKCE without a secret. Register your app's callback URL on the OAuth client under Integrations.

The auth guide explains exchange and refresh. Keep refresh tokens in HttpOnly cookies and return short-lived access tokens only to the owning session. Validate request bodies and callback URLs before exchanging a code.

Coding agent instructions

Build a custom camp portal using PlayaOS for the API, database, and authentication. Read https://playaos.app/docs/sdk-setup and https://playaos.app/docs/authentication before coding. Use @playaos/api-client in server code for authenticated REST calls at https://api.playaos.app/api/v1. Pass the origin (https://api.playaos.app, without /api/v1) as createClient's baseUrl, and the camp portal origin as embedBaseUrl. For member-scoped reads and admin writes, derive a per-request client with withMember(the signed-in member's Supabase session JWT). Keep PLAYAOS_API_KEY and PLAYAOS_CLIENT_SECRET in server-only environment variables. Never pass an org key to a browser Provider. For a public application form, use @playaos/react's PlayaOSProvider with a createClient configured with the browser-safe camp key from the Embed origins section, then render ApplicationForm. The @playaos/sdk Provider is a separate widget API, not the React hooks Provider. The SDK exchange idToken is for legacy embed auth, not a Supabase session JWT; never send it as X-PlayaOS-Member-Token. For OAuth session persistence, use the confidential client ID together with its matching secret in server-side exchange/refresh routes; keep refresh tokens in HttpOnly cookies. The Camp portal public client ID is for browser PKCE without a secret. Use @playaos/ui-kit only if its design fits. Verify a public application submission, a signed-in member read, and that neither server secret appears in browser bundles.

Verify

  • Submit a public application and confirm it appears in your camp's admin portal.
  • Read a member's dues using their signed-in session and the appropriate org key scope.
  • Verify OAuth session refresh uses the confidential client and that neither server secret reaches browser bundles.

API reference · Scopes · Embeds