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:
-Xor--request: HTTP method (GET,POST,PATCH,DELETE)-Hor--header: request headers-dor--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/bootstrapPOST /api/auth/loginGET /api/auth/mePOST /api/auth/refreshPOST /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"4. JWT refresh/logout with cookie jar
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.txtLogout and clear server-side refresh state:
curl -i -X POST "$API/api/auth/logout" \
-b cookies.txt5. Express + PostgreSQL daily CRUD examples
Assume a users table in PostgreSQL and these API routes:
GET /api/usersGET /api/users/:idPOST /api/usersPATCH /api/users/:idDELETE /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 $TOKENRequest 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.accessTokenLogout:
Invoke-RestMethod -Method Post "$API/api/auth/logout" `
-WebSession $sessionFull 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 $headersVerbose debugging (equivalent to curl -v):
Invoke-WebRequest "$API/api/users" `
-Headers @{ Authorization = "Bearer $TOKEN" } `
-VerboseCopy-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" }