JSON APIs and authentication

curl · Essentials · 10 min

Most modern APIs speak JSON with token auth; this is the everyday curl workflow.

For JSON APIs, use --json (curl 7.82+). It sends the data as the body, sets Content-Type: application/json and Accept: application/json, and uses POST:

curl --json '{"name":"Ann"}' https://api.example.com/users

--json @user.json reads a file and --json @- reads stdin, so you can pipe generated JSON in. Combine with -X PATCH or -X PUT for other methods. On older curl, the equivalent is -H 'Content-Type: application/json' -d '{...}'.

Building JSON by hand in shell quotes gets messy quickly; generate it with jq -n --arg name "$NAME" '{name: $name}' and pipe it into --json @- so quoting and escaping are always right.

Authentication:

  • Bearer tokens: -H "Authorization: Bearer $TOKEN" (or --oauth2-bearer "$TOKEN").
  • Basic auth: -u user:password, which curl base64-encodes into an Authorization: Basic header. -u user alone prompts for the password, keeping it out of shell history.
  • API keys usually go in a custom header such as -H "X-API-Key: $KEY".

Keep secrets in environment variables or files, not literally in commands: anything on the command line can end up in shell history and is visible to other users in ps. Then pipe the response into jq to read it: curl -sS ... | jq '.items[].name'.

Example

curl --json '{"name":"Ann","role":"admin"}' https://api.example.com/users
# sends POST, Content-Type and Accept: application/json
jq -n --arg name "$NAME" '{name: $name}' | curl --json @- https://api.example.com/users
curl -X PATCH --json '{"role":"viewer"}' https://api.example.com/users/42
curl -sS -H "Authorization: Bearer $API_TOKEN" https://api.example.com/me | jq .email
curl -u ann https://intranet.example.com/report     # prompts for password
curl -sS -H "X-API-Key: $KEY" 'https://api.example.com/items?limit=2' | jq '.items[].name'

Remember

  • --json sets body, Content-Type and Accept in one flag
  • Bearer: -H "Authorization: Bearer $TOKEN"; basic: -u user
  • Generate JSON with jq and pipe it to --json @-

Watch out for

  • Interpolating shell variables into hand-written JSON strings; quotes or newlines in the value break the body.

Check yourself

  1. What does `--json '{}'` set that a plain `-d '{}'` does not?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: curl.se/docs/manpage.html#--json