Advanced · 25 min · practise every command in the built-in terminal

🛠️ Project: A Daily Report from an API

The café's order system runs on this server, and its API tells you today's orders:

curl -s http://localhost:5000/api/orders

One long line of JSON — handy for programs, not for people. The owner wants a short report every evening: how many orders, how much money came in, what sold best, which orders still wait.

Read it

sudo apt install jq                                   # if you haven't yet
curl -s http://localhost:5000/api/orders | jq .
curl -s http://localhost:5000/api/orders | jq '.orders[0]'

Each order has an id, a customer, its items (product, qty, price), a total and a status: paid, pending or cancelled.

Ask it

curl -s http://localhost:5000/api/orders | jq '.orders | length'
curl -s http://localhost:5000/api/orders | jq '[.orders[] | select(.status == "paid") | .total] | add'
curl -s http://localhost:5000/api/orders | jq -r '.orders[] | select(.status == "pending") | "\(.id) \(.customer)"'

Fetch once, ask many times: save the answer in a file, and point jq at the file.

curl -s http://localhost:5000/api/orders > /tmp/orders.json

What sold best

The cups of every paid order, grouped by product:

jq '[.orders[] | select(.status == "paid") | .items[]] | group_by(.product) | map({product: .[0].product, qty: (map(.qty) | add)}) | sort_by(-.qty)' /tmp/orders.json

group_by makes an array of arrays — one per product; map({...}) turns each into one object; sort_by(-.qty) puts the biggest first. Add | .[0].product with -r for just the winner.

The report script

~/scripts/orders-report.sh saves a summary as JSON in ~/reports/orders-DATE.json:

#!/bin/bash
# Today's orders from the café's API, summed up in ~/reports/orders-DATE.json
mkdir -p ~/reports
OUT=~/reports/orders-$(date +%F).json
curl -s http://localhost:5000/api/orders | jq '{
  date: .date,
  orders: (.orders | length),
  revenue: ([.orders[] | select(.status == "paid") | .total] | add),
  pending: [.orders[] | select(.status == "pending") | .id]
}' > "$OUT"
echo "report saved: $OUT"
{
  "date": "2026-10-30",
  "orders": 12,
  "revenue": 57,
  "pending": [
    1004,
    1009,
    1012
  ]
}

For the accountant: CSV

jq -r '.orders[] | select(.status == "paid") | [.id, .customer, .total] | @csv' /tmp/orders.json > ~/reports/paid.csv

💡 curl -s URL | jq FILTER is how most automation talks to cloud services, monitoring and CI systems — the API changes, the pattern stays.

Practice tasks

  1. See today's orders from the API, readably
  2. Count today's orders
  3. Add up the totals of the paid orders: today's revenue
  4. Find the product that sold best (most cups in paid orders)
  5. Write ~/scripts/orders-report.sh: it saves the summary (orders, revenue, pending) in ~/reports/orders-DATE.json
  6. Run it and check today's report
  7. Export the paid orders as CSV (id, customer, total) to ~/reports/paid.csv

Commands in this lesson

Projects