Cloudflare Commands
Overview
The netapi cloudflare command group provides CLI access to Cloudflare API for:
-
Zone management
-
Cache purging
-
DNS record management
-
Pages project deployments
-
Access (Zero Trust) applications and policies
Prerequisites
Load secrets before using Cloudflare commands:
dsource d000 dev/app
Required environment variables:
| Variable | Description |
|---|---|
|
Cloudflare API token with appropriate permissions |
|
Cloudflare account ID (auto-detected from zones if not set) |
API Token Permissions
Create a token at dash.cloudflare.com/profile/api-tokens with:
| Permission | Required For |
|---|---|
Zone:Zone:Read |
|
Zone:Cache Purge:Edit |
|
Zone:DNS:Edit |
|
Account:Cloudflare Pages:Read |
|
Account:Cloudflare Pages:Edit |
|
Account:Access: Apps and Policies:Edit |
|
Recommended Token Strategy
For security, use separate tokens with minimal permissions:
| Token Name | Permissions | Use Case |
|---|---|---|
|
Pages:Read, Access:Edit, Cache Purge, Zone:Read |
Local CLI operations, IP-filtered to your machine |
|
Zone:Zone:Read, Zone:DNS:Edit |
DNS management, IP-filtered |
|
Account:Cloudflare Pages:Edit |
GitHub Actions / GitLab CI deployments, no IP filter |
Cache Commands
purge
Purge Cloudflare cache for a domain. Essential after deploying new assets.
# Purge all cache (with confirmation)
netapi cloudflare purge domusdigitalis.dev
# Skip confirmation
netapi cloudflare purge domusdigitalis.dev -y
# Purge specific URL
netapi cloudflare purge domusdigitalis.dev --url https://docs.domusdigitalis.dev/_/css/site.css
Options:
| Option | Required | Description |
|---|---|---|
|
Yes |
Domain name (e.g., domusdigitalis.dev) |
|
No |
Specific URL to purge (purges all if not specified) |
|
No |
Skip confirmation prompt |
DNS Commands
Manage DNS records for your zones.
dns list
List DNS records for a domain:
# List all records
netapi cloudflare dns list domusdigitalis.dev
# Filter by record type
netapi cloudflare dns list domusdigitalis.dev -t CNAME
netapi cloudflare dns list domusdigitalis.dev -t A
netapi cloudflare dns list domusdigitalis.dev -t TXT
dns add
Add a DNS record:
# Add A record
netapi cloudflare dns add domusdigitalis.dev -t A -n test -c 10.50.1.100
# Add CNAME record with proxy enabled
netapi cloudflare dns add domusdigitalis.dev -t CNAME -n www -c domusdigitalis.dev -p
# Add TXT record
netapi cloudflare dns add domusdigitalis.dev -t TXT -n _dmarc -c "v=DMARC1; p=none"
# Add MX record with priority
netapi cloudflare dns add domusdigitalis.dev -t MX -n @ -c mail.example.com --priority 10
Options:
| Option | Required | Description |
|---|---|---|
|
Yes |
Domain name |
|
Yes |
Record type (A, AAAA, CNAME, TXT, MX) |
|
Yes |
Record name (e.g., www, @, subdomain) |
|
Yes |
Record content (IP, hostname, text) |
|
No |
TTL in seconds (1 = auto, default) |
|
No |
Enable Cloudflare proxy |
|
No |
MX record priority |
Pages Commands
Manage Cloudflare Pages projects and deployments. Supports full project lifecycle: create, configure, deploy, and add custom domains.
pages list
List all Cloudflare Pages projects:
netapi cloudflare pages list
Cloudflare Pages Projects
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Name ┃ Subdomain ┃ Domains ┃
┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ domus-docs │ domus-docs.pages.dev │ domus-docs.pages.dev, docs.domusdigitalis.dev │
│ architectus-docs │ architectus-docs.pages.dev │ architectus-docs.pages.dev, docs.architectus.dev │
└────────────────────┴────────────────────────────┴───────────────────────────────────────────────┘
pages get
Get details for a specific Pages project:
netapi cloudflare pages get architectus-docs
Project: architectus-docs
Subdomain: architectus-docs.pages.dev
Created: 2026-02-17T23:38:42
Build Config:
Command: N/A
Output: build/site
Root: /
Domains:
- architectus-docs.pages.dev
- docs.architectus.dev
pages create
Create a new Pages project (direct upload, no git integration):
# Basic project
netapi cloudflare pages create my-project --output "dist"
# Antora documentation site
netapi cloudflare pages create architectus-docs --output "build/site"
# With build command (for CI reference)
netapi cloudflare pages create my-site \
--build "npm ci && npm run build" \
--output "build/site" \
--branch main
Options:
| Option | Required | Description |
|---|---|---|
|
Yes |
Project name (becomes subdomain) |
|
No |
Build output directory |
|
No |
Build command (reference only for direct upload) |
|
No |
Root directory (default: |
|
No |
Production branch (default: |
|
For git-connected projects (Cloudflare builds from repo), use the dashboard or Terraform. |
pages update
Update a Pages project configuration:
# Update output directory
netapi cloudflare pages update architectus-docs --output "build/site"
# Update build command
netapi cloudflare pages update my-site --build "npm run build:prod"
# Update multiple settings
netapi cloudflare pages update my-site \
--build "npm ci && npm run build" \
--output "dist" \
--root "/packages/web"
pages delete
Delete a Pages project:
# With confirmation prompt
netapi cloudflare pages delete my-old-project
# Skip confirmation
netapi cloudflare pages delete my-old-project -y
|
This permanently deletes the project and all deployments. Custom domains will stop working immediately. |
pages domain
Add a custom domain to a Pages project:
netapi cloudflare pages domain architectus-docs docs.architectus.dev
Added domain: docs.architectus.dev
Project: architectus-docs
Status: initializing
Note: Configure DNS CNAME record pointing to:
architectus-docs.pages.dev
After adding the domain, create the DNS record:
# If using separate DNS token
CF_API_TOKEN=$CF_DNS_TOKEN netapi cloudflare dns add architectus.dev \
-t CNAME -n docs -c architectus-docs.pages.dev --proxied
pages deployments
List recent deployments for a Pages project:
# Show last 5 deployments (default)
netapi cloudflare pages deployments domus-docs
# Show last 10 deployments
netapi cloudflare pages deployments domus-docs -n 10
# JSON output for scripting
netapi cloudflare pages deployments domus-docs --json
Deployments: domus-docs
┏━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ ID ┃ Status ┃ Environment ┃ Branch ┃ URL ┃ Created ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ ff16df47-aa6 │ success │ production │ main │ https://ff16df47.domus-docs… │ 2026-02-22T00:04:02 │
│ c64c5822-056 │ active │ production │ main │ https://c64c5822.domus-docs… │ 2026-02-22T00:03:56 │
│ d3febab0-78c │ failure │ production │ main │ https://d3febab0.domus-docs… │ 2026-02-21T23:36:16 │
└──────────────┴───────────┴─────────────┴────────┴──────────────────────────────┴─────────────────────┘
Deployment Status Values
| Status | Stage | Description |
|---|---|---|
|
|
Deployment completed successfully. Site is live. |
|
|
Deployment is currently in progress. |
|
varies |
Deployment failed. Check logs for details. |
|
|
Deployment queued but not yet started. |
|
varies |
Deployment was manually canceled. |
Monitor Deployment Progress
Watch deployment status in real-time:
# Watch latest deployment (updates every 5s)
watch -n 5 'netapi cloudflare pages deployments domus-docs -n 1'
# Or with jq for cleaner output
watch -n 5 'curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=1" \
| jq -r ".result[0] | \"\\(.id[:12]) \\(.latest_stage.status) \\(.latest_stage.name)\""'
pages deployment (single)
Get details for a specific deployment:
netapi cloudflare pages deployment domus-docs 8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
{
"id": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"project_name": "domus-docs",
"environment": "production",
"url": "https://8f3a2b1c.domus-docs.pages.dev",
"latest_stage": {
"name": "deploy",
"status": "success",
"started_on": "2026-02-13T07:29:45Z",
"ended_on": "2026-02-13T07:30:00Z"
},
"deployment_trigger": {
"type": "wrangler",
"metadata": {
"commit_hash": "7a235e0"
}
},
"stages": [
{"name": "queued", "status": "success"},
{"name": "initialize", "status": "success"},
{"name": "clone_repo", "status": "skipped"},
{"name": "build", "status": "skipped"},
{"name": "deploy", "status": "success"}
]
}
Checking Deployment Status (CI/CD)
Poll for deployment completion in automation scripts:
#!/bin/bash
# wait-for-deployment.sh - Wait for Cloudflare Pages deployment to complete
PROJECT="domus-docs"
MAX_WAIT=300 # 5 minutes
INTERVAL=10 # Check every 10 seconds
# Get latest deployment ID
DEPLOYMENT_ID=$(netapi cloudflare pages deployments "$PROJECT" -n 1 --json | jq -r '.[0].id')
echo "Waiting for deployment $DEPLOYMENT_ID..."
elapsed=0
while [ $elapsed -lt $MAX_WAIT ]; do
STATUS=$(netapi cloudflare pages deployment "$PROJECT" "$DEPLOYMENT_ID" --json | jq -r '.latest_stage.status')
case $STATUS in
success)
echo "Deployment successful!"
exit 0
;;
failure)
echo "Deployment failed!"
exit 1
;;
active|idle)
echo "Status: $STATUS (waiting...)"
sleep $INTERVAL
elapsed=$((elapsed + INTERVAL))
;;
*)
echo "Unknown status: $STATUS"
exit 2
;;
esac
done
echo "Timeout waiting for deployment"
exit 3
Direct API Commands (curl)
When netapi doesn’t support a feature, use the Cloudflare API directly.
List Deployments with Full Details
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=5" \
| jq '.result[] | {id, status: .latest_stage.status, stage: .latest_stage.name, created: .created_on}'
Get Single Deployment Status
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments/<deployment-id>" \
| jq '{status: .result.latest_stage.status, stage: .result.latest_stage.name}'
Get Build Logs for Failed Deployment
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments/<deployment-id>/history/logs" \
| jq -r '.result.data[].line' | tail -50
Troubleshooting Deployment Failures
Check deployment logs when status is failure:
# Get deployment details with logs
netapi cloudflare pages deployment domus-docs <deployment-id> --logs
| Error | Solution |
|---|---|
|
Check build command in Pages settings. Verify local build works. |
|
Individual files must be < 25MB. Split or compress assets. |
|
Too many deployments. Wait 1 minute between deploys. |
|
Verify |
Wrangler Pages Deployment
For direct deployments to Cloudflare Pages (bypassing the dashboard), use wrangler:
List Projects
wrangler pages project list
┌──────────────┬───────────────────────────────────────────────┬──────────────┬────────────────┐
│ Project Name │ Project Domains │ Git Provider │ Last Modified │
├──────────────┼───────────────────────────────────────────────┼──────────────┼────────────────┤
│ domus-docs │ domus-docs.pages.dev, docs.domusdigitalis.dev │ Yes │ 5 minutes ago │
├──────────────┼───────────────────────────────────────────────┼──────────────┼────────────────┤
│ domus-ui │ domus-ui.pages.dev, ui.domusdigitalis.dev │ Yes │ 10 minutes ago │
└──────────────┴───────────────────────────────────────────────┴──────────────┴────────────────┘
Deploy to Pages
Deploy a local directory to Cloudflare Pages:
# Deploy Antora site
wrangler pages deploy build/site --project-name=domus-docs
# Deploy Antora UI bundle
wrangler pages deploy build --project-name=domus-ui
⛅️ wrangler 4.64.0
───────────────────
Uploading... (794/794)
✨ Success! Uploaded 567 files (227 already uploaded) (4.29 sec)
🌎 Deploying...
✨ Deployment complete! Take a peek over at https://a5568b3d.domus-docs.pages.dev
|
The preview URL (e.g., |
Full Deploy Workflow
Build and deploy without touching the dashboard:
# 1. Build the Antora site
cd ~/atelier/_bibliotheca/domus-docs
make local
# 2. Deploy to Pages
wrangler pages deploy build/site --project-name=domus-docs
# 3. Purge CDN cache (optional but recommended)
netapi cloudflare purge domusdigitalis.dev -y
For the Antora UI bundle:
# 1. Build the UI bundle
cd ~/atelier/_bibliotheca/domus-antora-ui
npx gulp bundle
# 2. Deploy to Pages
wrangler pages deploy build --project-name=domus-ui
Access (Zero Trust) Commands
Manage Cloudflare Access applications and policies via CLI.
access apps
List Access applications:
netapi cloudflare access apps
┌────────────────────────────────────────────────────────────────────────────────────┐
│ Cloudflare Access Applications │
├──────────────────────┬───────────────────────────────────┬─────────────┬───────────┤
│ Name │ Domain │ Type │ ID │
├──────────────────────┼───────────────────────────────────┼─────────────┼───────────┤
│ domus-docs │ docs.domusdigitalis.dev │ self_hosted │ 328ba6e8… │
│ domus-docs-static │ docs.domusdigitalis.dev/_/* │ self_hosted │ ac2893db… │
│ antora-ui-bundle │ ui.domusdigitalis.dev │ self_hosted │ e9c4b01d… │
└──────────────────────┴───────────────────────────────────┴─────────────┴───────────┘
access policies
List policies for an Access application:
netapi cloudflare access policies 328ba6e8-bf0d-4490-8f66-8837acaaaa82
access bypass-static
One-command solution for Antora sites behind Access. Creates a bypass for static assets (/_/*):
netapi cloudflare access bypass-static docs.domusdigitalis.dev
This command:
-
Creates a new Access application for
docs.domusdigitalis.dev/_/* -
Adds a bypass policy allowing everyone
-
Static assets (CSS, JS, fonts) now load without authentication
netapi cloudflare access bypass-static docs.domusdigitalis.dev
# Output:
# Creating Access app: docs-static
# Domain pattern: docs.domusdigitalis.dev/_/*
# Created app: ac2893db-f5c2-40dd-b2e1-08d1a1f047c2
# Created bypass policy: fae81e60-b364-4aaa-b6bc-197e660e5b6e
# Success! Static assets will now load without authentication.
# Verify with: curl -sI https://docs.domusdigitalis.dev/_/css/site.css | head -1
Options:
| Option | Required | Description |
|---|---|---|
|
Yes |
Domain to bypass (e.g., docs.example.com) |
|
No |
Path pattern (default: |
|
No |
Application name (default: |
access create-app
Create an Access application:
netapi cloudflare access create-app -n "My App" -d app.domusdigitalis.dev
# With custom session duration
netapi cloudflare access create-app -n "My App" -d app.domusdigitalis.dev -s 12h
Common Workflows
Deploy and Purge Cache
After deploying a new Antora site build:
# 1. Trigger Pages deployment (via git push)
git push
# 2. Wait for deployment to complete
netapi cloudflare pages deployments domus-docs -n 1
# 3. Purge CDN cache
netapi cloudflare purge domusdigitalis.dev -y
Fix Antora Site Behind Access
If your Antora site shows a white page because CSS/JS returns 302 redirects:
# 1. Verify the issue
curl -sI "https://docs.domusdigitalis.dev/_/css/site.css" | head -1
# If HTTP/2 302 -> Access is blocking
# 2. Create static assets bypass
netapi cloudflare access bypass-static docs.domusdigitalis.dev
# 3. Verify fix
curl -sI "https://docs.domusdigitalis.dev/_/css/site.css" | head -1
# Should show HTTP/2 200
# 4. Clear browser cache (Ctrl+Shift+R)
Validation
Quick validation of all Cloudflare commands:
# Zone commands
netapi cloudflare zones
netapi cloudflare zone domusdigitalis.dev
# DNS commands
netapi cloudflare dns list domusdigitalis.dev
# Pages commands
netapi cloudflare pages list
netapi cloudflare pages deployments domus-docs
# Access commands
netapi cloudflare access apps
jq Patterns for Cloudflare API
Advanced jq patterns for parsing Cloudflare API responses. All examples assume credentials loaded:
eval "$(dsource d000 dev/app)"
Deployment Status Queries
Latest Deployment Status (One-liner)
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=1" \
| jq -r '.result[0] | "\(.id[:12]) \(.latest_stage.status) \(.latest_stage.name)"'
ff16df47-aa6 success deploy
Deployment with Timing Info
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=1" \
| jq '.result[0] | {
id: .id[:12],
status: .latest_stage.status,
stage: .latest_stage.name,
started: .latest_stage.started_on,
ended: .latest_stage.ended_on,
duration: (if .latest_stage.ended_on and .latest_stage.started_on then
(((.latest_stage.ended_on | fromdateiso8601) - (.latest_stage.started_on | fromdateiso8601)) | tostring) + "s"
else "in progress" end)
}'
{
"id": "ff16df47-aa6",
"status": "success",
"stage": "deploy",
"started": "2026-02-22T00:03:45Z",
"ended": "2026-02-22T00:04:02Z",
"duration": "17s"
}
All Stages with Status
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=1" \
| jq -r '.result[0].stages[] | "\(.name): \(.status)"'
queued: success initialize: success clone_repo: skipped build: skipped deploy: success
Find Failed Deployments
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=20" \
| jq -r '.result[] | select(.latest_stage.status == "failure") | "\(.id[:12]) \(.created_on) \(.latest_stage.name)"'
Deployments in Last 24 Hours
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=50" \
| jq --arg since "$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
'[.result[] | select(.created_on > $since)] | length as $count |
{total: $count, success: [.[] | select(.latest_stage.status == "success")] | length,
failure: [.[] | select(.latest_stage.status == "failure")] | length}'
{
"total": 8,
"success": 7,
"failure": 1
}
DNS Record Queries
List Records as Table
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
| jq -r '.result[] | [.type, .name, .content[:40], (if .proxied then "proxied" else "dns-only" end)] | @tsv' \
| column -t
Access Application Queries
Zone Analytics
Requests by Status Code (Last 24h)
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/analytics/dashboard?since=-1440" \
| jq '.result.totals.requests.http_status | to_entries | sort_by(-.value) | .[:10] | .[] | "\(.key): \(.value)"'
Cache Hit Ratio
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/analytics/dashboard?since=-1440" \
| jq '.result.totals | {
total: .requests.all,
cached: .requests.cached,
uncached: .requests.uncached,
hit_ratio: ((.requests.cached / .requests.all * 100) | floor | tostring + "%")
}'
Utility Patterns
Get Zone ID by Domain Name
CF_ZONE_ID=$(curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones?name=domusdigitalis.dev" \
| jq -r '.result[0].id')
Get Account ID from Token
CF_ACCOUNT_ID=$(curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts" \
| jq -r '.result[0].id')
Conditional Logic
Exit Code Based on Status
# Returns exit code 0 if success, 1 otherwise
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=1" \
| jq -e '.result[0].latest_stage.status == "success"' > /dev/null
Wait for Deployment (Script)
#!/bin/bash
# wait-deploy.sh - Wait for Cloudflare Pages deployment
PROJECT="${1:-domus-docs}"
TIMEOUT="${2:-300}"
INTERVAL=10
echo "Waiting for $PROJECT deployment..."
elapsed=0
while [ $elapsed -lt $TIMEOUT ]; do
STATUS=$(curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/$PROJECT/deployments?per_page=1" \
| jq -r '.result[0].latest_stage.status')
case $STATUS in
success) echo "✓ Deployment successful!"; exit 0 ;;
failure) echo "✗ Deployment failed!"; exit 1 ;;
*) printf "\r[%3ds] Status: %-10s" $elapsed "$STATUS" ;;
esac
sleep $INTERVAL
elapsed=$((elapsed + INTERVAL))
done
echo "✗ Timeout after ${TIMEOUT}s"
exit 2
Deployment Status with Emoji
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=5" \
| jq -r '.result[] | "\(if .latest_stage.status == "success" then "✓" elif .latest_stage.status == "failure" then "✗" else "◐" end) \(.id[:12]) \(.latest_stage.status) \(.created_on[:16])"'
✓ ff16df47-aa6 success 2026-02-22T00:04 ✓ c64c5822-056 success 2026-02-22T00:03 ✗ d3febab0-78c failure 2026-02-21T23:36 ✓ 2e7b1330-a8f success 2026-02-21T21:40 ✓ 8424dae3-46e success 2026-02-21T21:14
Transform to Other Formats
CSV Export
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=20" \
| jq -r '["id","status","stage","created"], (.result[] | [.id[:12], .latest_stage.status, .latest_stage.name, .created_on]) | @csv'
Markdown Table
curl -s -H "Authorization: Bearer $CF_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/pages/projects/domus-docs/deployments?per_page=5" \
| jq -r '["| ID | Status | Stage | Created |", "|---|---|---|---|"], (.result[] | "| \(.id[:12]) | \(.latest_stage.status) | \(.latest_stage.name) | \(.created_on[:16]) |") | .[]'