Skip to content
AgileLogics
6 min read

Working with JSON and APIs

Prerequisites: Pipes: connecting commands, Variables

Web APIs return JSON. Two tools make Bash good at working with them: curl makes HTTP requests, and jq processes JSON. Install jq with your package manager (apt install jq, brew install jq).

jq basics

# illustrative
json='{"name": "Ada", "languages": ["R", "Python"], "address": {"city": "London"}}'

echo "$json" | jq '.name'
echo "$json" | jq -r '.name'
echo "$json" | jq -r '.address.city'
echo "$json" | jq -r '.languages[]'
echo "$json" | jq '.languages | length'
"Ada"
Ada
London
R
Python
2
  • .key selects a field; .a.b goes deeper; .list[] outputs each array element.
  • -r prints raw text without JSON quotes — what you want in scripts.
  • | inside a jq program chains filters, just like shell pipes.

Filtering arrays

# illustrative
cat > users.json <<'EOF'
[
  {"name": "Ada", "role": "admin", "active": true},
  {"name": "Linus", "role": "dev", "active": false},
  {"name": "Grace", "role": "admin", "active": true}
]
EOF

jq -r '.[] | select(.role == "admin") | .name' users.json
jq '[.[] | select(.active)] | length' users.json
jq -r '.[] | "\(.name) (\(.role))"' users.json
Ada
Grace
2
Ada (admin)
Linus (dev)
Grace (admin)

Paste JSON into the JSON Formatter to explore its structure before writing a jq filter.

Calling an API with curl

# illustrative
response=$(curl -fsS --max-time 10 \
  -H "Accept: application/json" \
  "https://api.github.com/repos/torvalds/linux") || {
  echo "Request failed" >&2
  exit 1
}

stars=$(jq -r '.stargazers_count' <<< "$response")
echo "Linux has $stars stars on GitHub"
  • -f makes curl fail (non-zero exit) on HTTP errors like 404; -s hides the progress bar; -S still shows errors.
  • --max-time sets a timeout — always set one.
  • -H adds a header. For POST requests: curl -X POST -H "Content-Type: application/json" -d '{"title":"Hi"}' URL.

Secrets

Pass API tokens through environment variables, not command-line arguments (which other users can see in ps), and never commit them: curl -H "Authorization: Bearer $API_TOKEN" ....