Skip to content

Quickstart

Last updated 

Spooler is a message queue with a small surface — the whole API is 13 operations. Payloads travel raw as request and response bodies, message attributes ride Spooler-* headers. A receive hands out a lease — an opaque signed token — and you ack, nack, or renew by presenting it back. Messages that exhaust their retries land in a failure queue you can peek, recover, or discard. That is the whole model.

Typical use is work that leaves the request path: background jobs, distributing tasks across a pool of workers, buffering webhook or event bursts ahead of a slower consumer, and retrying work that failed. If a unit of work must survive a crash and be retried until someone acks it, it belongs in a queue.

You need curl and an API key from the console.

sh
export SPOOLER_KEY='<your api key>'
export SPOOLER_API=https://api.spooler.sh/v1

Running the local image instead? Point SPOOLER_API at it: http://localhost:8080/v1.

Every request below addresses the spool named default, which every account has. A spool is an isolated storage unit — like a database instance of your own — that holds your queues; storage and capacity limits are per spool.

Create a queue

sh
curl -X PUT "$SPOOLER_API/spools/default/queues/test" \
  -H "Authorization: Bearer $SPOOLER_KEY"

Returns 201. Queues are created with server defaults; read them back with List queues and change lease timeouts, retries, retention, and deduplication windows with Update queue settings.

Send a message

sh
curl -si -X POST "$SPOOLER_API/spools/default/queues/test/send" \
  -H "Authorization: Bearer $SPOOLER_KEY" \
  --data-binary 'hello, world'
http
HTTP/2 201

{"duplicate":false,"id":"1-1"}

The body you send is the message — bytes in, bytes out, no envelope. 201 means the message is durably stored: it was written and fsynced before the response.

Receive it

sh
curl -si -X POST "$SPOOLER_API/spools/default/queues/test/recv?wait=20s" \
  -H "Authorization: Bearer $SPOOLER_KEY"
http
HTTP/2 200
spooler-lease: dGhpcyBpcyBub3QgYSByZWFsIGxlYXNl
spooler-message-id: 1-1
spooler-retry-count: 0
spooler-lease-expires-at: 2026-08-12T10:00:30Z

hello, world

wait=20s long-polls: the call waits until a message becomes visible or the wait elapses (204). Omit it to return immediately.

Receiving does not delete the message — it leases it. While the lease is live, no other receiver gets the message; if you never settle it, the lease times out and the message is redelivered.

Acknowledge it

sh
curl -X POST "$SPOOLER_API/spools/default/ack" \
  -H "Authorization: Bearer $SPOOLER_KEY" \
  -H "Content-Type: application/json" \
  --data '{"lease": "<the spooler-lease header value>"}'

Returns 204. The message is durably removed. That is the whole loop: send, receive, ack.

Where to go next

  • Run Spooler locally for development and tests: docker run --rm -p 127.0.0.1:8080:8080 spoolersh/memspoold — no account needed; see Running locally.
  • What a delivery guarantees, and what it doesn't — Delivery.
  • Give up on a delivery instead of acking it — nack returns it for redelivery; after the queue's maxRetries it lands in the failure queue.
  • Exactly-once enqueue with deduplication.
  • What the server enforces: limits and errors.
  • Every operation, generated from the spec — API reference.
  • What Spooler deliberately is not — non-goals and alternatives.