This document aims to outline the differences between the Cloudflare API versions 1 (v1) and 4 (v4) and help you migrate from v1 to v4.
The API docs for v4 are always found at https://api.cloudflare.com/.
v1 used a single endpoint and triggered behavior based on the value of the a request parameter. All endpoints were POST requests regardless of the data requested or being modified.
v4 organizes API resources into namespaced URIs which GET, POST, PUT, PATCH, and DELETE requests dictate how information is interacted with.
The base URL for v1 operations was https://www.cloudflare.com/api_json.html. The base URL for v4 operations is https://api.cloudflare.com/client/v4.
For brevity, both base URLs are represented as $V1_URL and $V4_URL in this document’s examples.
GET requests are used to fetch data from the API. GET requests are considered idempotent and will never affect underlying data.
In general there are two types of GET requests:
page
per_page
order
direction
ASC
DESC
POST requests are used when creating objects within the API. Complete well-formed JSON objects are expected in the request body.
If the request was successful, the created object is returned in the response’s result object along with any additional information (a generated id field, for example).
This is best exemplified when creating a zone. The minimum required payload is something similar to the following:
{ "name" : "example.com" }
However the complete zone object created looks more like:
{ "created_on": "2016-05-04T17:27:51.703294Z", "development_mode": 0, "id": "835e2f3260c0619b6833729d7bb51aec", "meta": { "custom_certificate_quota": 0, "multiple_railguns_allowed": false, "page_rule_quota": 3, "phishing_detected": false, "step": 4, "wildcard_proxiable": false }, "modified_on": "2016-05-04T17:27:51.768173Z", "name": "example.com", "name_servers": [ "lily.ns.cloudflare.com", "matt.ns.cloudflare.com" ], "original_dnshost": null, "original_name_servers": [ "ns1.example.net", "ns4.example.net", "ns3.example.net", "ns2.example.net" ], "original_registrar": "example, inc.", "owner": { "email": "hello@example.com", "id": "31f8757a9501fb0f5c1c29fb1277ad04", "type": "user" }, "paused": false, "permissions": [ "#analytics:read", "#billing:edit", "#billing:read", "#cache_purge:edit", "#dns_records:edit", "#dns_records:read", "#lb:edit", "#lb:read", "#logs:read", "#organization:edit", "#organization:read", "#ssl:edit", "#ssl:read", "#waf:edit", "#waf:read", "#zone:edit", "#zone:read", "#zone_settings:edit", "#zone_settings:read" ], "plan": { "can_subscribe": true, "currency": "USD", "externally_managed": false, "frequency": "", "id": "0feeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "is_subscribed": true, "legacy_id": "free", "name": "Free Website", "price": 0 }, "status": "pending", "type": "full" }
PUT requests are used when replacing existing objects within the API. Like POST, complete JSON objects are expected in the request body.
If the request was successful, the modified object is returned in the response’s result object.
PATCH requests are used to change one or more fields within an API object. Unlike POST and PUT requests, data objects may be incomplete. Only the fields provided will be affected.
If the request was successful, the complete modified object is returned in the response’s result object.
DELETE requests are used to delete objects within the API.
v1 used form-encoded data to send data into the API and JSON to represent data in responses. This requires extra work on both the client- and server-side for data translation back and forth.
v4 uses JSON to represent data in both requests and responses. It can be expected that when creating a Page Rule that the JSON object sent in the POST request will be nearly identical coming back in a GET request to that same object.
The response format is similar to that of v1’s response objects. A v1 response consists of four common fields: request, response, result, and msg:
{ "request": {}, "response": {}, "result": "success", "msg": null }
In v4, the response has be changed slightly. The inbound request is no longer echoed back out and the response field has been renamed to result. The errors and messages fields offer additional information about the state of the request and/or response. The result_info field will appear when results are potentially paginated.
{ "result": {}, "success": true, "errors": [], "messages": [], "result_info": { "page": 1, "per_page": 20, "count": 1, "total_count": 200 } }
v1 used two request parameters to authenticate requests: tkn and email.
v4 uses these same fields, however they are passed in via HTTP headers.
X-Auth-Email
email
X-Auth-Key
tkn
You can always find your API key in your Dashboard under Account Settings.
Every resource in the v4 API (Users, Zones, Settings, Organizations, etc.) can be identified with an ID field. This is a 32-byte string of hex characters ([a-f0-9]). ID values are usually captured during resource creation (POST requests) or when fetching entire collections (GET requests) of resources.
It’s important to emphasise that the IDs returned in v4 responses are no longer numeric as they were in v1.
You can always find the IDs for API resources by making a GET request to it’s corresponding collection endpoint. For example, to list all Zone objects, a GET request may be sent to $V4_URL/zones. All objects listed in the result array will contain an id field. These endpoints also have the advantage of supporting pagination and filtering.
v1’s stats requests are covered in the v4 Zone Analytics Dashboard request.
Before:
curl $V1_URL \ -d 'a=stats' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com' \ -d 'interval=20'
After:
curl -X GET $V4_URL'/zones/023e105f4ecef8ad9ca31a8372d0c353/analytics/dashboard?since=2015-01-01T12:23:00Z&until=2015-01-02T12:23:00Z' -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json'
The primary difference between v1 and v4 requests for Zone statistics is that the interval has been changed to a date range defined by the since and until query parameters. These can be absolute timestamps or numbers relative to the time of the request.
Note: The Zone ID used in the v4 example (023e105f4ecef8ad9ca31a8372d0c353) will be different from zone-to-zone. See the next section, Retreive the list of domains, for how to get these IDs for your zones.
stats
v1’s zone_load_multi requests are covered in the v4 List Zones request.
curl $V1_URL \ -d 'a=zone_load_multi' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \
curl -X GET $V4_URL'/zones' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json'
The /zones endpoint lists multiple zones which may also be filtered by name or status. Pagination is also supported.
In addition to listing multiple zones, a single zone may also be loaded by concatenating the zone’s ID to the URL as shown in the Zone Details endpoint (/zones/:zone_identifier).
zone_load_multi
v1’s rec_load_all requests are covered in the v4 List DNS Records request.
curl $V1_URL \ -d 'a=rec_load_all' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com'
curl -X GET '/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json'
The /zones/:zone_identifier/dns_records endpoint lists multiple DNS records which may also be filtered by type, name, and content. Pagination is also supported.
In addition to listing multiple DNS records, a single record may also be loaded by concatenating the records’s ID to the URL as shown in the DNS record details endpoint (/zones/:zone_identifier/dns_records/:identifier).
rec_load_all
curl $V1_URL \ -d 'a=rec_new' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com' \ -d 'type=A' \ -d 'name=sub' \ -d 'content=1.2.3.4'
curl -X POST '/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json' \ --data '{ "type": "A", "name": "sub.example.com", "content": "1.2.3.4" }'
curl $V1_URL \ -d 'a=rec_edit' \ -d 'id=9001' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com' \ -d 'type=A' \ -d 'name=sub' \ -d 'content=1.2.3.4' \ -d 'service_mode=1' \ -d 'ttl=1'
curl -X PUT $V4_URL'/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records/372e67954025e0ba6aaa6d586b9e0b59' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json' \ --data '{ "type": "A", "name": "sub.example.com", "content": "1.2.3.4", "proxied": true }'
DNS records are updated by sending a PUT request to the /zones/:zone_identifier/dns_records/:identifier endpoint.
rec_edit
v1’s rec_delete requests are covered with the v4 Delete DNS record request.
curl https://www.cloudflare.com/api_json.html \ -d 'a=rec_delete' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com' \ -d 'id=9001'
curl -X DELETE $V4_URL'/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records/372e67954025e0ba6aaa6d586b9e0b59' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json' \
Sending a DELETE request to the /zones/:zone_identifier/dns_records/:identifier endpoint will remove the DNS record from the zone.
rec_delete
There is no direct analog to v1’s zone_check request as zone IDs are returned from other endpoints.
It is recommended to use v4’s List Zones endpoint to read zone IDs from the returned objects. It is also possible to filter by zone name by passing a name query parameter.
curl -X GET $V4_URL'/zones?name=example.org' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json'
zone_check
Threat scores are no longer supported after v1.
ip_lkup
v1’s zone_settings requests are covered in the v4 Get all Zone settings request.
zone_settings
curl $V1_URL \ -d 'a=zone_settings' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com'
curl -X GET "https://api.cloudflare.com/client/v4/zones/023e105f4ecef8ad9ca31a8372d0c353/settings" \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json'
Previously in v1, the settings were key/value pairs returned. v4 supports many settings some of which have more complex data requirements than singular value. Settings are JSON objects composed of id, value, editable, and modified_on fields.
id
value
editable
modified_on
The id fields are analogous to setting keys returned in v1. v4 also improves these by making them more friendly to humans. For example, the Always Online setting previously looked like:
"ob": 1
v4 represents this as:
{ "id": "always_online", "value": "on", "editable": true, "modified_on": "2014-01-01T05:20:00.12345Z" }
In addition to being able to list all settings bound to a zone, individual settings may be queried with the /zones/:zone_identifier/settings/:name endpoint. This same endpoint can be use to modify setting values (assuming that the editable field is true) by issuing a PATCH request.
/zones/:zone_identifier/settings/:name
true
The next section outlines all settings in Section 4 of the v1 API docs. It should be noted that there are many more settings now available in v4.
All zone settings in v4 follow the same URI convention: /zones/:zone_identifier/settings/:name. This endpoint can be used to fetch the setting’s state (via a GET request) or modified (via a PATCH request).
For example, to fetch the minify setting:
minify
curl -X GET '/zones/023e105f4ecef8ad9ca31a8372d0c353/settings/minify' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json'
And to modify that same setting:
curl -X PATCH '/zones/023e105f4ecef8ad9ca31a8372d0c353/settings/minify' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json' \ --data '{ "value":{ "css": "off", "html": "off", "js": "off" } }'
Be sure to consult the v4 documentation for specific settings you wish to affect. A complete listing follows.
sec_lvl
security_level
cache_lvl
cache_level
devmode
development_mode
ipv46
ipv6
async
rocket_loader
mirage2
mirage
ob
always_online
ch_ttl
challenge_ttl
exp_ttl
browser_cache_ttl
bic
browser_check
email_filter
email_obfuscation
sse
server_side_exclude
hotlink
hotlink_protection
geoloc
ip_geolocation
spdy
ssl
lazy
img
preload
prefetch_preload
waf_profile
waf
origin_error_page_pass_thru
sort_query_string_for_cache
mobile_redirect
polish
response_buffering
security_header
tls_client_auth
true_client_ip_header
tls_1_2_only
v1’s fpurge_ts requests are covered in the v4 Purge all files request.
fpurge_ts
curl $V1_URL \ -d 'a=fpurge_ts' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com' \ -d 'v=1'
curl -X DELETE $V4_URL'/zones/023e105f4ecef8ad9ca31a8372d0c353/purge_cache' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H 'Content-Type: application/json' \ --data '{"purge_everything": true}'
The v4 /zones/:zone_identifier/purge_cache endpoint allows for clearing a zone’s cache. By sending "purge_everything": true, the API will clear all cache for the given zone. The next section describes how to use the same endpoint to clear specific files.
/zones/:zone_identifier/purge_cache
"purge_everything": true
v1’s zone_file_purge requests are covered by the v4 Purge individual files by URL and Cache-Tags request.
zone_file_purge
curl https://www.cloudflare.com/api_json.html \ -d 'a=zone_file_purge' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'z=example.com' \ -d 'url=http://www.example.com/style.css'
curl -X DELETE $V4_URL'/zones/023e105f4ecef8ad9ca31a8372d0c353/purge_cache' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H "Content-Type: application/json" \ --data '{ "files": ["http://www.example.com/css/styles.css"], "tags": ["some-tag", "another-tag"] }'
The v4 /zones/:zone_identifier/purge_cache is also used to clear specific files from the Cloudflare cache. To keep API requests to a minimum, files field accepts an array of file names to purge. A tags array is also available for enterprise zones and allows any file with matching Cache-tag headers to be purged. For more information on purging by Cache-Tag, we’ve written a helpdesk article covers it in great detail.
files
tags
Cache-tag
v1’s wl / ban / nul requests are handled by the v4 Create Access Rule request.
wl
ban
nul
curl $V1_URL \ -d 'a=wl' \ -d 'tkn='$API_KEY \ -d 'email='$API_EMAIL \ -d 'key=0.0.0.0' \
curl -X POST $V4_URL'/zones/023e105f4ecef8ad9ca31a8372d0c353/firewall/access_rules/rules' \ -H 'X-Auth-Email: '$API_EMAIL \ -H 'X-Auth-Key: '$API_KEY \ -H "Content-Type: application/json" \ --data '{ "mode": "whitelist", "configuration": { "target": "ip", "value": "0.0.0.0" }, "notes": "This rule is on because of an event that occured on date X" }'
Support for access rules has grown significantly in v4. Different modes change the firewall’s behavior allowing for blocking, whitelisting, triggering a JavaScript challenge (I Am Under Attack Mode) or presenting a CAPTCHA challenge page). Rules can target IP addresses (IPv4 or 6), address ranges, ASNs, and even countries. In addition to applying access rules at a zone-level, rules may also be set at a user- or organization-level.
Now that you’ve migrated, here’s a quick look at all the new things you can do with v4 that you couldn’t do earlier with v1:
https://api.cloudflare.com/
Everyone’s Internet application can benefit from using Cloudflare. Pick a plan that fits your needs.
for personal websites and blogs
Our mission is to build a better Internet. We believe every website should have free access to foundational security and performance. Cloudflare's Free plan has no limit on the amount of bandwidth your visitors use or websites you add.
If you want to make your site even faster and more resilient, you can easily upgrade to one of our higher tier plans.
Learn More
To provide you with the best possible experience on our website, we may use cookies, as described here.By clicking accept, closing this banner, or continuing to browse our websites, you consent to the use of such cookies.