400 Bad Request invalid JSON: causes and how to fix it
A 400 Bad Request for invalid JSON means your body did not parse. Check shell quoting, single quotes, trailing commas, and unserialized objects.

A 400 Bad Request that says the JSON is invalid means the server could not parse your request body as JSON, so it never got as far as checking your fields. Look at how the body was built: shell quoting that mangled it, single quotes or a trailing comma, an object that was never serialized, or an empty body labeled Content-Type: application/json.
JSON's rules are quoted from RFC 8259 and MDN's JSON.parse errors page, and curl's behavior from its man page and everything curl, all read 2026-09-28. Sume's responses are read from its current API code and its Errors and rate limits docs.
What makes a request body invalid JSON?
Anything a JSON parser rejects. RFC 9110 defines a 400 as a request the server won't process because of a perceived client error, such as malformed request syntax. For JSON, RFC 8259 says a string begins and ends with quotation marks, the " character, and every property name is a string. MDN adds that JSON.parse() does not allow trailing commas or leading zeros such as 01. Four such bodies, as the server receives them:
| Body the server received | Why it fails | Fix |
|---|---|---|
{'prompt': 'hi'} | Single quotes don't delimit JSON strings or property names. | Use double quotes, or let a JSON library write the body. |
{"prompt": "hi",} | A trailing comma after the last member. | Remove the comma. |
[object Object] | An object passed to fetch as the body is converted with toString(). | Send JSON.stringify(body). |
| Nothing at all | An empty body labeled application/json. | Send a body, or drop the header. |
Why does my curl JSON fail on Windows?
Usually because of shell quoting. everything curl's JSON example wraps the body in single quotes, -d '{ "name": "Darth" }', and notes that on Windows single quotes don't work the same way; Sume's docs use the same Unix form. In PowerShell, typing curl can also run an alias for another tool, so type curl.exe, or see posting JSON with Invoke-RestMethod.
The portable fix is to keep the JSON in a file, which needs no extra quoting. -d @file reads the body from a file but strips carriage returns and newlines. --json @file, in curl 7.82.0 and later, posts the file as is and sets Content-Type: application/json and Accept: application/json. curl doesn't check that the data is JSON, so the file still has to be valid. The rest of the command still follows your shell's rules; this one is written for Bash:
# body.json: {"model": "sume/auto", "prompt": "A red fox running through fresh snow"}
curl https://api.sume.com/v1/videos \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Idempotency-Key: fox-video-001" \
--json @body.jsonWhat does Sume return for a body that isn't JSON?
Sume's docs list both invalid_request and bad_request under 400. In current code, a body that doesn't parse is the bad_request one: it carries the parser's own message and is marked retryable: false with next_action: fix_input, so resending the same bytes won't help.
An empty body sent with the JSON header gets the message Body cannot be empty when content-type is set to 'application/json' instead. A malformed one looks like this, abridged:
{
"error": {
"code": "bad_request",
"message": "Body is not valid JSON but content-type is set to 'application/json'",
"retryable": false,
"next_action": "fix_input"
}
}What if the JSON parses but I still get a 400?
Then the problem is usually a field. When a field breaks the route's request schema, current code answers 400 invalid_request with details.errors[] entries, each carrying a path, a message, and a type. On a Format run create, an unknown top-level field is 400 unknown_parameter, with a suggestion when the name is close (webook_url → webhook_url).
The key is checked before the body: in current code an invalid key with a broken body gets 401, not 400, so fix a 401 first. A wrong Content-Type is a different error, 415 Unsupported Media Type, and field errors on POST /v1/videos are covered in video generation API 400 errors.
Why do I get an invalid JSON error on a POST with no body?
Because the request still carried Content-Type: application/json. In current code the JSON parser runs whenever that header is present, and an empty body fails it. For a POST that takes no body, such as canceling a Sume job, leave the header off, as the docs' own example does:
curl -X POST https://api.sume.com/v1/jobs/job_123/cancel \
-H "Authorization: Bearer $SUME_API_KEY"Sources
- RFC 9110: HTTP Semantics (read 2026-09-28)
- RFC 8259: The JSON Data Interchange Format (read 2026-09-28)
- MDN: SyntaxError: JSON.parse: bad parsing (read 2026-09-28)
- MDN: Using the Fetch API (read 2026-09-28)
- MDN: Object.prototype.toString() (read 2026-09-28)
- curl man page (read 2026-09-28)
- everything curl: Arguments to options (read 2026-09-28)
- everything curl: Differences (read 2026-09-28)
- Errors and rate limits
- Create a run
- Generation admission
- Video Generation
Related posts
More in Developers
- 401 vs 403 vs 404: what each API error tells you
401 means your credentials are missing or invalid, 403 means they aren't enough, and 404 means not found, or hidden from you. How to fix each one.
- 429 vs 503: rate limit or server overload?
429 means you sent too many requests in a given time; 503 means the server can't handle requests right now. Both can carry Retry-After. What to do.
- 504 Gateway Timeout from an API: did my request go through?
A 504 from an API means a proxy stopped waiting for the server. Your request may still be running, so check before you resend. How to avoid 504s.
- AI model aggregator: what it is and when to go direct
An AI model aggregator sells many labs' models behind one API key, one request shape and one bill. What you gain, what you give up, and what to check.
Written by Sume