Skip to content

Authentication

Chalk uses two authentication mechanisms:

  1. API Keys — For tenant-level API access (X-API-Key header)
  2. JWT Tokens — For participant-level authentication in rooms

API Key Authentication

All tenant API endpoints require the X-API-Key header:

Terminal window
curl -X GET https://api.chalk.dev/api/v1/tenants/tenant_abc123 \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

API keys are issued when creating a tenant and can be rotated via the Rotate API Key endpoint.

Exchange API Key for Tokens

POST /api/v1/auth/token

Exchange an API key for JWT access and refresh tokens.

Request

{
"api_key": "sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response

{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600
}
}
FieldTypeDescription
access_tokenstringJWT for authenticating requests
refresh_tokenstringToken for obtaining new access tokens
token_typestringAlways “Bearer”
expires_inintAccess token lifetime in seconds

Refresh Tokens

POST /api/v1/auth/refresh

Obtain new tokens using a refresh token.

Request

{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}

Response

{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600
}
}

Using JWT Tokens

Include the access token in the Authorization header:

Terminal window
curl -X GET https://api.chalk.dev/api/v1/rooms/room_abc123 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Token Lifecycle

┌─────────────────┐
│ API Key │
│ (long-lived) │
└────────┬────────┘
│ POST /auth/token
┌─────────────────┐
│ Access Token │◄────────┐
│ (short-lived) │ │
└────────┬────────┘ │
│ expires │ POST /auth/refresh
▼ │
┌─────────────────┐ │
│ Refresh Token │─────────┘
│ (longer-lived) │
└─────────────────┘

Error Responses

Invalid API Key

{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}

Expired Token

{
"error": {
"code": "TOKEN_EXPIRED",
"message": "Access token has expired"
}
}

Invalid Refresh Token

{
"error": {
"code": "INVALID_REFRESH_TOKEN",
"message": "Refresh token is invalid or expired"
}
}