Authentication
JWT-based authentication, securing your requests, and rate limits.
Overview
The Foil Engine API uses JWT Bearer tokens issued by Supabase for authentication. Some endpoints require authentication (creating, saving, deleting personas), while others are publicly accessible (browsing public personas, chatting with published characters).
Authorization header of every authenticated request.Authentication Header
Include your JWT token as a Bearer token in the Authorization header:
Authorization: Bearer <your_jwt_token>Requests to protected endpoints without a valid token will return a 401 Unauthorized response.
Auth Endpoints
GET /api/v1/auth/me
Returns the currently authenticated user. Requires auth.
| Field | Type | Description |
|---|---|---|
id | string | Unique user ID (UUID) |
email | string | User's email address |
display_name | string | User's display name |
Example request:
curl /api/v1/auth/me \
-H "Authorization: Bearer <your_jwt_token>"Example response:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "developer@example.com",
"display_name": "Dev User"
}POST /api/v1/auth/migrate-progress
Migrates anonymous play progress to the authenticated user's account. Call this after a user signs in to preserve any chat history or scores accumulated before authentication. Requires auth.
Example request:
curl -X POST /api/v1/auth/migrate-progress \
-H "Authorization: Bearer <your_jwt_token>"Game SDK Authentication
For game integrations, the Game SDK uses API key authentication instead of JWT tokens. Include your key in the X-API-Key header:
X-API-Key: pk_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6API keys are scoped to your account and can only access your own published personas. Create and manage keys from the API Keys dashboard or via the POST /api/v1/sdk/api-keys endpoint (requires JWT auth).
Which Endpoints Require Auth?
| Action | Auth Required |
|---|---|
| Browse public personas | No |
| Chat with published personas (web) | No |
| Chat via Game SDK | API Key |
| List your own personas | JWT |
| Create / save a persona | JWT |
| Publish a persona | JWT |
| Delete a persona | JWT |
| Manage API keys | JWT |
Rate Limits
Rate limits are applied per IP address. When a limit is exceeded, the API returns a 429 Too Many Requests response with a Retry-After header indicating seconds until the next request can be made.
| Category | Limit | Scope |
|---|---|---|
| Generation (AI content creation) | 10 requests / minute | Per IP |
| Chat (sending messages) | 60 requests / minute | Per IP |
| General (all other endpoints) | 120 requests / minute | Per IP |
| SDK Chat (sending messages) | 30 requests / minute | Per API key |
| SDK General (init, history, reset) | 60 requests / minute | Per API key |
Example rate-limited response:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
{
"error": "Rate limit exceeded. Try again in 12 seconds."
}