Appearance
Quickstart
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/v1Running 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, worldwait=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
maxRetriesit 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.

