Fixed: "415 Unsupported Media Type" from a POST to an ASP.NET Core Minimal API
A POST with perfectly good JSON came back as 415 Unsupported Media Type, and the API's log had nothing to say about it. The JSON wasn't the problem: the request never said it was JSON. curl labels a -d body as a web form unless you tell it otherwise, and a minimal API endpoint that expects JSON won't touch that.
What I Was Doing
A .NET 10 minimal API has an endpoint that takes a JSON body, through a record parameter:
private static async Task<Results<Created<CategoryResponse>, ProblemHttpResult>> CreateAsync(
CategoryRequest request,
I sent it a JSON body with curl:
curl -i -X POST http://localhost:5190/api/v1/categories -d '{"name":"Form"}'
What I Expected
201 Created.
What I Got
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/problem+json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.16",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "00-522930cbe0a99ef7a908259655babf4d-3e463430e46c094b-00"
}
The API's normal log stayed empty for this request.

What I Checked
What the API saw. To see more, I ran the API with the Microsoft.AspNetCore log level at Debug, passing it on the command line:
dotnet run --project src/Dewiride.Inventory.Api -- --Logging:LogLevel:Microsoft.AspNetCore=Debug
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5190/api/v1/categories - application/x-www-form-urlencoded 15
dbug: Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware[1]
Request matched endpoint '415 HTTP Unsupported Media Type'
There it is: application/x-www-form-urlencoded. That's what curl's -d sends by default. And routing itself chose the 415, without running the endpoint, which is why nothing else was logged.
What the documentation says. The error handling page mentions the status for "unsupported request content types" on JSON body binding, and the parameter binding page lists "Body (as JSON)" as a binding source. So the endpoint accepts JSON, and the request said it was something else.
Why It Happens
Content-Type tells the server how to read the body. A record parameter makes ASP.NET Core expect JSON, and it goes by that header, not by what the bytes look like. A body labelled as a web form isn't accepted, even if its text happens to be valid JSON.
The Fix
Send the header. In curl:
curl -i -X POST http://localhost:5190/api/v1/categories -H "Content-Type: application/json" -d '{"name":"With header"}'
In a .http file, put it right under the request line, with a blank line before the body:
POST {{Dewiride.Inventory.Api_HostAddress}}/api/v1/categories
Content-Type: application/json
{
"name": "With header"
}
After the Fix
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Location: /api/v1/categories/502
{
"id": 502,
"name": "With header",
"createdAtUtc": "2026-11-04T11:43:36.60438Z"
}

Common Mistakes
| Mistake | What happens | Do this instead |
|---|---|---|
Assuming curl's -d means JSON | It sends a form type | Add the header |
| Changing the endpoint to read the raw body | You lose binding and validation | Fix the client |
Forgetting the blank line in a .http file | The body is read as more headers | Put one blank line before the body |
Adding [FromForm] to make it pass | The endpoint no longer reads JSON | Send JSON with the right header |
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
415 Unsupported Media Type with no error in the log | No Content-Type: application/json | Add it |
400 Bad Request after adding the header | The JSON itself is broken | See the bad request post |
415 from a browser form | Forms send a form type | Send JSON with fetch, or accept forms |
415 with text/plain | A client library's default | Set the content type in the client |
FAQ
Why doesn't ASP.NET Core look at the body and guess?
Because the header is what HTTP defines for this. Guessing would make a client's mistake look like it worked, until the day it didn't.
Does curl's --json flag help?
Yes: --json sets the header for you, in curl 7.82 and newer. Older copies of curl don't have it.
Conclusion
415 Unsupported Media Type from a minimal API POST means the request didn't say its body is JSON. curl's -d sends application/x-www-form-urlencoded, and routing answers 415 before your code runs, so the log stays quiet. Add Content-Type: application/json.
Additional Resources
- Parameter binding in Minimal API apps — how a body is bound.
- curl's --json option — the shortcut for JSON requests.
