返回 Skills
jezweb/claude-skills· MIT 内容可用

cloudflare-api

Hit the Cloudflare REST API directly for operations that wrangler and MCP can't handle well. Bulk DNS, custom hostnames, email routing, cache purge, WAF rules, redirect rules, zone settings, Worker routes, D1 cross-database queries, R2 bulk operations, KV bulk read/write, Vectorize queries, Queues, and fleet-wide resource audits. Produces curl commands or scripts. Triggers: 'cloudflare api', 'bulk dns', 'custom hostname', 'email routing', 'cache purge', 'waf rule', 'd1 query', 'r2 bucket', 'kv bulk', 'vectorize query', 'audit resources', 'fleet operation'.

安装

与 skills.sh 相同的 Command / Prompt 安装方式


name: cloudflare-api description: "Hit the Cloudflare REST API directly for operations that wrangler and MCP can't handle well. Bulk DNS, custom hostnames, email routing, cache purge, WAF rules, redirect rules, zone settings, Worker routes, D1 cross-database queries, R2 bulk operations, KV bulk read/write, Vectorize queries, Queues, and fleet-wide resource audits. Produces curl commands or scripts. Triggers: 'cloudflare api', 'bulk dns', 'custom hostname', 'email routing', 'cache purge', 'waf rule', 'd1 query', 'r2 bucket', 'kv bulk', 'vectorize query', 'audit resources', 'fleet operation'." compatibility: claude-code-only allowed-tools:

  • Read
  • Write
  • Edit
  • Bash
  • Glob
  • Grep

Cloudflare API

Hit the Cloudflare REST API directly when wrangler CLI or MCP servers aren't the right tool. For bulk operations, fleet-wide changes, and features that wrangler doesn't expose.

When to Use This Instead of Wrangler or MCP

Use caseWranglerMCPThis skill
Deploy a WorkerYesYesNo
Create a D1 databaseYesYesNo
Bulk update 50 DNS recordsSlow (one at a time)Slow (one tool call each)Yes — batch script
Custom hostnames for white-labelNoPartialYes
Email routing rulesNoPartialYes
WAF/firewall rulesNoYes but verboseYes — direct API
Redirect rules in bulkNoOne at a timeYes — batch script
Zone settings across 20 zonesNo20 separate callsYes — fleet script
Cache purge by tag/prefixNoYesYes (when scripting)
Worker route managementLimitedYesYes (when bulk)
Analytics/logs queryNoPartialYes — GraphQL
D1 query/export across databasesOne DB at a timeOne DB at a timeYes — cross-DB scripts
R2 bulk object operationsNoOne at a timeYes — S3 API + batch
KV bulk read/write/deleteOne at a timeOne at a timeYes — bulk endpoints
Vectorize query/deleteNoVia Worker onlyYes — direct API
Queue message injectionNoVia Worker onlyYes — direct API
Audit all resources in accountNoTediousYes — inventory script

Rule of thumb: Single operations → MCP or wrangler. Bulk/fleet/scripted → API directly.

Auth Setup

API Token (recommended)

Create a scoped token at: Dashboard → My Profile → API Tokens → Create Token

# Store it
export CLOUDFLARE_API_TOKEN="your-token-here"

# Test it
curl -s "https://api.cloudflare.com/client/v4/user/tokens/verify" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.success'

Token scopes: Always use minimal permissions. Common presets:

  • "Edit zone DNS" — for DNS operations
  • "Edit zone settings" — for zone config changes
  • "Edit Cloudflare Workers" — for Worker route management
  • "Read analytics" — for GraphQL analytics

Account and Zone IDs

# List your zones (find zone IDs)
curl -s "https://api.cloudflare.com/client/v4/zones?per_page=50" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {name, id}'

# Get zone ID by domain name
ZONE_ID=$(curl -s "https://api.cloudflare.com/client/v4/zones?name=example.com" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq -r '.result[0].id')

Store IDs in environment or a config file — don't hardcode them in scripts.

Workflows

Bulk DNS Operations

Add/update many records at once (e.g. migrating a domain, setting up a new client):

# Pattern: read records from a file, create in batch
while IFS=',' read -r type name content proxied; do
  curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"type\":\"$type\",\"name\":\"$name\",\"content\":\"$content\",\"proxied\":$proxied,\"ttl\":1}" \
    | jq '{name: .result.name, id: .result.id, success: .success}'
  sleep 0.25  # Rate limit: 1200 req/5min
done < dns-records.csv

Export all records from a zone (backup or migration):

curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?per_page=100" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq -r '.result[] | [.type, .name, .content, .proxied] | @csv' > dns-export.csv

Find and replace across records (e.g. IP migration):

OLD_IP="203.0.113.1"
NEW_IP="198.51.100.1"

# Find records pointing to old IP
RECORDS=$(curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?content=$OLD_IP" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq -r '.result[].id')

# Update each one
for RECORD_ID in $RECORDS; do
  curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "{\"content\":\"$NEW_IP\"}" | jq '.success'
done

Custom Hostnames (White-Label Client Domains)

For SaaS apps where clients use their own domain (e.g. app.clientdomain.com → your Worker):

# Create custom hostname
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hostname": "app.clientdomain.com",
    "ssl": {
      "method": "http",
      "type": "dv",
      "settings": {
        "min_tls_version": "1.2"
      }
    }
  }' | jq '{id: .result.id, status: .result.status, ssl_status: .result.ssl.status}'

# List custom hostnames
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames?per_page=50" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | {hostname, status, ssl_status: .ssl.status}'

# Check status (client needs to add CNAME)
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$HOSTNAME_ID" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result.status'

Client setup: They add a CNAME: app.clientdomain.com → your-worker.your-domain.com

Email Routing Rules

# Enable email routing on zone
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/enable" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

# Create a routing rule (forward info@ to a real address)
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/rules" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Forward info@",
    "enabled": true,
    "matchers": [{"type": "literal", "field": "to", "value": "info@example.com"}],
    "actions": [{"type": "forward", "value": ["real-inbox@gmail.com"]}]
  }' | jq '.success'

# Create catch-all rule
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/rules" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Catch-all",
    "enabled": true,
    "matchers": [{"type": "all"}],
    "actions": [{"type": "forward", "value": ["catchall@company.com"]}]
  }' | jq '.success'

# List rules
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/email/routing/rules" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {name, enabled, matchers, actions}'

Cache Purge

# Purge everything (nuclear option)
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"purge_everything": true}'

# Purge specific URLs
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"files": ["https://example.com/styles.css", "https://example.com/app.js"]}'

# Purge by cache tag (requires Enterprise or cache tag headers)
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tags": ["product-123", "homepage"]}'

# Purge by prefix
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"prefixes": ["https://example.com/images/"]}'

Redirect Rules (Bulk)

# Create a redirect rule
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_request_dynamic_redirect/entrypoint" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [
      {
        "expression": "(http.request.uri.path eq \"/old-page\")",
        "description": "Redirect old-page to new-page",
        "action": "redirect",
        "action_parameters": {
          "from_value": {
            "target_url": {"value": "https://example.com/new-page"},
            "status_code": 301
          }
        }
      }
    ]
  }'

For bulk redirects (301s from a CSV), generate the rules array programmatically:

import json, csv

rules = []
with open('redirects.csv') as f:
    for row in csv.reader(f):
        old_path, new_url = row
        rules.append({
            "expression": f'(http.request.uri.path eq "{old_path}")',
            "description": f"Redirect {old_path}",
            "action": "redirect",
            "action_parameters": {
                "from_value": {
                    "target_url": {"value": new_url},
                    "status_code": 301
                }
            }
        })
print(json.dumps({"rules": rules}, indent=2))

Zone Settings (Fleet-Wide)

Apply the same settings across multiple zones:

# Settings to apply
SETTINGS='{"value":"full"}'  # SSL mode: full (strict)

# Get all active zones
ZONES=$(curl -s "https://api.cloudflare.com/client/v4/zones?status=active&per_page=50" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq -r '.result[].id')

# Apply to each zone
for ZONE in $ZONES; do
  curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE/settings/ssl" \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d "$SETTINGS" | jq "{zone: .result.id, success: .success}"
  sleep 0.25
done

Common fleet settings:

  • ssl — "full" or "strict"
  • min_tls_version — "1.2"
  • always_use_https — "on"
  • security_level — "medium"
  • browser_cache_ttl — 14400

WAF / Firewall Rules

# Create a WAF custom rule (block by country)
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_request_firewall_custom/entrypoint" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [{
      "expression": "(ip.geoip.country in {\"RU\" \"CN\"})",
      "action": "block",
      "description": "Block traffic from RU and CN"
    }]
  }'

# Rate limiting rule
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_ratelimit/entrypoint" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [{
      "expression": "(http.request.uri.path contains \"/api/\")",
      "action": "block",
      "ratelimit": {
        "characteristics": ["ip.src"],
        "period": 60,
        "requests_per_period": 100
      },
      "description": "Rate limit API to 100 req/min per IP"
    }]
  }'

Worker Routes

# List routes
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result[] | {pattern, id}'

# Create route
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pattern": "api.example.com/*", "script": "my-worker"}'

# Delete route
curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes/$ROUTE_ID" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

Analytics (GraphQL)

# Worker analytics (requests, errors, CPU time)
curl -s -X POST "https://api.cloudflare.com/client/v4/graphql" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ viewer { zones(filter: {zoneTag: \"'$ZONE_ID'\"}) { httpRequests1dGroups(limit: 7, filter: {date_gt: \"2026-03-10\"}) { dimensions { date } sum { requests pageViews } } } } }"
  }' | jq '.data.viewer.zones[0].httpRequests1dGroups'

Rate Limits

EndpointLimit
Most API calls1200 requests / 5 minutes
DNS record operations1200 / 5 min (shared with above)
Cache purge1000 purge calls / day
Zone creation5 per minute

In scripts: Add sleep 0.25 between calls for sustained operations. Use p-limit or xargs -P 4 for controlled parallelism.

Script Generation

When the user describes what they need, generate a script in .jez/scripts/ that:

  • Reads API token from environment (never hardcode)
  • Handles pagination for list operations
  • Includes error checking (jq '.success' after each call)
  • Adds rate limit sleep between calls
  • Logs what it does
  • Supports --dry-run where possible

Prefer curl + jq for simple operations. Use Python for complex logic (pagination loops, error handling, CSV processing). Use TypeScript with the cloudflare npm package for type safety in larger scripts.

API Reference

Base URL: https://api.cloudflare.com/client/v4/

Full docs: https://developers.cloudflare.com/api/

The API follows a consistent pattern:

  • GET /zones — list
  • POST /zones — create
  • GET /zones/:id — read
  • PATCH /zones/:id — update
  • DELETE /zones/:id — delete
  • PUT /zones/:id/settings/:name — update setting

Every response has { success: bool, errors: [], messages: [], result: {} }.

Reference Files

WhenRead
D1, R2, KV, Workers, Vectorize, Queues API patternsreferences/developer-platform-api.md

附带文件

references/developer-platform-api.md
# Developer Platform API Patterns

REST API patterns for Cloudflare's developer platform services: D1, R2, KV, Workers, Vectorize, Queues, and Durable Objects. These complement what wrangler does — use the API for bulk operations, cross-database queries, automation scripts, and operations wrangler doesn't expose.

All endpoints use: `https://api.cloudflare.com/client/v4/accounts/{account_id}/...`

---

## D1 (SQL Database)

### List Databases

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/d1/database" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | {uuid, name, num_tables, file_size, version}'
```

### Query a Database

```bash
# Run SQL directly via API (useful for scripts, automation, debugging)
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/d1/database/$DB_ID/query" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sql": "SELECT * FROM users LIMIT 10"}' \
  | jq '.result[0].results'

# With parameters (prevents SQL injection)
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/d1/database/$DB_ID/query" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sql": "SELECT * FROM users WHERE email = ?1", "params": ["jez@example.com"]}' \
  | jq '.result[0].results'
```

### Raw SQL via API (Batch)

```bash
# Run multiple statements in one call
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/d1/database/$DB_ID/raw" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "sql": "INSERT INTO users (id, name, email) VALUES (?1, ?2, ?3); INSERT INTO users (id, name, email) VALUES (?4, ?5, ?6);",
    "params": ["id1", "Alice", "alice@example.com", "id2", "Bob", "bob@example.com"]
  }'
```

### Export/Backup a D1 Database

```bash
# Export as SQL dump
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/d1/database/$DB_ID/export" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"output_format": "file"}' \
  | jq '.result'

# Then poll for the export to complete and download
```

### Cross-Database Operations

Wrangler can only talk to one database at a time. The API lets you script across multiple:

```python
import json, urllib.request

def query_d1(db_id, sql, params=None):
    url = f"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/d1/database/{db_id}/query"
    payload = {"sql": sql}
    if params:
        payload["params"] = params
    req = urllib.request.Request(url, data=json.dumps(payload).encode(),
        headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"})
    return json.loads(urllib.request.urlopen(req).read())["result"][0]["results"]

# Query across multiple D1 databases
for db_name, db_id in databases.items():
    users = query_d1(db_id, "SELECT COUNT(*) as count FROM users")
    print(f"{db_name}: {users[0]['count']} users")
```

### D1 Gotchas via API

- Max 100KB per single SQL statement
- Max 1000 bound parameters per query
- `query` endpoint returns results; `raw` endpoint for DDL/DML without result sets
- Export is async — returns a bookmark to poll, not the dump directly

---

## R2 (Object Storage)

### List Buckets

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/r2/buckets" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result.buckets[] | {name, creation_date}'
```

### Create Bucket

```bash
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/r2/buckets" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-bucket", "locationHint": "apac"}'
```

### List Objects in a Bucket (S3 API)

R2 objects are managed via the S3-compatible API, not the Cloudflare API:

```bash
# Using AWS CLI with R2 credentials
aws s3api list-objects-v2 \
  --bucket my-bucket \
  --endpoint-url "https://$ACCOUNT_ID.r2.cloudflarestorage.com" \
  --max-keys 100 \
  | jq '.Contents[] | {Key, Size, LastModified}'
```

### Bulk Delete Objects

```bash
# Delete all objects matching a prefix
aws s3 rm "s3://my-bucket/uploads/2025/" \
  --endpoint-url "https://$ACCOUNT_ID.r2.cloudflarestorage.com" \
  --recursive
```

### R2 Usage Stats

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/r2/buckets/$BUCKET_NAME/usage" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result'
```

---

## KV (Key-Value Store)

### List Namespaces

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | {id, title}'
```

### Read/Write Values

```bash
# Write
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/values/my-key" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -d "my-value"

# Write with metadata and expiration
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/values/my-key" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: multipart/form-data" \
  -F "value=my-value" \
  -F 'metadata={"source": "api"}' \
  -F "expiration_ttl=3600"

# Read
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/values/my-key" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"

# Delete
curl -s -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/values/my-key" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

### List All Keys (with pagination)

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/keys?limit=1000" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | .name'
```

### Bulk Write (up to 10,000 pairs)

```bash
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/bulk" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {"key": "key1", "value": "value1"},
    {"key": "key2", "value": "value2", "expiration_ttl": 3600}
  ]'
```

### Bulk Delete

```bash
curl -s -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$NS_ID/bulk" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '["key1", "key2", "key3"]'
```

---

## Workers

### List Workers

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | {id, modified_on, usage_model}'
```

### Get Worker Details

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts/$WORKER_NAME" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result'
```

### Get Worker Settings (Bindings, Compatibility)

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts/$WORKER_NAME/settings" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result | {bindings, compatibility_date, compatibility_flags}'
```

### List All Worker Bindings Across Account

Useful for auditing what's connected to what:

```python
import json, urllib.request

url = f"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/workers/scripts"
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {TOKEN}"})
workers = json.loads(urllib.request.urlopen(req).read())["result"]

for w in workers:
    settings_url = f"{url}/{w['id']}/settings"
    req = urllib.request.Request(settings_url, headers={"Authorization": f"Bearer {TOKEN}"})
    settings = json.loads(urllib.request.urlopen(req).read())["result"]
    bindings = settings.get("bindings", [])
    if bindings:
        print(f"\n{w['id']}:")
        for b in bindings:
            print(f"  {b['type']}: {b.get('name', '')} → {b.get('namespace_id', b.get('database_id', b.get('bucket_name', '')))}")
```

### Worker Subdomain

```bash
# Get current subdomain
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/subdomain" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | jq '.result.subdomain'
```

---

## Vectorize

### List Indexes

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/vectorize/v2/indexes" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | {name, config}'
```

### Get Index Info

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/vectorize/v2/indexes/$INDEX_NAME" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result'
```

### Query Vectors

```bash
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/vectorize/v2/indexes/$INDEX_NAME/query" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "vector": [0.1, 0.2, ...],
    "topK": 10,
    "returnValues": false,
    "returnMetadata": "all",
    "filter": {"type": {"$eq": "client"}}
  }'
```

### Delete Vectors by ID

```bash
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/vectorize/v2/indexes/$INDEX_NAME/delete-by-ids" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["vec-1", "vec-2"]}'
```

### Vectorize Gotchas

- Metadata indexes must be created BEFORE inserting vectors (vectors inserted before are NOT retroactively indexed)
- Max 1000 vectors per upsert call
- Metadata filter values are case-sensitive

---

## Queues

### List Queues

```bash
curl -s "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/queues" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  | jq '.result[] | {queue_id, queue_name, producers_total_count, consumers_total_count}'
```

### Send Message to Queue

```bash
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/queues/$QUEUE_ID/messages" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"body": {"task": "process_image", "id": "123"}}'
```

### Bulk Send Messages

```bash
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/queues/$QUEUE_ID/messages/batch" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"body": {"task": "resize", "id": "1"}},
      {"body": {"task": "resize", "id": "2"}}
    ]
  }'
```

---

## Fleet Operations

### Audit All Resources Across Account

Generate a full inventory of what's deployed:

```python
import json, urllib.request

BASE = f"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}"
HEADERS = {"Authorization": f"Bearer {TOKEN}"}

def get(path):
    req = urllib.request.Request(f"{BASE}/{path}", headers=HEADERS)
    return json.loads(urllib.request.urlopen(req).read()).get("result", [])

print("=== Workers ===")
for w in get("workers/scripts"):
    print(f"  {w['id']}")

print("\n=== D1 Databases ===")
for db in get("d1/database"):
    print(f"  {db['name']} ({db['uuid'][:8]}...)")

print("\n=== R2 Buckets ===")
for b in get("r2/buckets").get("buckets", []):
    print(f"  {b['name']}")

print("\n=== KV Namespaces ===")
for ns in get("storage/kv/namespaces"):
    print(f"  {ns['title']} ({ns['id'][:8]}...)")

print("\n=== Vectorize Indexes ===")
for idx in get("vectorize/v2/indexes"):
    print(f"  {idx['name']}")

print("\n=== Queues ===")
for q in get("queues"):
    print(f"  {q['queue_name']}")
```

### Compare Resources Across Two Accounts

Useful when migrating between Jezweb Team and Jez Personal accounts:

```python
accounts = {
    "team": "YOUR_TEAM_ACCOUNT_ID",
    "personal": "YOUR_PERSONAL_ACCOUNT_ID",
}

for name, acct_id in accounts.items():
    workers = get_for_account(acct_id, "workers/scripts")
    d1s = get_for_account(acct_id, "d1/database")
    print(f"\n{name}: {len(workers)} workers, {len(d1s)} D1 databases")
```
    cloudflare-api | Prompt Minder