provider.only on Sume image requests: why other slugs return 400
Porting an OpenRouter-style image call? On Sume, provider.only and order accept only sume; other slugs return 400 provider_not_available. Field rules.

In v1, provider.only and provider.order accept only "sume". Any other provider slug returns 400 provider_not_available. Sume's Image API follows the OpenRouter Image API schema, so a request written for a multi-provider router parses, but Sume publishes a single sume endpoint for each model and does not disclose the upstream provider.
That makes most routing fields harmless to keep and a few of them wrong to send.
Field by field
| Field | Behavior on Sume | What to do in a port |
|---|---|---|
provider.only | Accepts only sume | Set to ["sume"] or remove |
provider.order | Accepts only sume | Set to ["sume"] or remove |
provider.ignore | Accepted, no effect | Remove, it hides nothing |
provider.sort | Accepted, no effect | Remove |
provider.allow_fallbacks | Accepted, no effect | Remove |
provider.options | Must be omitted or {} | Drop provider-specific keys |
Any other slug in only / order | 400 provider_not_available | Fix the slug |
See the error for yourself
This sends one request that is valid and one with a different provider slug, so you can see the status codes before you port the rest. The second call should fail before anything is generated.
import os, requests
key = os.environ.get("SUME_API_KEY")
if not key:
raise SystemExit("set SUME_API_KEY")
for slug in ("sume", "some-other-provider"):
r = requests.post(
"https://api.sume.com/v1/images",
headers={"Authorization": f"Bearer {key}"},
json={"model": "bytedance-seed/seedream-4.5", "mode": "async",
"prompt": "A red panda astronaut",
"provider": {"only": [slug]}},
timeout=60,
)
print(slug, r.status_code, r.text[:160])Why it is built this way
Keeping the schema lets a client library written for another router connect without edits. Rejecting unknown slugs keeps the client from believing a request went to a provider that it did not.
To get a particular family, choose the catalog model id. That is the lever Sume gives you. Routing within a model is not yours to set.
Related limits in the same table
stream: truereturns400 streaming_not_supported. Use async mode and read the job events instead.seedandoutput_compressionreturn400 unsupported_parameterbecause no model advertises them.mode: "subscribe"is an alias for sync, a single bounded wait.
A porting checklist
Before you switch a client over, strip the routing block to the one field you need, or to nothing. Then run a single low-cost call per model you use and read the status code. A clean 200 or 202 means the request shape is accepted. A 400 names the field to fix, and fixing it is usually a deletion.
Also re-read each model's descriptors with the catalog call. Routing is only one of the places a request written for another service can differ.
Sources
Related posts
More in Integrations
- Render a Short over MCP: timeline_create, jobs_wait, timeline_get
Three hosted MCP tool calls turn a Timeline document into a vertical Short: create with an idempotency_key, wait on the job, then fetch the result.
- GitHub Actions job that renders a 9:16 clip on Sume as an artifact
A workflow file that replaces a Sora render step: submit to Sume, poll with a deadline, and upload the mp4 as a build artifact. The key stays in a secret.
- stt_create dry_run and max_spend_usd: cap an MCP transcription run
On Sume's hosted MCP, dry_run previews admission and cost without submitting, and max_spend_usd caps a paid stt_create. Add an idempotency_key to every write.
- Vercel Sandbox static egress IP: do I need to allowlist Sume?
Secure Compute gives Vercel Sandbox static egress IPs. Calling Sume needs only an API key over HTTPS; for webhooks into your app, verify the signature.
Written by Sume