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 issued per deployment. Grants access to the /api/v1 endpoints: starting runs, reading status, minting participant tokens. Never expose it 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. |
| Public (none) | Anonymous visitors. Survey-mode deployments expose a rate-limited public endpoint that creates anonymous runs and returns a participant token, with no credentials at all. |
API keys
An API key is generated when you deploy a workflow. It is shown once in the deployment dialog — store it in a secrets manager. Keys are prefixed with cf_ and only a prefix is kept visible in the dashboard afterwards.
Pass the key in the Authorization header as a bearer token on every /api/v1 request:
POST https://your-chatterfly.example.com/api/v1/runs
Authorization: Bearer cf_your_api_key_here
Content-Type: application/json
{ "input": { "name": "Alice" } }Because the key is bound to a deployment, it implicitly identifies both your tenant and the workflow version to run — there is no separate workflow ID to pass.
API requests are rate-limited per tenant (per-minute budget). When you exceed it, requests return 429 Too Many Requests — back off and retry.
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
Deployments with survey_mode enabled expose an unauthenticated, rate-limited endpoint that does the run-creation and token-minting dance in one step:
POST /api/public/surveys/dep_abc123/start{
"run_id": "run_xyz789",
"participant_token": "eyJhbGciOiJIUzI1NiIs..."
}This is what powers the serverless embed and hosted survey pages. It only works for survey-mode 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.
