Skip to content
cronpad
API reference / Workspace API

Workspace API

Everything in a workspace that isn’t a job or a run: API keys, secrets, alerting, statistics and the audit log, plus the server’s health endpoints.

Identity and workspace

GET /api/v1/me returns the user and accessible workspaces. GET /api/v1/workspaces/{ws} returns id, name, slug, plan and created_at; PATCH accepts name and slug. The workspace must match the authenticated workspace; other IDs return 404.

API keys

EndpointDescription
GET /api/v1/api-keysList keys: id, name, prefix (e.g. cp_ab12cd34), scopes, created_at, last_used_at, revoked_at
POST /api/v1/api-keysCreate: {"name": "ci", "scopes": ["jobs:read","runs:read"]}. Response includes the full key once.
DELETE /api/v1/api-keys/{id}Revoke. Takes effect immediately.

Secrets

EndpointDescription
GET /api/v1/secretsList names with created_at/updated_at. Values are never returned.
PUT /api/v1/secrets/{name}Create or replace: {"value": "…"}
DELETE /api/v1/secrets/{name}Delete

See Secrets.

Alert channels

EndpointDescription
GET /api/v1/alert-channelsList
POST /api/v1/alert-channelsCreate. Email channels start unverified. Webhook channels return a signing_secret once.
GET /api/v1/alert-channels/{id}Read one channel
GET /api/v1/alert-channels/verify?token=…Verify an address using its signed email link (no login required)
POST /api/v1/alert-channels/{id}/verifyResend confirmation links
PATCH /api/v1/alert-channels/{id}Update
DELETE /api/v1/alert-channels/{id}Delete (rules referencing it stop sending to it)
POST /api/v1/alert-channels/{id}/testSend a test alert

See Alert channels.

Alert rules

EndpointDescription
GET /api/v1/alert-rulesList
POST /api/v1/alert-rulesCreate
GET /api/v1/alert-rules/{id}Read one rule
PATCH /api/v1/alert-rules/{id}Update
DELETE /api/v1/alert-rules/{id}Delete

See Alert rules.

Stats

GET /api/v1/stats/overview?window=24h (1h, 24h, 7d, 30d):

{
  "window": "24h",
  "jobs": {"active": 42, "paused": 3, "disabled": 1, "completed": 7},
  "runs": {"total": 18240, "succeeded": 18190, "failed": 50, "sla_breached": 4},
  "start_lag_ms": {"p50": 3, "p95": 9, "p99": 41},
  "failing_jobs": [{"id": "job_01J9…", "name": "crm-sync", "consecutive_failures": 6}]
}

Audit log

GET /api/v1/audit-log?action=job.pause&limit=50. Each entry has actor (user:…, key:… or system), action (e.g. job.create, job.update, job.pause, job.auto_disable, api_key.create, secret.update), target, details and created_at. Entries are kept for 30 days by default.

Health (no authentication, outside /api/v1)

EndpointReturns
GET /healthz200 while the process is running. Use for liveness probes.
GET /readyz200 when both databases are writable, the queue file responds, the dispatcher is active and result writing is keeping up; 503 otherwise, with a JSON breakdown. Use for readiness probes and uptime checks.
GET /version{"version": "1.0.0", "commit": "…", "build_date": "…", "edition": "oss"}
{"dispatcher": "active", "queue": true, "heartbeat": "2026-10-18T09:30:00Z", "writer_backpressure": false, "sqlite_writable": true}

dispatcher is one of starting, active, standby (another process holds the dispatcher lock) or stopped. queue is false when the queue file can’t be read, sqlite_writable covers both databases, and heartbeat is the dispatcher’s last tick.

Usage and suspension

GET /api/v1/usage returns the workspace’s UTC calendar-month run usage and effective limit:

{"month":"2026-10","runs":1200,"limit":50000,"over_quota_policy":"block","reset_at":"2026-11-01T00:00:00Z"}

limit is 0 for unlimited. over_quota_policy is block or allow. reset_at is the start of the next UTC month. At a blocking cap, manual job triggers return 429 with error.code: "limit_exceeded" and limit: "max_runs_per_month_per_workspace".

Suspended workspaces retain read access. Mutations return 403 with error.code: "workspace_suspended"; operators restore access with the cronpad workspace unsuspend <slug> command. Skipped runs carry a skip_reason (quota_exceeded, workspace_suspended, previous_run_in_progress or misfire) separate from delivery errors in last_error.