DEV Community

Cover image for How to Use Cloudflare APIs?
Preecha
Preecha

Posted on

How to Use Cloudflare APIs?

TL;DR

Cloudflare APIs let you manage DNS, zones, Workers, security, and analytics programmatically. Authenticate with API tokens (recommended) or global keys, call api.cloudflare.com/client/v4, and handle rate limits gracefully. For testing, use Apidog to validate DNS changes, test Worker deployments, and automate configuration across environments.

Try Apidog today

Introduction

Cloudflare sits in front of millions of websites and provides DNS, CDN, DDoS protection, WAF, Workers serverless functions, and more. The dashboard is useful for small setups, but production environments need repeatable automation.

The Cloudflare API exposes the same core configuration areas programmatically. You can create zones, update DNS records, configure page rules, deploy Workers, manage SSL settings, and pull analytics.

Common API use cases include:

  • Infrastructure as code with Terraform or Pulumi
  • CI/CD pipeline integration
  • Multi-zone management
  • Automated DNS updates
  • Worker deployments

Apidog can help you test API calls, validate responses, and document your integration. Save zone configurations as reusable requests and share them with your team.

By the end of this guide, you will be able to:

  • Authenticate with Cloudflare API tokens
  • Manage zones and DNS records
  • Deploy and manage Workers
  • Configure security settings
  • Pull analytics and logs

Authentication

Cloudflare supports two authentication methods. Prefer API tokens over global API keys.

Method 1: API tokens (recommended)

API tokens are scoped to specific permissions. If a token is compromised, the impact is limited to the permissions and resources assigned to it.

Create a token:

  1. Open Cloudflare Dashboard → My Profile → API Tokens.
  2. Select Create Token.
  3. Choose a template, such as DNS editing or Workers deployment, or create a custom token.
  4. Scope the token to specific zones or accounts where possible.
  5. Copy the token and store it securely.

Verify a token before using it in automation:

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Method 2: Global API key (not recommended)

A global API key has full account access. Avoid using it in scripts, CI/CD pipelines, or shared environments.

curl -X GET "https://api.cloudflare.com/client/v4/user" \
  -H "X-Auth-Email: your-email@example.com" \
  -H "X-Auth-Key: YOUR_GLOBAL_API_KEY"
Enter fullscreen mode Exit fullscreen mode

Response format

Cloudflare API responses use this structure:

{
  "result": {},
  "success": true,
  "errors": [],
  "messages": []
}
Enter fullscreen mode Exit fullscreen mode

Check success and errors before using result in your automation.

Zone management

A Cloudflare zone represents a domain managed by Cloudflare.

List zones

Use this request to find zone IDs and confirm token access:

curl -X GET "https://api.cloudflare.com/client/v4/zones" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Example response:

{
  "result": [
    {
      "id": "023e105f4ecef8ad9ca31a8372d0c353",
      "name": "example.com",
      "status": "active",
      "paused": false,
      "type": "full",
      "development_mode": 0,
      "name_servers": [
        "ns1.cloudflare.com",
        "ns2.cloudflare.com"
      ],
      "original_name_servers": [
        "ns1.example.com"
      ],
      "original_registrar": null
    }
  ],
  "success": true
}
Enter fullscreen mode Exit fullscreen mode

Save the id value as ZONE_ID for subsequent requests.

Create a zone

Create a zone by providing the domain and Cloudflare account ID:

curl -X POST "https://api.cloudflare.com/client/v4/zones" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "newdomain.com",
    "account": {
      "id": "ACCOUNT_ID"
    },
    "type": "full"
  }'
Enter fullscreen mode Exit fullscreen mode

Get zone details

Retrieve a zone directly when you already know its ID:

curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

DNS record management

DNS records map hostnames to IP addresses and services.

List DNS records

Start by listing records so you can identify the RECORD_ID needed for updates and deletes:

curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Create a DNS record

Create a proxied A record for www.example.com:

curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "A",
    "name": "www",
    "content": "192.0.2.1",
    "ttl": 3600,
    "proxied": true
  }'
Enter fullscreen mode Exit fullscreen mode

Common DNS record types:

  • A — IPv4 address
  • AAAA — IPv6 address
  • CNAME — Alias to another domain
  • MX — Mail server
  • TXT — Text records such as SPF, DKIM, and domain verification
  • NS — Name server

Update a DNS record

Use PUT with the existing record ID to replace a record configuration:

curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/RECORD_ID" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "A",
    "name": "www",
    "content": "192.0.2.2",
    "ttl": 3600,
    "proxied": true
  }'
Enter fullscreen mode Exit fullscreen mode

Delete a DNS record

Delete a record only after confirming its ID:

curl -X DELETE "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/RECORD_ID" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Cloudflare Workers

Workers run JavaScript at the edge, close to users.

List Workers

List scripts deployed in an account:

curl -X GET "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/workers/scripts" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Upload a Worker

Upload a Worker script from a local worker.js file:

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/workers/scripts/my-worker" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/javascript" \
  --data-binary @worker.js
Enter fullscreen mode Exit fullscreen mode

Example worker.js:

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url)

    if (url.pathname === "/api/hello") {
      return new Response(JSON.stringify({ message: "Hello from the edge!" }), {
        headers: { "Content-Type": "application/json" }
      })
    }

    return fetch(request)
  }
}
Enter fullscreen mode Exit fullscreen mode

Bind a route

Attach the Worker to a route in a zone:

curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/workers/routes" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "pattern": "example.com/api/*",
    "script": "my-worker"
  }'
Enter fullscreen mode Exit fullscreen mode

Create a Worker KV namespace

Create a KV namespace for data accessible from Workers:

curl -X POST "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/storage/kv/namespaces" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "my-kv-namespace"
  }'
Enter fullscreen mode Exit fullscreen mode

Security and WAF

Use the API to apply security and caching configuration consistently across zones.

Create a page rule

This page rule enables flexible SSL and aggressive caching for matching URLs:

curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/pagerules" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "targets": [
      {
        "target": "url",
        "constraint": {
          "operator": "matches",
          "value": "example.com/*"
        }
      }
    ],
    "actions": [
      {
        "id": "ssl",
        "value": "flexible"
      },
      {
        "id": "cache_level",
        "value": "aggressive"
      }
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

Create a firewall rule

This example blocks requests from China:

curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/firewall/rules" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "expression": "ip.geoip.country eq \"CN\"",
      "paused": false
    },
    "action": "block",
    "description": "Block traffic from China"
  }'
Enter fullscreen mode Exit fullscreen mode

Create a rate limit

This rule limits POST requests to /api/*:

curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/rate_limits" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "disabled": false,
    "description": "Rate limit API endpoints",
    "match": {
      "request": {
        "methods": ["POST"],
        "url_pattern": "*/api/*"
      }
    },
    "threshold": 100,
    "period": 60,
    "action": {
      "mode": "ban",
      "timeout": 600
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Analytics and logs

Retrieve zone analytics

Fetch dashboard analytics for the previous 24 hours:

curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/analytics/dashboard?since=-1440&continuous=true" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Example response:

{
  "result": {
    "totals": {
      "requests": {
        "all": 1000000,
        "cached": 800000,
        "uncached": 200000
      },
      "bandwidth": {
        "all": 50000000000,
        "cached": 40000000000
      },
      "threats": {
        "all": 5000
      },
      "pageviews": {
        "all": 250000
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Enable zone logs with Logpush

Configure Logpush to send HTTP request logs to storage:

curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/logpush/jobs" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Logpush Job",
    "destination_conf": "s3://my-bucket/logs?region=us-east-1",
    "dataset": "http_requests",
    "logpull_options": "fields=ClientIP,ClientRequestPath,EdgeResponseStatus&timestamps=rfc3339"
  }'
Enter fullscreen mode Exit fullscreen mode

Testing with Apidog

Cloudflare changes can affect production traffic. Test requests, permissions, and response handling before applying configuration changes.

Image

1. Configure an environment

Create an environment and keep IDs and tokens out of individual requests:

CLOUDFLARE_API_TOKEN: your_token
CLOUDFLARE_ACCOUNT_ID: abc123
ZONE_ID: xyz789
BASE_URL: https://api.cloudflare.com/client/v4
Enter fullscreen mode Exit fullscreen mode

Use variables in requests:

{{BASE_URL}}/zones/{{ZONE_ID}}/dns_records
Enter fullscreen mode Exit fullscreen mode

Set the authorization header:

Authorization: Bearer {{CLOUDFLARE_API_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

2. Validate API responses

Add tests to ensure Cloudflare returns a successful response and no errors:

pm.test("Request was successful", () => {
  const response = pm.response.json()
  pm.expect(response.success).to.be.true
  pm.expect(response.errors).to.be.empty
})
Enter fullscreen mode Exit fullscreen mode

For a DNS record creation request, verify the properties your deployment expects:

pm.test("DNS record created correctly", () => {
  const response = pm.response.json()

  pm.expect(response.result.type).to.eql("A")
  pm.expect(response.result.name).to.eql("www")
  pm.expect(response.result.proxied).to.be.true
})
Enter fullscreen mode Exit fullscreen mode

3. Test Worker deployments

Save Worker scripts as files in Apidog and test upload responses:

pm.test("Worker uploaded", () => {
  const response = pm.response.json()
  pm.expect(response.result.id).to.eql("my-worker")
})
Enter fullscreen mode Exit fullscreen mode

Common errors and fixes

403 Forbidden

Cause: The token does not have the required permission.

Fix: Review token permissions in the Cloudflare dashboard. DNS edits need Zone:DNS:Edit. Workers need Account:Workers:Edit.

1003: Invalid or missing zone

Cause: The zone ID does not exist, or the token cannot access it.

Fix: Verify the zone ID in the request URL and confirm that the token scope includes the zone.

81057: Record already exists

Cause: A DNS record with the same name and type already exists.

Fix: Use PUT to update the existing record, or delete the record before creating a replacement.

Rate limit exceeded

Cause: Too many requests. The default limit is 1200 requests per five minutes.

Fix: Batch operations, add delays, and retry 429 responses with backoff.

async function updateRecords(records) {
  for (const record of records) {
    try {
      await updateRecord(record)
      await sleep(100) // Rate limit buffer
    } catch (error) {
      if (error.status === 429) {
        await sleep(60000) // Wait a minute
        await updateRecord(record) // Retry
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Alternatives and comparisons

Feature Cloudflare AWS Route 53 Fastly
DNS API
CDN API CloudFront API
Edge functions Workers Lambda@Edge Compute@Edge
WAF API AWS WAF
Free tier Generous Pay per use Limited
Response format JSON XML/JSON JSON

Cloudflare’s API is more unified than AWS’s fragmented services. Workers provide more flexibility than Lambda@Edge.

Real-world use cases

Multi-tenant SaaS

A platform creates Cloudflare zones automatically when customers add custom domains. Workers handle routing, DNS records are created through the API, and SSL certificates provision automatically.

Blue-green deployments

An engineering team uses DNS record updates to switch traffic between environments. The API updates A records during deployment, with propagation through Cloudflare’s network.

DDoS response automation

A security team monitors traffic through the analytics API. When attack patterns emerge, firewall rules are added through the API to block malicious IPs and reduce response time.

Wrapping up

You can use the Cloudflare API to:

  • Authenticate with scoped API tokens
  • Manage zones and DNS records programmatically
  • Deploy Workers for edge computing
  • Configure firewall rules and rate limiting
  • Pull analytics and configure log shipping
  • Test changes with Apidog before applying them to production

FAQ

What’s the difference between a zone and a domain?

A zone is Cloudflare’s representation of a domain. When you add a domain to Cloudflare, you create a zone. API requests for that domain use its zone ID.

How do I find my zone ID?

Go to Cloudflare Dashboard → select your domain → Overview, then scroll to the API section. The zone ID is displayed there.

Can I use the Cloudflare API without a paid plan?

Yes. Most API features work on free plans. Workers have a generous free tier. Some advanced features, including advanced WAF rules and Logpush, require paid plans.

How long do DNS changes take?

Changes made through the API are immediate in Cloudflare’s system. Propagation to Cloudflare nameservers takes seconds. Global propagation depends on TTL and recursive resolvers, typically taking minutes.

What’s the rate limit?

The default is 1200 requests per five minutes per token. Check the X-RateLimit-Remaining header. Enterprise plans have higher limits.

Can I manage multiple accounts with one token?

No. Tokens are scoped to one account. For multiple accounts, create separate tokens or use user-level tokens with access to multiple accounts.

How do Workers differ from Lambda?

Workers run at Cloudflare edge locations, not in specific regions. Cold starts are minimal. They are suited to request and response manipulation rather than long-running processes.

Can I use the API to purge cache?

Yes. Purge specific files with this request:


bash
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "files": ["https://example.com/style.css"]
  }'
Enter fullscreen mode Exit fullscreen mode

Top comments (0)