Files
calendar/agents/skills/calcom-api/references/authentication.md
T
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>Claude Haiku 4.5Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
12abc316e6 refactor: consolidate agent config into agents directory (#27427)
* refactor: consolidate agent config folders into agents directory

- Move .claude/skills and .claude/rules content to agents/
- Remove duplicate .cursor/ and .goose/ folders
- Create symlinks from .claude/ and .cursor/ to agents/
- Convert review.mdc to quality-review-checklist.md with proper frontmatter

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* feat: add Cal.com APIv2 skills to agents directory

Move the Cal.com API v2 skills from PR #27445 into the consolidated
agents/skills/ directory structure. This includes:
- SKILL.md - Main skill file with API overview
- references/authentication.md - Authentication methods
- references/bookings.md - Bookings API reference
- references/calendars.md - Calendars API reference
- references/event-types.md - Event types API reference
- references/schedules.md - Schedules API reference
- references/slots-availability.md - Slots and availability API reference
- references/webhooks.md - Webhooks API reference

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* fix: update calcom-api skill to use Claude Code frontmatter format

Remove non-standard frontmatter fields (license, metadata) and keep only
the Claude Code supported fields (name, description) as per the
Claude Code skills specification.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* refactor: restructure calcom-api SKILL.md as index file

Convert SKILL.md from a comprehensive API doc (317 lines) to a concise
index file (108 lines) that references the detailed documentation in
the references/ folder. This follows the Claude Code skills pattern of
keeping SKILL.md focused with supporting files for detailed content.

The SKILL.md now:
- Provides a quick start guide with essential examples
- References all 7 detailed reference docs in a table
- Lists common workflows and best practices
- Points to external resources

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* docs: preserve deleted content in reference files

Move content that was removed from SKILL.md to appropriate reference files:
- Add Error Handling and Pagination sections to authentication.md
- Add Organization endpoints to event-types.md
- Add Core Concepts section back to SKILL.md

This ensures no useful API documentation is lost during the restructuring.

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-02-03 14:14:41 +01:00

407 lines
9.0 KiB
Markdown

# Authentication API Reference
Detailed documentation for authentication methods in the Cal.com API v2.
## Authentication Methods
Cal.com API v2 supports two authentication methods:
1. **API Key Authentication** - For direct API access
2. **OAuth/Platform Authentication** - For platform integrations managing users on behalf of others
## API Key Authentication
The primary authentication method for most API consumers.
### Obtaining an API Key
1. Log in to your Cal.com account
2. Navigate to Settings > Developer > API Keys
3. Click "Create new API key"
4. Copy and securely store the generated key
### Using API Keys
Include the API key in the `Authorization` header with the `Bearer` prefix:
```http
GET /v2/bookings
Authorization: Bearer cal_live_abc123xyz...
```
### API Key Format
All Cal.com API keys are prefixed with `cal_`:
- `cal_live_...` - Production API keys
- `cal_test_...` - Test/sandbox API keys (if available)
### Example Request
```bash
curl -X GET "https://api.cal.com/v2/bookings" \
-H "Authorization: Bearer cal_live_abc123xyz789" \
-H "Content-Type: application/json"
```
## Refresh API Key
Generate a new API key and invalidate the current one:
```http
POST /v2/api-keys/refresh
Authorization: Bearer cal_live_current_key
Content-Type: application/json
{
"expiresAt": "2025-12-31T23:59:59Z"
}
```
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| expiresAt | string | No | ISO 8601 expiration date for the new key |
### Response
```json
{
"status": "success",
"data": {
"apiKey": "cal_live_new_key_xyz..."
}
}
```
## Platform Authentication (OAuth)
For platform customers building integrations that manage multiple users.
### Headers for Platform Authentication
Platform customers use additional headers alongside or instead of the Bearer token:
| Header | Description |
|--------|-------------|
| `x-cal-client-id` | OAuth client ID |
| `x-cal-secret-key` | OAuth client secret key |
| `Authorization` | Bearer token (managed user access token) |
### Example Platform Request
```bash
curl -X GET "https://api.cal.com/v2/bookings" \
-H "x-cal-client-id: your_client_id" \
-H "x-cal-secret-key: your_secret_key" \
-H "Authorization: Bearer managed_user_access_token" \
-H "Content-Type: application/json"
```
### When to Use Each Header
**For endpoints acting on behalf of a managed user:**
```http
GET /v2/bookings
x-cal-client-id: your_client_id
x-cal-secret-key: your_secret_key
Authorization: Bearer managed_user_access_token
```
**For platform-level operations (managing OAuth clients):**
```http
GET /v2/oauth-clients
Authorization: Bearer cal_live_platform_admin_key
```
## API Versioning
Many endpoints require a version header:
```http
cal-api-version: 2024-08-13
```
### Example with Version Header
```bash
curl -X POST "https://api.cal.com/v2/bookings" \
-H "Authorization: Bearer cal_live_abc123" \
-H "cal-api-version: 2024-08-13" \
-H "Content-Type: application/json" \
-d '{"start": "2024-01-15T10:00:00Z", "eventTypeId": 123, ...}'
```
## Authentication Errors
### 401 Unauthorized
Returned when authentication fails:
```json
{
"status": "error",
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}
```
Common causes:
- Missing `Authorization` header
- Invalid or expired API key
- API key without `cal_` prefix
- Incorrect Bearer token format
### 403 Forbidden
Returned when authenticated but lacking permissions:
```json
{
"status": "error",
"error": {
"code": "FORBIDDEN",
"message": "You do not have permission to access this resource"
}
}
```
Common causes:
- Accessing another user's resources
- Missing required scopes for platform tokens
- Organization/team permission restrictions
## Security Best Practices
1. **Never expose API keys in client-side code**: API keys should only be used in server-side applications
2. **Use environment variables**: Store API keys in environment variables, not in code
```bash
export CAL_API_KEY="cal_live_abc123..."
```
3. **Rotate keys regularly**: Use the refresh endpoint to rotate keys periodically
4. **Use minimal permissions**: Request only the scopes/permissions your application needs
5. **Monitor API usage**: Check your Cal.com dashboard for unusual activity
6. **Secure transmission**: Always use HTTPS for API requests
7. **Handle keys securely in logs**: Never log full API keys - redact sensitive portions
## Rate Limiting
API requests are rate limited. When exceeded, you'll receive:
```http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
```
```json
{
"status": "error",
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Please retry after 60 seconds."
}
}
```
### Rate Limit Headers
| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit` | Maximum requests per window |
| `X-RateLimit-Remaining` | Remaining requests in current window |
| `X-RateLimit-Reset` | Unix timestamp when the window resets |
| `Retry-After` | Seconds to wait before retrying (on 429) |
## Testing Authentication
Verify your API key is working:
```bash
curl -X GET "https://api.cal.com/v2/me" \
-H "Authorization: Bearer cal_live_your_api_key" \
-H "Content-Type: application/json"
```
### Expected Response
```json
{
"status": "success",
"data": {
"id": 12345,
"email": "user@example.com",
"username": "johndoe",
"name": "John Doe",
"timeZone": "America/New_York"
}
}
```
## Common Authentication Patterns
### Server-Side Integration
```javascript
const CAL_API_KEY = process.env.CAL_API_KEY;
async function getBookings() {
const response = await fetch('https://api.cal.com/v2/bookings', {
headers: {
'Authorization': `Bearer ${CAL_API_KEY}`,
'Content-Type': 'application/json',
'cal-api-version': '2024-08-13'
}
});
if (!response.ok) {
if (response.status === 401) {
throw new Error('Invalid API key');
}
throw new Error(`API error: ${response.status}`);
}
return response.json();
}
```
### Handling Token Refresh
```javascript
async function makeAuthenticatedRequest(url, options = {}) {
let response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${apiKey}`
}
});
if (response.status === 401) {
// Refresh the API key
const refreshResponse = await fetch('https://api.cal.com/v2/api-keys/refresh', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({})
});
if (refreshResponse.ok) {
const { data } = await refreshResponse.json();
apiKey = data.apiKey;
// Retry original request with new key
response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${apiKey}`
}
});
}
}
return response;
}
```
## Error Handling
The API returns standard HTTP status codes:
| Status Code | Description |
|-------------|-------------|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request (invalid parameters) |
| 401 | Unauthorized (invalid or missing API key) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found |
| 422 | Unprocessable Entity (validation error) |
| 429 | Too Many Requests (rate limited) |
| 500 | Internal Server Error |
### Error Response Format
```json
{
"status": "error",
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message"
}
}
```
### Common Error Codes
| Code | Description |
|------|-------------|
| UNAUTHORIZED | Invalid or missing authentication |
| FORBIDDEN | Insufficient permissions |
| NOT_FOUND | Resource not found |
| VALIDATION_ERROR | Invalid request parameters |
| RATE_LIMITED | Too many requests |
## Pagination
List endpoints support pagination via `take` and `skip` parameters:
| Parameter | Type | Default | Max | Description |
|-----------|------|---------|-----|-------------|
| take | number | 10 | 250 | Number of items to return |
| skip | number | 0 | - | Number of items to skip |
### Example
```http
GET /v2/bookings?take=20&skip=40
```
This returns items 41-60 (skipping the first 40, taking 20).
### Pagination Response
Some endpoints include pagination metadata:
```json
{
"status": "success",
"data": [...],
"pagination": {
"total": 150,
"take": 20,
"skip": 40
}
}
```
## Troubleshooting
### "Invalid API key" Error
1. Verify the key starts with `cal_`
2. Check for extra whitespace or characters
3. Ensure the key hasn't been revoked or expired
4. Confirm you're using the correct environment (production vs test)
### "Missing Authorization header" Error
1. Ensure the header name is exactly `Authorization`
2. Include the `Bearer ` prefix (with space)
3. Check for typos in the header name
### Platform Authentication Issues
1. Verify both `x-cal-client-id` and `x-cal-secret-key` are provided
2. Ensure the managed user access token is valid
3. Check that the OAuth client has the required permissions