Skip to Content
chalvien 1.0 is released

cURL Quick Guide for Daily API Work

This guide is a practical curl reference for local development with:

  • Express APIs
  • JWT authentication
  • PostgreSQL-backed endpoints

You can copy and run each command as-is (adjust host, port, and payloads).

1. Core cURL patterns

Most daily commands use these flags:

  • -X or --request: HTTP method (GET, POST, PATCH, DELETE)
  • -H or --header: request headers
  • -d or --data: JSON/form payload
  • -i: include response headers
  • -s: silent mode (useful in scripts)

Examples:

# GET (default method is GET, so -X GET is optional) curl -i http://localhost:5000/health # POST with JSON curl -i -X POST http://localhost:5000/api/users \ -H 'Content-Type: application/json' \ -d '{"name":"Max","email":"max@example.com"}'

2. Helpful shell variables

Using variables makes commands shorter and repeatable.

API='http://localhost:5000' EMAIL='admin@example.com' PASS='StrongPassword123!'

3. JWT auth flow (bootstrap -> login -> protected routes)

These examples assume endpoints like:

  • POST /api/auth/bootstrap
  • POST /api/auth/login
  • GET /api/auth/me
  • POST /api/auth/refresh
  • POST /api/auth/logout

Create the first admin (dev setup):

curl -i -X POST "$API/api/auth/bootstrap" \ -H 'Content-Type: application/json' \ -d '{"email":"admin@example.com","password":"StrongPassword123!","name":"System Admin"}'

Login and capture access token with jq:

ACCESS_TOKEN=$(curl -s -X POST "$API/api/auth/login" \ -H 'Content-Type: application/json' \ -d "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}" \ | jq -r '.accessToken') echo "$ACCESS_TOKEN"

Use JWT for protected route:

curl -i "$API/api/auth/me" \ -H "Authorization: Bearer $ACCESS_TOKEN"

If refresh token is in an HttpOnly cookie, persist cookies with -c and -b.

Login and store cookies:

curl -i -X POST "$API/api/auth/login" \ -H 'Content-Type: application/json' \ -c cookies.txt \ -d "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}"

Refresh access token using cookie:

curl -i -X POST "$API/api/auth/refresh" \ -b cookies.txt

Logout and clear server-side refresh state:

curl -i -X POST "$API/api/auth/logout" \ -b cookies.txt

5. Express + PostgreSQL daily CRUD examples

Assume a users table in PostgreSQL and these API routes:

  • GET /api/users
  • GET /api/users/:id
  • POST /api/users
  • PATCH /api/users/:id
  • DELETE /api/users/:id

Create user:

curl -i -X POST "$API/api/users" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{"name":"Nnamdi","email":"nnamdi@example.com"}'

List users:

curl -i "$API/api/users" \ -H "Authorization: Bearer $ACCESS_TOKEN"

Get one user:

curl -i "$API/api/users/1" \ -H "Authorization: Bearer $ACCESS_TOKEN"

Update user:

curl -i -X PATCH "$API/api/users/1" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{"name":"Nnamdi Okafor"}'

Delete user:

curl -i -X DELETE "$API/api/users/1" \ -H "Authorization: Bearer $ACCESS_TOKEN"

6. Minimal Express + pg endpoint example

If you need a tiny reference implementation:

const express = require("express") const { Pool } = require("pg") const app = express() app.use(express.json()) const pool = new Pool({ connectionString: process.env.DATABASE_URL, }) app.get("/health", async (req, res) => { const { rows } = await pool.query("select now() as now") res.json({ ok: true, dbTime: rows[0].now }) }) app.get("/api/users", async (req, res) => { const { rows } = await pool.query( "select id, name, email from users order by id desc limit 50" ) res.json({ users: rows }) }) app.post("/api/users", async (req, res) => { const { name, email } = req.body const { rows } = await pool.query( "insert into users(name, email) values($1, $2) returning id, name, email", [name, email] ) res.status(201).json({ user: rows[0] }) }) app.listen(5000, () => { console.log("API running on http://localhost:5000") })

7. PostgreSQL quick checks from API perspective

Check API health (includes DB check):

curl -i "$API/health"

Example filtered list endpoint:

curl -i "$API/api/users?limit=20&offset=0" \ -H "Authorization: Bearer $ACCESS_TOKEN"

8. Common troubleshooting

  • 401 Unauthorized: token missing, expired, or wrong secret.
  • 403 Forbidden: token valid but role not allowed.
  • 400 Bad Request: invalid JSON payload or missing required fields.
  • 500 Internal Server Error: backend query/runtime issue. Check API logs.

Use verbose mode when debugging:

curl -v -X GET "$API/api/users" \ -H "Authorization: Bearer $ACCESS_TOKEN"

9. Copy-paste daily sequence

API='http://localhost:5000' EMAIL='admin@example.com' PASS='StrongPassword123!' curl -s -X POST "$API/api/auth/bootstrap" \ -H 'Content-Type: application/json' \ -d '{"email":"admin@example.com","password":"StrongPassword123!","name":"System Admin"}' ACCESS_TOKEN=$(curl -s -X POST "$API/api/auth/login" \ -H 'Content-Type: application/json' \ -d "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}" | jq -r '.accessToken') curl -s "$API/api/auth/me" -H "Authorization: Bearer $ACCESS_TOKEN" curl -s -X POST "$API/api/users" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{"name":"Max","email":"max@example.com"}' curl -s "$API/api/users" -H "Authorization: Bearer $ACCESS_TOKEN"

10. Windows PowerShell equivalent commands

PowerShell ships built-in JSON parsing so you don’t need jq. Use Invoke-RestMethod (aliased as irm) or Invoke-WebRequest (aliased as iwr).

Setup variables:

$API = 'http://localhost:5000' $EMAIL = 'admin@example.com' $PASS = 'StrongPassword123!'

Bootstrap first admin:

Invoke-RestMethod -Method Post "$API/api/auth/bootstrap" ` -ContentType 'application/json' ` -Body '{"email":"admin@example.com","password":"StrongPassword123!","name":"System Admin"}'

Login and capture access token (no jq needed):

$login = Invoke-RestMethod -Method Post "$API/api/auth/login" ` -ContentType 'application/json' ` -Body (ConvertTo-Json @{ email = $EMAIL; password = $PASS }) $TOKEN = $login.accessToken Write-Host $TOKEN

Request a protected route:

Invoke-RestMethod "$API/api/auth/me" ` -Headers @{ Authorization = "Bearer $TOKEN" }

Refresh token (cookie is stored automatically by the session):

$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession Invoke-RestMethod -Method Post "$API/api/auth/login" ` -ContentType 'application/json' ` -Body (ConvertTo-Json @{ email = $EMAIL; password = $PASS }) ` -SessionVariable session | Out-Null $refresh = Invoke-RestMethod -Method Post "$API/api/auth/refresh" ` -WebSession $session $TOKEN = $refresh.accessToken

Logout:

Invoke-RestMethod -Method Post "$API/api/auth/logout" ` -WebSession $session

Full CRUD against users:

$headers = @{ Authorization = "Bearer $TOKEN" } # Create Invoke-RestMethod -Method Post "$API/api/users" ` -ContentType 'application/json' ` -Headers $headers ` -Body (ConvertTo-Json @{ name = 'Nnamdi'; email = 'nnamdi@example.com' }) # List Invoke-RestMethod "$API/api/users" -Headers $headers # Get one Invoke-RestMethod "$API/api/users/1" -Headers $headers # Update Invoke-RestMethod -Method Patch "$API/api/users/1" ` -ContentType 'application/json' ` -Headers $headers ` -Body (ConvertTo-Json @{ name = 'Nnamdi Okafor' }) # Delete Invoke-RestMethod -Method Delete "$API/api/users/1" -Headers $headers

Verbose debugging (equivalent to curl -v):

Invoke-WebRequest "$API/api/users" ` -Headers @{ Authorization = "Bearer $TOKEN" } ` -Verbose

Copy-paste daily sequence:

$API = 'http://localhost:5000' $EMAIL = 'admin@example.com' $PASS = 'StrongPassword123!' # Bootstrap (once) Invoke-RestMethod -Method Post "$API/api/auth/bootstrap" ` -ContentType 'application/json' ` -Body '{"email":"admin@example.com","password":"StrongPassword123!","name":"System Admin"}' # Login $TOKEN = (Invoke-RestMethod -Method Post "$API/api/auth/login" ` -ContentType 'application/json' ` -Body (ConvertTo-Json @{ email = $EMAIL; password = $PASS })).accessToken # Me Invoke-RestMethod "$API/api/auth/me" -Headers @{ Authorization = "Bearer $TOKEN" } # Create user Invoke-RestMethod -Method Post "$API/api/users" ` -ContentType 'application/json' ` -Headers @{ Authorization = "Bearer $TOKEN" } ` -Body (ConvertTo-Json @{ name = 'Max'; email = 'max@example.com' }) # List users Invoke-RestMethod "$API/api/users" -Headers @{ Authorization = "Bearer $TOKEN" }