C
Chatty

Authentication

API keys

All Chatty API requests require a Bearer API key in the Authorization header:

Authorization: Bearer chatty_sk_<your-key>

Keys are created per bot in Dashboard → Settings → API Keys. A bot can have multiple keys — create separate ones for different environments and revoke them independently.

API keys are shown once at creation and cannot be retrieved again. Store them in environment variables, never in source code.

Scopes

Every key carries one or more scopes controlling which endpoints it can call. Assign the minimum scopes needed.

ScopeEndpoints
chatPOST /api/v1/chat
readGET leads, conversations, knowledge, analytics, usage, bot details
writePOST/DELETE knowledge, DELETE conversations
adminAll of the above
📌

Embed integration

Needs only chat. Visitors send messages but can't read your data.
🔗

CRM sync

Needs read to pull leads and conversations.
📄

Content pipeline

Needs write to add/remove knowledge sources.
📊

Internal dashboard

Use admin for full access.

IP allowlist

Restrict a key to specific IPs or CIDR ranges. Requests from any other IP return 403.

["203.0.113.42", "10.0.0.0/8", "2001:db8::/32"]

Leave the allowlist empty to allow requests from any IP. The embed widget uses a separate mechanism and is not affected.

Key management

MethodEndpointDescription
POST/api/keysCreate a new key
GET/api/keys?bot_id=...List all keys for a bot
PATCH/api/keys/{id}Update name, scopes, allowlist
DELETE/api/keys/{id}Revoke permanently

These require a Supabase session token (dashboard login), not an API key.

OAuth2 (multi-account access)

An API key is scoped to exactly one bot — it can't create new bots or list every bot on your account. For that, authenticate as your Chatty account instead, via OAuth2. This is what powers the Developer API's bot-management endpoints and the MCP server, and is the right choice for building an integration or connecting an AI agent rather than embedding a single widget.

If you're connecting an MCP client (Claude Desktop, etc.), you don't need to read this section — MCP clients discover and register themselves automatically. This is for building your own OAuth2 integration.

Chatty implements the standard authorization-code grant with mandatory PKCE (S256) — the same flow GitHub, Google, and most modern APIs use:

  1. Register your app — POST https://api.chatty.personaliai.com/oauth/register with {"client_name": "...", "redirect_uris": ["https://yourapp.com/callback"]}. Returns a client_id (and a client_secret if you asked for a confidential client via "token_endpoint_auth_method": "client_secret_post" — omit it for a public/PKCE-only client, e.g. a CLI tool or desktop app).
  2. Send the user to approve access — redirect their browser to /oauth/authorize with client_id, redirect_uri, scope, a PKCE code_challenge (S256), and a state value you'll verify on return.
  3. Exchange the code — after approval, your redirect_uri receives ?code=...&state=.... POST /oauth/token (form-encoded, not JSON) with grant_type=authorization_code, the code, your code_verifier, and redirect_uri to get an access token (1 hour) and refresh token (30 days).
  4. Use the token — same as an API key: Authorization: Bearer chatty_oat_... on any /api/v1/* request.
Token exchange
curl -X POST https://api.chatty.personaliai.com/oauth/token \
  -d grant_type=authorization_code \
  -d code=THE_CODE_FROM_STEP_3 \
  -d redirect_uri=https://yourapp.com/callback \
  -d client_id=YOUR_CLIENT_ID \
  -d code_verifier=YOUR_PKCE_VERIFIER
The token endpoint requires application/x-www-form-urlencoded (RFC 6749), not JSON — this is what makes off-the-shelf OAuth2 client libraries work against it without modification.

Discovery metadata (for OAuth2/MCP client libraries that auto-configure themselves) is served at /.well-known/oauth-authorization-server.

Security headers

Every response includes:

HeaderValue
X-Request-IDUnique UUID per request — include in bug reports
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
Strict-Transport-Securitymax-age=31536000; includeSubDomains; preload
Content-Security-Policydefault-src 'none'