Sume webhook_url 400: localhost, http, credentials, alias clash

Why a Sume create call rejects webhook_url with 400 invalid_request: localhost, private IPs, http, credentials in the URL, or conflicting webhook_url aliases.

5 min readSume
All posts

Sume rejects a webhook URL with 400 invalid_request when it is not a public HTTPS URL, or when two spellings of the field disagree. Localhost, private-network ranges, plain http:// and credentials embedded in the URL all fail at create, before any run or job exists. The check runs again at delivery time, so a URL that passed at submit can still fail later.

Details below come from Run webhooks, Webhooks and Errors and spend, read 2026-10-02.

Which URLs does Sume refuse?

A rejected create returns the standard envelope with error.code of invalid_request, and nothing is charged.

Webhook URL rules at create, read 2026-10-02
Your URLOutcomeFix
http://hooks.example.com/sume400 invalid_request (plain HTTP)Use https
https://localhost:3000/hook400 invalid_request (localhost)Expose a public HTTPS tunnel or staging host
https://10.0.0.5/hook400 invalid_request (private range)Use a publicly routable host
https://user:pass@example.com/hook400 invalid_request (credentials in URL)Authenticate with the signature, not the URL
URL over the 2048-character maximum (run webhooks)Rejected at createShorten the URL; carry state in your own database

What is the alias conflict?

Run endpoints accept the URL under several names. Inside communication, webhook_url and callback_url are aliases with identical behavior, so send one or the other. There are also fal-shaped top-level webhook_url, callback_url and mode fields, which Sume normalizes into communication.*. Sending the same value on both layers is fine. Conflicting values return 400 invalid_request.

Generation-job submits use the same idea: webhook_url and its alias callback_url. If you send a URL without a mode, you get webhook mode.

# Fine: same value on both layers
curl -sS -X POST https://api.sume.com/v1/formats/acme/product-promo/runs \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: promo-8823-v1" \
  -d '{"instruction":"Make the promo",
       "webhook_url":"https://hooks.example.com/sume",
       "communication":{"webhook_url":"https://hooks.example.com/sume"}}'

# 400 invalid_request: the two layers name different URLs
#   "webhook_url":"https://a.example.com/x"
#   "communication":{"webhook_url":"https://b.example.com/x"}

What does mode do for a run?

For Format, Action and Agent Completion runs, communication.mode is async (the default) or webhook, and the docs call it descriptive: supplying the URL is what arms delivery. There is no subscribe value for runs. So a run with a valid webhook_url and mode: "async" still gets its single terminal POST, and a run with mode: "webhook" but no URL has nothing to deliver to.

Why can a valid URL still fail later?

The URL is re-validated as public HTTPS at delivery time, not only when you submit. If DNS now points the host at a private address, or the endpoint starts redirecting, the attempt fails. Redirects are never followed, and a 3xx counts as a failed attempt, so register the final URL rather than a vanity link that redirects.

The failure shows up on the receipt as webhook_delivery.status of failed or exhausted with last_error, while the run itself stays completed. Read the receipt from result_url, fix the endpoint, and replay with the redeliver route.

A quick checklist before you submit

Run through these before the first paid call, because a 400 at create costs nothing but a blocked launch does.

  • Use an https:// URL on a public host with a certificate that validates.
  • Put no username or password in the URL; verify the sume-v1 signature instead.
  • Send one spelling of the field, or the same value on every layer.
  • Answer the first POST with a 2xx inside 10 seconds, then do the work.
  • Keep status polling as a backup for any event that never arrives.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume