Send request data
Send JSON
Send a JSON request body with the correct content type and preserve the exact bytes from a file when needed.
JSON is the default language of HTTP APIs. For years, sending it with curl took three things: --data for the body, a --header for the content type, and careful quoting in between.
Modern curl (7.82.0 and later) has --json. It sends the body and adds the right Content-Type and Accept headers in one move.
Send an object
Send a small JSON object to an echo endpoint:
curl --json '{"name":"Mina","active":true}' https://httpbin.org/anything
httpbin returns the headers it saw and the body it parsed:
{
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
},
"json": {
"active": true,
"name": "Mina"
},
"method": "POST"
}
Check three things in that echo.
The method became POST. Sending data implies it, so you didn’t have to ask.
Content-Type: application/json is there. That header tells the server how to parse the body. Without it, many frameworks refuse the request or ignore the body entirely.
And the json field proves the server parsed your object, not a mangled version of it.
Notice the single quotes around the JSON. They protect the double quotes inside from the shell. Get the quoting wrong and the server receives something like {name:Mina}, or the shell errors out before curl even runs. This is the most common failure with JSON in curl.
Send a file
For bigger documents, stop fighting shell quoting and read the body from a file:
curl --json @request.json https://httpbin.org/anything
The @ prefix reads the file byte for byte. No escaping, no quoting puzzles. And you can validate the file first:
jq . request.json
jq fails loudly on broken JSON, before the server ever sees it.
On an older curl
If your curl doesn’t have --json, assemble the same request by hand:
curl --data '{"name":"Mina","active":true}' --header 'Content-Type: application/json' https://httpbin.org/anything
Same bytes on the wire. --json just saves you the typing.
Keep credentials out of examples
Request bodies get pasted into tickets, committed in test scripts, and stored in shell history. Never put a long-lived API credential inside a JSON example, a command you type, or a committed script. A well-formed request with a real secret in it is still a leak.
One last thing. --json guarantees correct headers and intact bytes. It does not check that your JSON matches what the API expects. That contract is between you and the server, and the server will tell you when you got it wrong.
Lesson completed