Appearance
Acknowledge a message and send another
POST /spools/{spool}/ack-and-send
Atomically completes the delivery the lease names and appends the request body to the queue Spooler-Queue names — a pipeline step handing its result to the next stage, with no window where the input is acked and the output is missing, or the reverse. The two queues may differ or be the same. Send's headers apply: Spooler-Delay-Seconds postpones the new message, a dedup key deduplicates it. Retries need no dedup key, whatever the status or a lost response: a retry of a committed call fails with 410 and appends nothing. On synchronous copies a redelivery after a lost lease means the first call never committed; with none, a primary change can lose a committed call, input and output alike (see the replication docs). A dedup hit refuses the whole call (409 kind dedup_claimed, the original id in details.id) and acks nothing — ack explicitly if folding into the existing message was the intent. The destination refuses the call the way it refuses a send: a draining queue, the lease's own included, answers 409 queue_deleting and nothing is acked. The spool's message cap does not apply (the call is net zero); the byte cap refuses only growth past the limit.
Sample
sh
curl -si -X POST "$SPOOLER_API/spools/<spool>/ack-and-send" \
-H "Authorization: Bearer $SPOOLER_KEY" \
-H "Spooler-Queue: <queue>" \
-H "Spooler-Lease: <lease>" \
--data-binary '<payload>'Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
spool | path | IdentName, 1–63 chars, ^[A-Za-z0-9_:-]+$ | yes | The spool name. |
handle | query | boolean | no | When true, the response carries a handle to the fresh message in Spooler-Handle. Its one use is to take the message back before anyone receives it: present it to discard to cancel a delayed send whose condition was met in the meantime, or to withdraw a send whose surrounding work failed to commit — a cancel window, not a transaction: a producer that crashes before cancelling leaves a deliverable message. Off by default, since the handle is a bearer credential. |
Spooler-Queue | header | IdentName, 1–63 chars, ^[A-Za-z0-9_:-]+$ | yes | The queue the new message is sent to; the lease names the one acked from. The two may be the same. |
Spooler-Lease | header | Lease, 16–256 chars, ^[A-Za-z0-9_-]+$ | yes | The lease from a receive, presented back. |
Spooler-Delay-Seconds | header | integer, 0–604,800 | no | Seconds until the new message becomes visible, at most a week. Omitted or 0 means immediately visible. |
Spooler-Dedup-String | header | string, 1–128 chars, ^[\x21-\x7E]+$ | no | The new message's dedup key, as on send. A hit inside the queue's dedup window refuses the whole call with 409. |
Spooler-Dedup-Hash | header | string, 32 chars, ^[0-9a-fA-F]{32}$ | no | The new message's 16-byte dedup fingerprint, hex-encoded, as on send. |
Request body
Required; application/octet-stream.
Responses
| Status | Description |
|---|---|
201 | Acknowledged and appended durably; no body. |
400 | The request is malformed; the kind names the problem. |
401 | The API key is missing or not recognized; the kind is unauthenticated. |
402 | The account is suspended; the kind is account_suspended. |
403 | The operation is refused; the kind names why: a plan limit (queue_limit, retention_limit), or account_blocked on any operation when the account is on an abuse hold. |
404 | The spool or queue does not exist; the kind says which. |
409 | Concurrent state refuses the operation; the kind names it. |
410 | The lease no longer settles anything: expired, already settled, or predates a primary change. |
413 | The message exceeds the plan's message size limit. The connection is closed, since the body is left unread. |
429 | The per-account request rate cap is exceeded. The body names the kind (rate_limited); the wait is the Retry-After header and is not repeated in the body. Headers are as structured as the body, and this one is the header HTTP defines for a wait. |
500 | The server failed; kind operation_unconfirmed means the write was accepted but its durability is unknown. |
503 | The spool is momentarily unavailable. |
507 | The new message would grow the spool's payload bytes past its plan's maximum (kind spool_full). An equal or smaller message always passes, so a full spool can still drain. |
201 headers
| Header | Description |
|---|---|
Spooler-Message-Id | The appended message's id. |
Spooler-Handle | The handle to the fresh message; present only when the request asked for it via handle=true. |
429 headers
| Header | Description |
|---|---|
Retry-After | Seconds until the next request is admitted, whole and at least 1; always the delay-seconds form, never an HTTP-date. |