Authentication
How to authenticate with the Astrocal API using API keys.
Astrocal uses API key authentication. Every request to an authenticated endpoint must include a Bearer token in the Authorization header.
API Keys
API keys are scoped to an organization and come in two modes:
- Live keys (
ac_live_...): Affect real data, create real bookings and calendar events. - Test keys (
ac_test_...): Isolated sandbox data. See Sandbox Mode.
Creating an API Key
The easiest way to create your first API key is from the dashboard. Go to Settings → API Keys and click Create Key.
Once you have a key, you can also create additional keys via the API:
curl -X POST https://api.astrocal.dev/v1/api-keys \
-H "Authorization: Bearer ac_live_..." \
-H "Content-Type: application/json" \
-d '{"name": "My Integration", "mode": "live"}'const response = await fetch("https://api.astrocal.dev/v1/api-keys", {
method: "POST",
headers: {
Authorization: "Bearer ac_live_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ name: "My Integration", mode: "live" }),
});
const data = await response.json();Try it in the API playground →
The full key is returned only once in the response. Store it securely.
Using an API Key
Include it as a Bearer token:
curl https://api.astrocal.dev/v1/event-types \
-H "Authorization: Bearer ac_live_..."const response = await fetch("https://api.astrocal.dev/v1/event-types", {
headers: {
Authorization: "Bearer ac_live_...",
},
});
const data = await response.json();Try it in the API playground →
Key Management
| Endpoint | Method | Description |
|---|---|---|
POST /v1/api-keys | POST | Create a new API key |
GET /v1/api-keys | GET | List all API keys |
DELETE /v1/api-keys/{id} | DELETE | Revoke an API key |
Revoked keys immediately fail authentication. Revocation is idempotent.
Public Endpoints
Some endpoints don't require authentication:
GET /health: Health checkPOST /v1/bookings: Create a booking (public booking page)POST /v1/bookings/{id}/cancel: Cancel with?token=(invitee self-service)POST /v1/bookings/{id}/reschedule: Reschedule with?token=(invitee self-service)GET /v1/availability: Check available slotsGET /v1/event-types/{id}: Public event type detail (active, non-test only)GET /v1/openapi.json: OpenAPI specification
Authenticated Endpoints
All other endpoints require an API key:
GET/POST/PATCH/DELETE /v1/event-types: Manage event typesPUT/GET /v1/event-types/{id}/availability: Manage availability rulesPOST/GET/DELETE /v1/event-types/{id}/hosts: Manage round-robin hostsGET /v1/bookings: List bookingsGET /v1/bookings/{id}: Get booking detailsGET/DELETE /v1/calendars: Calendar connectionsGET/POST/PATCH/DELETE /v1/webhooks: Webhook managementGET /v1/webhooks/{id}/deliveries: Webhook delivery historyPOST /v1/webhooks/{id}/deliveries/{delivery_id}/retry: Retry a deliveryGET/POST/DELETE /v1/api-keys: API key managementGET /v1/usage: Usage and rate limitsGET /v1/activity: Activity log
Service Key Auth (BFF Pattern)
Internal use only. This section documents the dashboard's server-to-server authentication. If you're integrating via API keys, you can skip this.
If you're building a backend-for-frontend that talks to the Astrocal API on behalf of users, you can authenticate with a service key instead of an API key. This bypasses API key lookup and lets you act on behalf of any organization.
curl https://api.astrocal.dev/v1/event-types \
-H "Authorization: Bearer $ASTROCAL_SERVICE_KEY" \
-H "X-Org-Id: org_uuid_here" \
-H "X-Astrocal-Mode: live"const response = await fetch("https://api.astrocal.dev/v1/event-types", {
headers: {
Authorization: "Bearer $ASTROCAL_SERVICE_KEY",
"X-Org-Id": "org_uuid_here",
"X-Astrocal-Mode": "live",
},
});
const data = await response.json();| Header | Required | Description |
|---|---|---|
Authorization: Bearer <service_key> | Yes | The service key from ASTROCAL_SERVICE_KEY |
X-Org-Id | Yes | The organization UUID to act on behalf of |
X-Astrocal-Mode | No | live (default) or test - controls sandbox isolation |
Service keys are for server-to-server use only. Never expose them to the browser.
Error Responses
Missing or invalid authentication returns a 401 error:
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid Authorization header"
}
}Rate Limits
API keys are subject to rate limits based on your subscription plan. See Rate Limits for details.