Bruno collection that polls a Sume job until it is terminal
Use bru.setNextRequest and bru.sleep in a Bruno post-response script to poll a Sume job's status route with a bounded attempt count, then fetch the result.

Bruno is a file-based API client, and its scripting API is enough to poll a Sume job without a separate script. The Bruno JavaScript reference lists bru.setVar, bru.getVar, bru.getEnvVar, bru.getSecretVar, bru.setNextRequest(name|null), await bru.sleep(ms) and res.getBody() and res.getStatus(), read 2026-10-03. Runtime variables last only during a collection run, while environment variables persist to disk.
The three requests
Build a folder with Submit, Status and Result. Submit posts to the Sume REST API in async mode with an Idempotency-Key; per the Sume jobs guide it answers 202 with status_url, result_url and next_poll_after_seconds. Keep the API key as a secret variable read with bru.getSecretVar, not typed into the request.
| Field | Meaning | Script action |
|---|---|---|
terminal | The job reached an end state | Stop polling |
result_ready | The result can be fetched | Move on to Result |
sume_status | Sume's job status | Log it |
next_poll_after_seconds (from submit) | Suggested poll gap | Use it for bru.sleep |
The scripts
In Submit's post-response script, store the job id and gap with bru.setVar. In Status, loop on itself while the job is not terminal, with an attempt counter so a stuck job cannot loop forever.
Run it from the collection runner, since the loop depends on setNextRequest ordering.
// Status: post-response script
const b = res.getBody();
const n = Number(bru.getVar("tries") || 0) + 1;
bru.setVar("tries", n);
if (b.terminal || n >= 60) {
bru.setNextRequest(b.result_ready ? "Result" : null);
} else {
const gap = Number(bru.getVar("gap") || 5);
await bru.sleep(gap * 1000);
bru.setNextRequest("Status");
}Rules the collection must respect
- Never resubmit on a failed or timed-out poll; resubmitting is a second paid job unless the idempotency key repeats.
/resultreturns 409job_not_completeduntil the job is done, so only call it afterresult_ready.- A 429 carries
retry-after; honor it before the next request. - Cancel with
POST /v1/jobs/:id/cancel; it returns 409job_generation_already_startedonce generation has begun. - Reset the
triesvariable at the start ofSubmit.
Sources
Related posts
More in Developers
- Bulk run: a bad item fails the whole create, a child failure does not
In a Sume bulk Format run, a bad item is a 400 with details.index and no queue; a child that fails admission after the 202 becomes one failed item.
- Bulk run worst-case spend: items x per-item cap on Sume
A Sume bulk run has no queue-level cap: each item carries its own generation_spend_cap_usd. 100 items at $120 can authorize up to $12,000. How to size it.
- Bun 1.4.1 Bun.serve: a Sume webhook receiver on raw bytes
A Bun.serve routes handler that reads the request as bytes, verifies x-sume-webhook-signature, refuses an empty secret, and returns 2xx only after the check.
- Bun 1.4.1 Bun.write(path, response): save Sume artifacts to disk
Bun 1.4.1 streams a Response body to disk instead of buffering it. Read GET /v1/jobs/:id/result, then Bun.write each artifact URL, checking the status first.
Written by Sume