How to Send JSON Data with cURL: GET, POST, PUT, PATCH, and DELETE Examples

From a terminal, cURL can send JSON straight to a REST API. You need an HTTP method, a Content-Type: application/json header, and a request body containing valid JSON.

The Short Version

For a POST request, use this command:

curl -X POST 'https://api.example.com/users' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alex","email":"alex@example.com"}'

Here, -X POST chooses the request method. The -H option adds the JSON content type, while -d provides the body.

Handy shortcut: If you’re running cURL 7.82.0 or newer, --json sends the data and adds the proper JSON headers for you:

curl 'https://api.example.com/users' \
  --json '{"name":"Alex","email":"alex@example.com"}'

Before You Start

First, check that cURL is installed:

curl --version

Recent versions of Windows 10 and Windows 11 include curl.exe. You’ll also find it preinstalled on most macOS and Linux systems. In every example below, replace the sample URL, IDs, credentials, and field names with values your API accepts.

JSON Options in cURL

OptionWhat it does
-X or --requestChooses POST, PUT, PATCH, DELETE, or another HTTP method.
-H or --headerAdds a request header, such as a content type or authorization token.
-d or --dataPuts data in the request body. Without -X, using this option makes cURL send a POST request.
--jsonSends JSON and adds the Content-Type and Accept headers.
-iPrints response headers along with the response body.
-vDisplays detailed connection and request diagnostics.

Sending JSON with POST

POST is commonly used to create a resource or submit an operation. A typical request looks like this:

curl -X POST 'https://api.example.com/orders' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{"product_id":42,"quantity":2}'

The Accept header tells the server you expect JSON back. Some APIs don’t require it, but including the header can head off content-negotiation trouble.

Sending JSON with PUT or PATCH

PUT generally replaces the server’s representation of a resource. PATCH changes selected fields instead, though the exact behavior is up to the API.

PUT Example

curl -X PUT 'https://api.example.com/users/123' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alex Morgan","email":"alex@example.com","active":true}'

PATCH Example

curl -X PATCH 'https://api.example.com/users/123' \
  -H 'Content-Type: application/json' \
  -d '{"active":false}'

Sending JSON with DELETE

A lot of DELETE endpoints need nothing more than the URL:

curl -X DELETE 'https://api.example.com/users/123'

Sometimes the endpoint accepts a JSON body. If it does, send that body the same way you would with another method:

curl -X DELETE 'https://api.example.com/sessions' \
  -H 'Content-Type: application/json' \
  -d '{"session_id":"abc123"}'

But support for request bodies on DELETE isn’t universal. Check the API documentation before relying on one.

Using JSON with GET

GET requests usually put their parameters in the URL, rather than a JSON body:

curl --get 'https://api.example.com/users' \
  --data-urlencode 'status=active' \
  --data-urlencode 'limit=20'

That produces a URL similar to https://api.example.com/users?status=active&limit=20. cURL can attach a body to GET, technically, but a proxy, framework, or server may ignore it. Stick with query parameters unless the API specifically asks for a GET body.

Sending JSON from a File

For a nested payload, or one you’ll send more than once, save the JSON in a file named payload.json:

{
  "name": "Alex",
  "roles": ["editor", "reviewer"],
  "preferences": {
    "notifications": true
  }
}

Put @ before the file path to send its contents:

curl -X POST 'https://api.example.com/users' \
  -H 'Content-Type: application/json' \
  --data-binary '@payload.json'

The --data-binary option preserves the file exactly as written. With newer cURL versions, the command gets shorter:

curl 'https://api.example.com/users' --json '@payload.json'

Adding API Authentication

Bearer Token

curl 'https://api.example.com/profile' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"display_name":"Alex"}'

Basic Authentication

curl -u 'username:password' \
  -H 'Content-Type: application/json' \
  -d '{"enabled":true}' \
  'https://api.example.com/settings'

Don’t put real secrets in scripts, shell history, screenshots, or shared logs. For commands you’ll reuse, environment variables or a secret manager are safer.

Quoting in Windows PowerShell

Under Windows PowerShell 5.1, curl may resolve to an Invoke-WebRequest alias. Use curl.exe when you want the actual cURL program:

curl.exe -X POST "https://api.example.com/users" `
  -H "Content-Type: application/json" `
  -d '{"name":"Alex","active":true}'

PowerShell 7 normally runs cURL directly when you enter curl. Keep the JSON body inside single quotes so PowerShell doesn’t interpret the double quotes within it.

Checking the Response and Status

Use -i if you want response headers included. Or save the body and print only the final HTTP status code:

curl -sS -o response.json -w '%{http_code}\n' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alex"}' \
  'https://api.example.com/users'

In this example, the response body goes into response.json. Common status codes include 200 for success and 201 when a resource has been created. You’ll often see 400 for invalid input, 401 for missing or invalid authentication, and 415 when the content type isn’t supported.

Mistakes That Cause Trouble

  • Invalid JSON: Property names and string values need double quotes. JSON doesn’t allow trailing commas.
  • No content type: Add Content-Type: application/json unless you’re using --json.
  • Broken shell quoting: On macOS, Linux, and PowerShell where appropriate, wrap the whole payload in single quotes.
  • Form data instead of JSON: A plain -d 'name=Alex' sends form-style data. It isn’t JSON.
  • Credentials in logs: Verbose output can expose authorization headers, so sanitize logs before sharing them.

Debugging a Failed JSON Request

  1. Add -v and inspect the outgoing method and headers.
  2. Use -i to view the server’s response headers and status.
  3. Check the payload with a JSON validator or jq.
  4. Make sure the endpoint supports the HTTP method you selected.
  5. Compare the field names and data types against the API documentation.
curl -v -X POST 'https://api.example.com/users' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Alex"}'

Security note: Don’t treat -k or --insecure as a routine answer to TLS certificate errors. It turns off certificate verification, which can leave the connection open to interception.

Leave a Comment

Related Posts