Log the Sume request_id in Python JSON logs, no keys or URLs

A small logging helper for failed /v1/videos calls: keep error.code, request_id and job id, and leave out the API key and signed media URLs.

5 min readSume
All posts

When a Sume call fails, log error.code, error.request_id, the HTTP status and your own job id, as one JSON line. Sume says the request id is safe to share with support. It also says not to include API keys, signed URLs, raw media URLs, or private workspace and user ids in a report, so the logger should drop those fields by design.

What the error body gives you

Public errors share one envelope: {"error": {"code", "message", "request_id", "details"}}. The request id also appears in response headers. For video jobs that failed after acceptance, the poll shows a single error string, which is the public reason; there is no request id in it, so log your own job id next to it.

Fields to keep and to drop when you log a Sume failure, from the Sume errors docs (read 2026-10-08)
FieldLog it?Reason
error.codeyesbranch and alert on it
error.request_idyesthe id support asks for
HTTP statusyesseparates 4xx from 5xx
error.detailsyes, trimmedfor example details.supported on a 400
Authorization headerneverit is your API key
unsigned_urls and Location valuesneversigned or private media URLs

The helper

The function below takes a requests.Response, builds the log record and writes it with the standard logging module. It truncates details to 500 characters and falls back to a plain-text record when the body is not JSON, which is what a proxy error page looks like.

import json
import logging

log = logging.getLogger("sume")

def log_sume_failure(resp, job_id: str | None = None) -> None:
    try:
        err = resp.json().get("error", {})
    except ValueError:
        err = {}
    log.error(json.dumps({
        "event": "sume_request_failed",
        "status": resp.status_code,
        "code": err.get("code"),
        "request_id": err.get("request_id"),
        "job_id": job_id,
        "details": json.dumps(err.get("details"))[:500],
        "retry_after": resp.headers.get("retry-after"),
    }))

What to alert on

Count by code, not by message text. unauthorized means a bad or missing key and should page a human once, not retry. rate_limited and queue_full are expected under load and should only alert when they persist. unsupported_capability and unsupported_parameter are bugs in your own request builder, so alert on any non-zero count after a deploy.

Because the request id is also in the response headers, a proxy that strips bodies can still log it. Log both when you have both.

When you open a ticket, send the request id, the time, the route and the HTTP status. That is enough for support to find the call, and none of it is secret.

Using it

Call it right before you raise. A 429 with retry-after becomes a record you can chart, and a 400 with unsupported_capability keeps details.supported, so the next engineer sees the allowed values without reproducing the call. For the typed version of the same envelope, see the dataclass post, and for Node the pino version.

  • Redact at the logger, not at each call site.
  • Keep the job id from id on the 202 so a poll failure can be tied to the submit.
  • Send the request_id to support; do not paste the key or a download URL.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume