ControlPlaneDocs
Console
Docs/Getting started/Quickstart

Quickstart

Set up Control Plane and make your first API call in under 15 minutes.

Time
~15 minutes
Requires
Stripe account
Runtime
Node.js 18+
Prerequisite
You'll need an existing Stripe account (test mode is fine) and Node.js 18 or higher. If you don't have Node yet, install it with brew install node or from nodejs.org.

1Create your account

Head to console.aaronchangai.org and sign up with GitHub or email. No credit card required, and you can use Control Plane in test mode for as long as you like.

Open the Console

2Create your app

In the Console, navigate to Settings and click Create app. An app represents one of your SaaS products — each one gets its own isolated Stripe integration and webhook endpoint, so test and production stay completely separate.

console.aaronchangai.org/settings/apps
screenshot placeholder
Console → Settings → Create app. Give the app a human-readable name; the slug is auto-generated and editable.

Common pattern: create two apps — my-saas-dev and my-saas-prod — and point each at its own Stripe account.

3Connect your payment provider

Navigate to Settings → your app → Configure Stripe. The flow has four parts: get your secret key, save it (which generates your webhook URL), register the webhook in Stripe, then save the signing secret back in the Console.

  1. 1Stripe Dashboard → Developers → API keys: copy your sk_test_… (or sk_live_…) secret key.
  2. 2Paste it into the Secret Key field in the Console and click Save. A Webhook URL will appear — copy it.
  3. 3Stripe Dashboard → Developers → Webhooks → Add endpoint. Paste your Webhook URL and select the three customer.subscription.* events.
  4. 4Stripe shows a Signing Secret (whsec_…) only once. Paste it into the Webhook Secret field in the Console. Save.
Webhook URL format
https://api.aaronchangai.org/api/v1/webhooks/stripe/{appId}
Stripe events to subscribe to
customer.subscription.created
customer.subscription.updated
customer.subscription.deleted
Tip
The signing secret is shown only once by Stripe. If you missed it, open your webhook endpoint in the Stripe Dashboard and click Reveal signing secret.

4Create your first organization

Organizations represent your customers' workspaces. Create one from the Console dashboard to test your setup before going live — it takes about ten seconds.

console.aaronchangai.org/orgs/new
screenshot placeholder
From the dashboard, click New Organization. Give it a name and slug; everything else is configured later via the API.
Verify
You can also create organizations programmatically once you're ready. Most teams call cp.orgs.create() from a Stripe checkout.session.completed handler to provision workspaces the moment a customer subscribes.

5Get an API key

API keys let your backend call the Control Plane API on behalf of an organization. They're scoped per-org and per-environment (live or test).

console.aaronchangai.org/orgs/{slug}/keys
screenshot placeholder
Open the org you just created, switch to API Keys, and click Create API Key.
bash
export CONTROLPLANE_API_KEY="cp_live_xxxxxxxxxxxxxxxxxx"
Shown only once
The full key is displayed once at creation time. Store it in your secrets manager (1Password, Doppler, AWS Secrets Manager) immediately. Lost keys can be rotated but never recovered.

6Install the SDKPrivate beta

The TypeScript SDK is currently in private beta. Request access from your dashboard and we'll flip the flag on your account. If you'd rather skip the SDK, every endpoint below has an equivalent curl example you can use with any HTTP client.

bashPrivate beta
npm install @controlplane/sdk
 
# or with pnpm / yarn
pnpm add @controlplane/sdk
yarn add @controlplane/sdk

7Initialize the client

Instantiate the client once at boot and reuse it across requests. The token is read from your environment so it never ships to the browser.

lib/controlplane.ts
import { ControlPlaneClient } from '@controlplane/sdk'
 
export const cp = new ControlPlaneClient({
baseUrl: 'https://api.aaronchangai.org',
token: process.env.CONTROLPLANE_API_KEY!,
})

Or hit the REST API directly with any HTTP client:

bash
curl https://api.aaronchangai.org/api/v1/organizations \
-H "Authorization: Bearer $CONTROLPLANE_API_KEY"

8Invite a team member

The first real API call: invite a teammate to the org you created in step 4. Grab your org ID from the Console URL (console.aaronchangai.org/orgs/[orgId]).

invite.ts
// TypeScript SDK
await cp.members.invite('org_2pX9aB1cD', {
email: 'alice@acme.com',
role: 'admin',
})

Or with curl:

bash
curl -X POST https://api.aaronchangai.org/api/v1/organizations/org_2pX9aB1cD/members/invite \
-H "Authorization: Bearer $CONTROLPLANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"alice@acme.com","role":"admin"}'
Verify
Alice receives an invite email. When she accepts, she's added as an active member with the assigned role. You can verify in the Console under Members or by calling cp.members.list(orgId).

9Billing syncs automatically

With Stripe connected (step 3), subscription events are automatically routed to the right organization. Control Plane handles plan updates, seat-limit enforcement, entitlement changes, and the full audit trail. No code required.

  • Plan updates when a customer upgrades or downgrades
  • Seat limit enforcement based on subscription quantity
  • Entitlement changes on trial start, expiry, or cancellation
  • Full audit trail of every billing event

Trigger a test sync from your terminal using the Stripe CLI:

bash
# Forward live Stripe events to your local Control Plane app
stripe listen --forward-to https://api.aaronchangai.org/api/v1/webhooks/stripe/app_abc123
 
# In another tab, fire a test subscription event
stripe trigger customer.subscription.created
Tip
Watch the org's plan update in real time in the Console under Billing → Events. Each event shows the raw Stripe payload, the resolved organization, and the resulting state change.

10Embed the team management UIPrivate beta

Drop pre-built React components into your app and let customers manage their own teams without leaving your product. Components ship with zero global CSS — styling is isolated under a cp-Tailwind prefix so they can't conflict with your design system.

app/team/page.tsxPrivate beta
import {
ControlPlaneProvider,
MemberList,
BillingPanel,
} from '@controlplane/ui'
 
export default function TeamSettingsPage({ orgId }: { orgId: string }) {
return (
<ControlPlaneProvider
apiKey={process.env.NEXT_PUBLIC_CONTROLPLANE_KEY}
orgId={orgId}
>
<MemberList />
<BillingPanel />
</ControlPlaneProvider>
)
}
You're done

That's it. You're shipping.

You now have organizations, members, roles, billing sync, and embeddable UI — wired end-to-end. Pop into the Console anytime to inspect live state, or jump to the SDK reference for everything else.

Last updated 22 May 2026