FastAPI 0.143 makes OTel exporter setup opt-in: Sume webhook spans
FastAPI 0.143.0 stops auto-configuring OpenTelemetry exporters. If your Sume webhook route traces went quiet after the upgrade, here is the one-line opt-in.

FastAPI 0.143.0 made automatic OpenTelemetry exporter setup opt-in. If your Sume webhook route was exporting traces on 0.142 and goes quiet after you upgrade, pass telemetry={"auto_configure": True} to FastAPI(...) or set FASTAPI_OTEL_AUTO_CONFIGURE=true. An app that builds its own OpenTelemetry providers and exporters needs no change.
What changed between 0.142 and 0.143
Native OpenTelemetry arrived in 0.142.0 on Sep 29, and 0.142.2 on Sep 30 fixed startup failures when the automatic configuration hit a problem, per the FastAPI releases list (read 2026-10-10). The earlier post on tagging spans with a Sume job id covers the attribute. This post covers what happens when you take the next release.
The 0.143.0 release notes (read 2026-10-10) carry one breaking change.
| Question | Answer from the notes |
|---|---|
| What changed | Automatic OpenTelemetry exporter setup, driven by OTEL_* environment variables, is now opt-in |
| How to opt in (env) | FASTAPI_OTEL_AUTO_CONFIGURE=true |
| How to opt in (code) | FastAPI(telemetry={"auto_configure": True}) |
| Who is unaffected | Apps that configure their own providers and exporters; FastAPI Cloud handles setup for compatible apps |
| Reference | PR #16476 |
Why it shows up on a webhook route
A receiver for Sume job webhooks is a good place to notice this. Sume retries a delivery up to 10 times with a 10 second timeout on each attempt, and it tells you to use job_id as your idempotency key. When a delivery fails twice and succeeds on the third try, the trace for the third request is what you look at, and the job_id on the span is how you find the other two.
Without an exporter, trace.get_current_span().set_attribute(...) still runs. It writes to a span that nothing sends anywhere, so the route works and the evidence is missing. That is a quiet failure, which is why the opt-in is worth a line in your upgrade checklist.
import hashlib
import hmac
import os
import time
from fastapi import FastAPI, HTTPException, Request
from opentelemetry import trace
app = FastAPI(telemetry={"auto_configure": True}) # opt in on 0.143 and later
SECRET = os.environ.get("SUME_COM_WEBHOOK_SIGNING_SECRET", "")
def verify(raw: bytes, ts: str, header: str) -> bool:
if not SECRET or not ts.isdigit() or abs(time.time() - int(ts)) > 300:
return False
mac = hmac.new(SECRET.encode(), ts.encode() + b"." + raw, hashlib.sha256)
want = "sume-v1=" + mac.hexdigest()
return any(hmac.compare_digest(e.strip(), want) for e in header.split(","))
@app.post("/sume/webhook")
async def sume_webhook(request: Request):
raw = await request.body()
ts = request.headers.get("x-sume-webhook-timestamp", "")
sig = request.headers.get("x-sume-webhook-signature", "")
if not verify(raw, ts, sig):
raise HTTPException(status_code=401)
event = await request.json()
trace.get_current_span().set_attribute("sume.job_id", event["job_id"])
return {"ok": True}How I checked the sample
I installed FastAPI 0.143.0 and opentelemetry-api, called the route through the test client with a valid signature, and got {"ok": true}. A second request with a wrong signature returned 401. The verifier follows the Sume docs: HMAC SHA-256 over <timestamp>.<raw_body>, a five minute tolerance, any sume-v1= entry may match during a secret rotation, and an empty secret is refused.
- If you set
OTEL_EXPORTER_OTLP_ENDPOINTand expected FastAPI to read it, add the opt-in. If you callTracerProvideryourself, leave things as they are. - Read the signing secret from
SUME_COM_WEBHOOK_SIGNING_SECRET, the name the Sume docs use. - Return 2xx only after you store the
job_id. A trace that says the route answered 200 should mean the event is safe. - Keep a status poll as a backup. The webhooks page says a delivery is an optimization, not the only recovery path.
Sources
Related posts
More in Developers
- Prove a Sume retry makes one job: drop the response on purpose
A 28-line fake server creates the job, then hangs up before replying. A stable Idempotency-Key leaves one job; a fresh key per retry leaves two. Runs anywhere.
- Fit an AI voiceover to a target length with Sume TTS speed 0.6 to 1.5
To hit a target duration, generate once, measure the audio, then set generation_config.speed to measured over target, clamped to Sume's 0.6 to 1.5 range.
- A for await loop over Sume job status: one async generator, 3 runtimes
Wrap Sume status polling in an async generator and read it with for await. One fetch-only file ran unchanged on Node, Bun and Deno and honors the poll hint.
- Generate a Go client from the Sume OpenAPI with oapi-codegen
The full Sume spec trips oapi-codegen on a [number, null] type, but filtering to the operations you use works. Config, generated names and a short caller.
Written by Sume