API reference
The SimpleQ REST API: publish jobs, manage queues, and operate the dead-letter queue. You publish a job over HTTP; SimpleQ queues it, applies retries and rate limits, and delivers it to your webhook. Every endpoint, request body, and status code is listed below.
- Base URL:
https://api.simpleq.io - Auth: send
Authorization: Bearer sq_live_...on every request. Create and revoke keys from the dashboard. All durations are in seconds.
Try it in your browser → Interactive API explorer — send live requests against the API.
Machine-readable spec: openapi.json — import it to generate a client.
Client libraries: TypeScript —
@simpleq/sdk(npm install @simpleq/sdk) · GitHub · npm.
Changing a setting on an existing queue? See Editing a queue for when each change takes effect.
Jobs
Publish jobs, check status, and retry failures.
POST /v1/queues/{queueName}/jobs
Publish a job Queues a job for delivery to the queue’s webhook. If idempotencyKey matches a previously published job, returns the existing job (200) instead of creating a duplicate.
Parameters:
queueName(path) (required): string — The queue name (URL-safe)
Request body:
payload: object (required) — Arbitrary JSON object delivered as-is to your webhook. SimpleQ does not inspect or validate the contents.idempotencyKey: string — Optional key for deduplication. Publishing twice with the same key returns the original job instead of creating a duplicate.delay: number — Delay delivery by this many seconds (max 86400 = 24h). Decimals allowed.
Responses:
- 200: Idempotent hit — existing job returned
- 201: Job created
- 400: Validation error
- 402: Free-plan monthly attempt limit reached — publishing resumes next cycle or after upgrading. Never sent to paid plans.
- 404: Queue not found
GET /v1/jobs/{id}
Get job status
Parameters:
id(path) (required): string — Job ID
Responses:
- 200: Job document
- 404: Job not found
Queues
Create queues and manage their config.
GET /v1/queues
List queues
Responses:
- 200: Array of queues (signingSecret omitted)
POST /v1/queues
Create a queue Creates a queue and generates a signingSecret (returned once on creation). Supports named templates that prefill defaults: anthropic, openai. Explicit fields override template values.
Request body:
name: string (required)webhookUrl: string (required)maxAttempts: integermaxDefers: integerconcurrency: integerdlqEnabled: booleanmode: string (standard | ack)rateLimitMax: integer | nullrateLimitWindow: numberackTimeout: numberackTimeoutAction: string (retry | dead)backoffType: string (fixed | exponential)backoffDelay: numbertemplate: string (anthropic | openai) — Optional. Prefills queue defaults from a named template. Explicit fields override the template values.
Responses:
- 201: Queue created (signingSecret included)
- 400: Validation error
- 403: Plan limit exceeded (maxAttempts/maxDefers ceiling or queue count cap)
GET /v1/queues/{id}
Get a queue
Parameters:
id(path) (required): string — Queue ID
Responses:
- 200: Queue (signingSecret omitted)
- 404: Queue not found
PUT /v1/queues/{id}
Update queue config Partial update. name cannot be changed after creation.
Parameters:
id(path) (required): string — Queue ID
Request body:
webhookUrl: stringmaxAttempts: integermaxDefers: integerconcurrency: integerdlqEnabled: booleanmode: string (standard | ack)rateLimitMax: integer | nullrateLimitWindow: numberackTimeout: numberackTimeoutAction: string (retry | dead)backoffType: string (fixed | exponential)backoffDelay: number
Responses:
- 200: Updated queue (signingSecret omitted — it is returned only on creation)
- 400: Validation error
- 403: Plan limit exceeded (maxAttempts/maxDefers ceiling)
- 404: Queue not found
DELETE /v1/queues/{id}
Delete a queue Deletes a queue. The queue stops accepting new jobs and the name becomes available to re-use immediately. Existing jobs remain retrievable by job ID for inspection.
Parameters:
id(path) (required): string — Queue ID
Responses:
- 204: Queue deleted
- 404: Queue not found
GET /v1/queues/{id}/jobs
List jobs in a queue
Parameters:
id(path) (required): string — Queue IDpage(query): integer [default 1, min 1]limit(query): integer [default 25, min 1, max 100]status(query): string (pending | processing | awaiting_ack | completed | dead)
Responses:
- 200: Paginated jobs
- 404: Queue not found
DLQ
Inspect and retry dead-lettered jobs.
GET /v1/queues/{id}/dlq
List dead-letter jobs
Parameters:
id(path) (required): string — Queue IDpage(query): integer [default 1, min 1]limit(query): integer [default 25, min 1, max 100]includeReplayed(query): boolean | null
Responses:
- 200: Paginated DLQ entries
- 404: Queue not found
- 410: Queue has been deleted; its dead-letter jobs are gone
POST /v1/queues/{id}/dlq/{jobId}/replay
Replay a dead-lettered job
Parameters:
id(path) (required): string — Queue IDjobId(path) (required): string — DLQ entry ID
Responses:
- 201: New job created from DLQ entry
- 402: Free-plan monthly attempt limit reached — replays mint new billable jobs, so they share the publish gate. Never sent to paid plans.
- 404: Queue or DLQ job not found
- 409: DLQ job already replayed
- 410: Queue has been deleted; its dead-letter jobs are gone
POST /v1/queues/{id}/dlq/replay
Bulk replay DLQ jobs Retries up to 1000 DLQ jobs at once. Provide either jobIds: string[] or all: true.
Parameters:
id(path) (required): string — Queue ID
Responses:
- 200: Bulk replay result
- 400: Validation error
- 402: Free-plan monthly attempt limit reached — replays mint new billable jobs, so they share the publish gate. Never sent to paid plans.
- 404: Queue not found
- 410: Queue has been deleted; its dead-letter jobs are gone
Ack mode
Async acknowledgement, defer, and nack for long-running or backpressured consumers.
POST /v1/jobs/{id}/ack
Acknowledge a job (ack-mode queues only) Signals successful completion of a job in awaiting_ack. Only valid for queues with mode: "ack".
Parameters:
id(path) (required): string — Job ID
Responses:
- 200: Ack accepted
- 400: Job is not awaiting ack, or queue does not use ack mode
- 404: Job not found
POST /v1/jobs/{id}/nack
Signal failure for a job (ack-mode queues only) Marks an awaiting_ack job as failed. retryable: true re-queues with backoff; retryable: false dead-letters immediately.
Parameters:
id(path) (required): string — Job ID
Request body:
retryable: booleanreason: string
Responses:
- 200: Nack accepted
- 400: Validation error, job not awaiting ack, or queue not in ack mode
- 404: Job not found
POST /v1/jobs/{id}/defer
Apply backpressure (ack-mode queues only) Holds an awaiting_ack job for retryAfter seconds, then redelivers — without burning an attempt. Use when a downstream returns 429/503/529.
Parameters:
id(path) (required): string — Job ID
Request body:
retryAfter: number (required)reason: string
Responses:
- 200: Defer accepted
- 400: Validation error, job not awaiting ack, or queue not in ack mode
- 404: Job not found