Test a Sume STT webhook locally: webhook_url must be public HTTPS
Sume rejects localhost, private-network and non-HTTPS webhook_url values. Put a tunnel in front of your dev server, or poll while you build.

You cannot give Sume http://localhost:3000 as a webhook. The webhook_url on an STT request must be a public HTTPS callback; localhost, private-network and non-HTTPS URLs are rejected. To test a receiver on your laptop, put a tunnel in front of it that gives you a public HTTPS address, or skip webhooks while you build and poll the job status instead.
Either route reaches the same place: a terminal event for the job.
What does Sume accept?
Per the Sume OpenAPI spec, the URL is stored for terminal job callback delivery. Delivery is terminal only, so you receive job.completed, job.failed or job.canceled, and there are no progress or partial callbacks.
| URL | Accepted? |
|---|---|
| https://hooks.example.com/sume | Yes, public HTTPS |
| http://hooks.example.com/sume | No, not HTTPS |
| https://localhost:3000/hook | No, localhost |
| https://10.0.0.5/hook | No, private network |
How do you develop against it?
Pick the lightest option that matches what you are testing.
- Testing signature checks: use a tunnel so the real
sume-v1signature reaches your code. - Testing only your own handler logic: post a saved payload to it with curl, no Sume call needed.
- Testing the pipeline end to end without a tunnel: poll the status route and add the webhook later.
What does the request look like?
Read the tunnel address from the environment so the same script works on any machine:
import os, requests
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
r = requests.post("https://api.sume.com/v1/stt-1.0/transcribe",
headers=H, timeout=60,
json={
"audio_url": os.environ["AUDIO_URL"],
"mode": "webhook",
"webhook_url": os.environ["PUBLIC_HOOK_URL"],
})
print(r.status_code, r.json()["data"]["job"]["id"] if r.ok else r.text[:200])
What if your receiver misses the call?
A tunnel that is down when the job finishes is the common failure. You do not need to rerun the job; see redelivering a missed webhook. For the wider pattern, read keeping a TTS pipeline portable.
Sources
Related posts
More in Developers
- Sume 400: Idempotency-Key must be 255 printable characters or less
The Sume API rejects an Idempotency-Key over 255 characters or with control characters. Why it happens (JSON blobs, newlines) and a TypeScript key builder.
- Sume 429 body: parse details.scope and window_seconds in TypeScript
A Sume rate_limited 429 names the read or write bucket and gives limit, window_seconds and retry_after_seconds. Parse them in TypeScript and wait.
- Sume 429 retry with a deadline: give up when retry-after is too long
Retrying a Sume 429 forever blocks a request. Cap the total wait, give up when retry-after exceeds what is left, then surface the error. TypeScript wrapper.
- Sume API 503 codes: which ones are retryable and which are not
Four 503 responses look alike but differ in the retryable flag: deploy_draining, database_busy, provider_capacity_exceeded and any _not_configured code.
Written by Sume