Authentication
Spooled Cloud supports multiple authentication methods for different use cases: API keys for server-to-server communication, JWT tokens for user sessions, and webhook signatures for incoming events.
API Keys
Server-to-server auth
JWT Tokens
Dashboard sessions
Webhook Signatures
Incoming webhooks
Authentication Flow
The authentication flow varies based on the method used. API keys are validated against the database, while JWT tokens are verified cryptographically.
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ecfdf5', 'primaryTextColor': '#065f46', 'primaryBorderColor': '#10b981', 'lineColor': '#6b7280', 'signalColor': '#10b981'}}}%%
sequenceDiagram
participant C as Client
participant S as Spooled API
participant DB as Database
alt API Key Auth
C->>S: Request + Authorization: Bearer sk_xxx
S->>DB: Validate key
DB-->>S: Organization context
S-->>C: Response
else JWT Auth
C->>S: Request + Authorization: Bearer jwt_xxx
S->>S: Validate & decode JWT
S-->>C: Response
end API Keys
API keys are the primary authentication method for programmatic access. Each organization can have multiple API keys with different permissions.
Key Format
API keys follow a structured format for easy identification:
spooled_sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
▲ ▲ ▲
│ │ └── Random secret (32 characters)
│ └─────── Environment (live or test)
└─────────── Prefix (sk = secret key) Using API Keys
Include your API key in the Authorization header with the Bearer scheme:
# All API requests require authentication
curl -X POST https://api.spooled.cloud/api/v1/jobs \
-H "Authorization: Bearer spooled_sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{"queue": "emails", "payload": {"to": "user@example.com"}}' Creating API Keys
API keys can be created via the dashboard or the API itself (requires an existing key):
# Create a new API key
curl -X POST https://api.spooled.cloud/api/v1/api-keys \
-H "Authorization: Bearer spooled_sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Server",
"permissions": ["jobs:read", "jobs:write", "queues:read"]
}'
# Response (key shown only once!)
{
"id": "key_xxxxx",
"name": "Production Server",
"key": "spooled_sk_live_a1b2c3d4...",
"permissions": ["jobs:read", "jobs:write", "queues:read"],
"created_at": "2025-01-15T10:30:00Z"
} ⚠️ Important
API keys are shown only once when created. Store them securely immediately. If you lose a key, you must create a new one.
Key Permissions
API keys can be scoped to specific permissions:
| Permission | Description |
|---|---|
jobs:read | List and view jobs |
jobs:write | Create, update, delete jobs |
queues:read | List and view queues |
queues:write | Create, pause, resume, delete queues |
workers:read | List and view workers |
workers:write | Register and manage workers |
schedules:read | List and view schedules |
schedules:write | Create and manage schedules |
webhooks:read | List and view webhook endpoints |
webhooks:write | Create and manage webhook endpoints |
billing:read | View billing and usage |
admin | Full access (includes all above) |
Revoking Keys
# Revoke an API key
curl -X DELETE https://api.spooled.cloud/api/v1/api-keys/key_xxxxx \
-H "Authorization: Bearer spooled_sk_live_xxxxx" Key Rotation
Best practice is to rotate API keys periodically. Here's a zero-downtime rotation strategy:
- Create a new API key
- Update your applications to use the new key
- Monitor that traffic is using the new key
- Revoke the old key
JWT Tokens
JWT (JSON Web Tokens) are used for dashboard authentication and user sessions. They're issued after email-based login or SSO authentication.
Token Types
| Token | Lifetime | Use Case |
|---|---|---|
| Access Token | 15 minutes | API requests from dashboard |
| Refresh Token | 7 days | Obtaining new access tokens |
Email Login Flow
# Step 1: Request login code
curl -X POST https://api.spooled.cloud/api/v1/auth/email/start \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'
# Response
{"sent": true}
# Step 2: Verify code (sent to email)
curl -X POST https://api.spooled.cloud/api/v1/auth/email/verify \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "code": "123456"}'
# Response
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900,
"user_id": "user_xxxxx",
"email": "user@example.com",
"organizations": [{"id": "org_xxxxx", "role": "owner"}]
} Token Refresh
# Refresh access token before expiry
curl -X POST https://api.spooled.cloud/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "eyJhbGciOiJIUzI1NiIs..."}'
# Response
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 900
} Using JWT in Requests
# JWT tokens use the same Authorization header
curl -X GET https://api.spooled.cloud/api/v1/auth/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." Webhook Signatures
When receiving webhooks from external services (Stripe, GitHub), Spooled verifies the webhook signature to ensure authenticity.
Signature Verification
Spooled automatically verifies signatures using the configured secret. For custom webhooks, configure signature verification per endpoint:
# Create webhook endpoint with signature verification
curl -X POST https://api.spooled.cloud/api/v1/webhooks \
-H "Authorization: Bearer spooled_sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "My Service",
"url": "https://api.spooled.cloud/webhooks/my-service",
"signature": {
"header": "X-Signature",
"algorithm": "hmac-sha256",
"secret": "your_shared_secret"
}
}' Security Best Practices
API Key Security
- Never expose keys in client-side code — Use a backend proxy
- Use environment variables —
SPOOLED_API_KEY - Avoid committing to git — Add to
.gitignore - Use least privilege — Only grant needed permissions
- Rotate regularly — At least quarterly for production
- Monitor usage — Set up alerts for unusual activity
Environment Variables
# .env (add to .gitignore)
SPOOLED_API_KEY=spooled_sk_live_xxxxx
# Use in code (Node.js example)
const client = new SpooledClient({
apiKey: process.env.SPOOLED_API_KEY,
}); Secret Managers
For production, consider using a secret manager:
- AWS Secrets Manager
- Google Secret Manager
- HashiCorp Vault
- Doppler
Error Codes
| Code | HTTP Status | Description |
|---|---|---|
unauthorized | 401 | Missing or invalid API key/token |
forbidden | 403 | Valid auth but insufficient permissions |
token_expired | 401 | JWT token has expired (refresh required) |
invalid_signature | 401 | Webhook signature verification failed |