Authentication & API Keys
Chatterfly uses different credentials for different audiences: API keys for your servers, participant tokens for end users in the browser, and unauthenticated public endpoints for survey-mode deployments. This page explains each and when to use which.
Overview
| Credential | Who uses it & where |
|---|---|
| API key | Your backend servers. Long-lived secret. Grants access to the /api/v1 endpoints: starting runs, reading status, minting participant tokens. Two kinds: a stable cfw_ workflow key (survives redeploys — recommended) or a cf_ per-deployment key. Never expose either in the browser. |
| Participant token | End users in browsers or apps. Short-lived JWT (1 hour) scoped to a single run and role. Safe to pass to the client — it can only interact with that one run. |
| Personal access token | You, via the CLI or MCP. A long-livedcfpat_ token minted in Settings → API tokens, bound to one workspace, that authenticates the management API as you. |
| Public (none) | Anonymous visitors. Public deployments expose a rate-limited endpoint that creates anonymous runs and returns a participant token, with no credentials at all. |
API keys
There are two kinds of API key, both passed as Authorization: Bearer <key> on /api/v1 requests:
| Key | Behaviour |
|---|---|
| cfw_ workflow key | Recommended. Minted from the Ship tab, scoped to a workflow, and survives redeploys. Runs resolve to the workflow's latest active deployment automatically, so your backend never changes when you redeploy. |
| cf_ deployment key | Generated when you deploy, bound to that specific deployment snapshot, and revoked on the next redeploy. Use when you deliberately want to pin one snapshot. |
Each key is shown once when created — store it in a secrets manager. Only a prefix is kept visible in the dashboard afterwards.
POST https://your-chatterfly.example.com/api/v1/runs
Authorization: Bearer cfw_your_workflow_key_here
Content-Type: application/json
{ "input": { "name": "Alice" } }A cfw_ key identifies your tenant and workflow; the run targets the latest deployment. Add "deployment_id" to the body only to pin a specific snapshot. A cf_ key already fixes the deployment, so no workflow ID is needed.
API requests are rate-limited per tenant (per-minute budget). When you exceed it, requests return 429 Too Many Requests — back off and retry.
Personal access tokens
A personal access token (cfpat_…) authenticates the CLI and the MCP server against the management API as you. Unlike run keys, it never works on the /api/v1 run surface — it is strictly a management credential.
Create one in the dashboard under Settings → API tokens. Each token is bound to the workspace it was created in, carries your permissions, and is shown only once — store it in a secrets manager. Pick an expiry (default 180 days) or no expiry, and revoke anytime.
chatterfly login --token cfpat_your_token_here
# Or as an environment variable (CLI or MCP):
export CHATTERFLY_TOKEN="cfpat_your_token_here"Participant tokens
Participant tokens let external users — customers, reviewers, survey respondents — join a run without a Chatterfly account. They are JWTs that expire after 1 hour and are scoped to exactly one run and one role.
Mint one server-side using your API key:
POST /api/v1/runs/run_xyz789/tokens
Authorization: Bearer cf_your_api_key_here
Content-Type: application/json
{ "role": "customer" }Response:
{ "participant_token": "eyJhbGciOiJIUzI1NiIs..." }Hand the token to your frontend (embed it in the page, or return it from your own API) and pass it to the widget together with the run ID. The widget uses it for the participant WebSocket and all /api/participant calls.
role must match a participant role declared in the workflow (e.g. customer). You can mint a token before the run has started executing — it is bound to the run ID and role and resolves to the concrete participant when the run reaches them.Public endpoints
Workflows deployed with Public access expose an unauthenticated, rate-limited endpoint that does the run-creation and token-minting dance in one step. Prefer the workflow-scoped form — it resolves to the latest live deployment:
POST /api/public/workflows/wf_abc123/start # recommended (latest deployment)
POST /api/public/surveys/dep_abc123/start # pins a specific deployment{
"run_id": "run_xyz789",
"participant_token": "eyJhbGciOiJIUzI1NiIs...",
"deployment_id": "dep_abc123"
}This is what powers the serverless embed and hosted survey pages. It only resolves Public deployments and only creates anonymous runs, so it is safe to call from any browser.
Best practices
- Store API keys in environment variables or a secrets manager — never in code.
- Mint participant tokens on demand, right before rendering the widget. Don't cache them — they expire after an hour.
- Use one deployment (and therefore one key) per environment: separate keys for staging and production.
- Prefer the serverless / public path for anonymous use cases — less surface area than handling keys yourself.
