Log x-sume-request-id on every Sume call in Python
Capture the x-sume-request-id response header in a requests hook, attach it to each log line with logging.Filter and contextvars, and quote it to support.

To make every Sume call traceable, read the x-sume-request-id response header once in a requests response hook and put it on each log line through a logging.Filter that reads a contextvars variable. Sume's errors docs say every response carries the header, and the error body repeats it as request_id, to quote to support.
The Python logging cookbook describes using a filter to add contextual information to records (read 2026-10-04), which is the right seam: your call sites stay clean and every line, including ones from libraries, gets the id.
What does the wiring look like?
The hook runs for every response on the session, including errors, so the failing call is the one you can find later.
import contextvars, logging, os, requests
request_id = contextvars.ContextVar("sume_request_id", default="-")
class SumeId(logging.Filter):
def filter(self, record):
record.sume_request_id = request_id.get()
return True
handler = logging.StreamHandler()
handler.addFilter(SumeId())
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(sume_request_id)s] %(message)s"))
log = logging.getLogger("sume")
log.addHandler(handler)
log.setLevel(logging.INFO)
def remember(resp, *args, **kwargs):
request_id.set(resp.headers.get("x-sume-request-id", "-"))
log.info("%s %s -> %s", resp.request.method, resp.request.path_url, resp.status_code)
session = requests.Session()
session.hooks["response"].append(remember)
session.headers["x-api-key"] = os.environ["SUME_API_KEY"]
if __name__ == "__main__":
session.get("https://api.sume.com/v1/jobs/job_123/status", timeout=30)Which fields are safe to log?
| Field | Where | Log it? |
|---|---|---|
| x-sume-request-id | Response header | Yes, on every call |
| error.code and error.retryable | Error body | Yes |
| retry-after and ratelimit-remaining | Response headers | Yes, as numbers |
| job id or run id | Submit response | Yes, in your own job logs |
| x-api-key | Request header | Never |
| Webhook signing secret | Your config | Never |
Why a contextvar and not a global?
A plain global would be overwritten by whichever thread or task answered last. A ContextVar is isolated per thread and per asyncio task, so concurrent polls log their own ids. If you use httpx rather than requests, the same idea works with an event hook.
What do you do with the id?
- Include it when you contact support, together with the time and the route.
- Store it next to the job id when a submit fails, so a retry can be correlated.
- Keep it out of metric labels; it is unique per call and would create a series for each.
Sources
Related posts
More in Developers
- Railway webhook custom headers vs Sume's signed headers
Railway project webhooks now accept custom headers. Sume signs its callbacks with x-sume-webhook-timestamp and x-sume-webhook-signature; verify them in Python.
- Railway Sandboxes: run the Sume CLI with an env-var key
Inside a short-lived sandbox, install the Sume CLI with the hosted installer, pass SUME_API_KEY as an environment variable, and never print it.
- Re-render 300 old Sora prompts: queue capacity by plan
A 300-prompt backlog does not fit in one burst. Use Sume's accepted-job limits per plan, the wave_size_hint, and queue_full handling to pace the re-render.
- React Router 7 resource route as a Sume webhook receiver
A React Router 7 route module with only an action is a resource route. Read request.text(), call verifyWebhook from @sume-com/sdk, answer 204, branch on event.
Written by Sume