Skip to content

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:readList and view jobs
jobs:writeCreate, update, delete jobs
queues:readList and view queues
queues:writeCreate, pause, resume, delete queues
workers:readList and view workers
workers:writeRegister and manage workers
schedules:readList and view schedules
schedules:writeCreate and manage schedules
webhooks:readList and view webhook endpoints
webhooks:writeCreate and manage webhook endpoints
billing:readView billing and usage
adminFull 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:

  1. Create a new API key
  2. Update your applications to use the new key
  3. Monitor that traffic is using the new key
  4. 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 Token15 minutesAPI requests from dashboard
Refresh Token7 daysObtaining 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 variablesSPOOLED_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
unauthorized401Missing or invalid API key/token
forbidden403Valid auth but insufficient permissions
token_expired401JWT token has expired (refresh required)
invalid_signature401Webhook signature verification failed