Cloudflare MCP Server — 284 tools
The Cloudflare DADL turns Cloudflare's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 284 tools — email, page, zone, worker, account, secondary, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process.
Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Cloudflare feature area, required credential scopes.
Source: Cloudflare REST API v4
Which Cloudflare endpoints are covered?
19% (284 of ~1500 endpoints)
Focus: zones, DNS records, DNSSEC, DNS settings, secondary DNS incoming/outgoing/peers/TSIGs/ACLs, DNS Firewall clusters, Registrar domains/search/pricing/registration, Pages projects/deployments/domains, Workers scripts/routes/secrets/cron/deployments/tails, KV namespaces/keys, R2 buckets/lifecycle/CORS/domains, D1 databases/queries, SSL/TLS certificates/custom hostnames, cache purge/settings, load balancers/pools/monitors, firewall rules/rulesets/rate limits, page rules, Access apps/policies/groups, accounts/members/roles, Email Routing settings/DNS/rules/catch-all/destination addresses, Email Sending send/raw MIME/sending subdomains/DNS status/suppressions/reputation/limits, Email Auth DMARC reports/SPF inspection
Missing: Argo, Spectrum, Stream, Images (transformations), Email Security (Area 1), Email Routing wrangler plan endpoint, Radar email statistics, Waiting Room, Web3, Turnstile, Queues, Hyperdrive, Vectorize, AI Gateway, Durable Objects, Zone Lockdown, IP Access Rules, User-Agent Blocking, Logpush, Notifications, Audit Logs
How do you configure the Cloudflare DADL?
- Log in to Cloudflare dashboard at https://dash.cloudflare.com
- Go to My Profile (top right) → API Tokens
- Click 'Create Token'
- Use a template (e.g. 'Edit zone DNS') or create a custom token with specific permissions
- Copy the token immediately -- it is shown only once
Environment variable: CREDENTIAL_CLOUDFLARE_API_TOKEN
API Tokens (scoped) are preferred over the Global API Key. Tokens can be restricted to specific zones and permissions. The Global API Key (X-Auth-Email + X-Auth-Key headers) grants full account access and is only needed for the rare endpoints that reject tokens. Registrar: the registrar/domains endpoints DO work with a scoped API Token, but only if it carries the 'Account > Registrar > Domains' permission (Read for list/get, Edit for update) -- without it Cloudflare returns HTTP 403 (code 10000). Verified working against the live API with a scoped token plus that permission; the Global API Key is not required. The Registrar API beta tools (search_registrar_domains, check_registrar_domains, register_registrar_domain) additionally require the token's Registrar permission at Edit/write level AND a billing profile + default registrant contact configured on the account. Email: routing settings, DNS, rules and catch-all need the zone permission 'Email Routing Rules' (Read/Edit); destination addresses need the account permission 'Email Routing Addresses' (Read/Edit); DMARC/SPF tools need 'DMARC Management' (Read/Edit); Email Sending (send, sending subdomains, suppressions, reputation, limits) needs the account permission 'Email Sending' (Read/Edit) plus a sending subdomain whose DNS status is ready. Verified 2026-09-27 against the live API: routing settings/DNS/rules/catch-all, destination addresses, DMARC status/config, SPF inspection, sending limits, sending-subdomain preview and the suppression CRUD work with a scoped token carrying those permissions; the account-wide rules list still returned 403 with per-zone rule permissions, and reputation returns 404 until Email Sending is activated.
How do you install the Cloudflare MCP server with ToolMesh?
Add to your backends.yaml:
- name: cloudflare
transport: rest
dadl: cloudflare.dadl
Set the credential:
CREDENTIAL_CLOUDFLARE_API_TOKEN=your-token-here What 284 tools does the Cloudflare DADL expose?
GET list_accounts List all accounts you have access to GET get_account Get account details PUT update_account Update account settings GET list_account_members List all account members GET get_account_member Get account member details POST add_account_member Add a member to an account PUT update_account_member Update account member roles DELETE remove_account_member Remove a member from an account GET list_account_roles List all available roles for an account GET get_account_role Get role details and permissions GET verify_token Verify the API token used for this request: returns its id and status (active/expired/disabled) plus validity window. Confirms auth works; does NOT list the token's own permissions (use GET /user/tokens/{id} for that). GET list_token_permission_groups List the catalog of grantable API token permission groups (id, name, scopes). Use to find the exact group ID to attach when creating a token via the API -- e.g. filter name=Registrar to locate the registrar read vs write groups. Returns the global catalog, NOT the current token's permissions. Needs the token permission User > API Tokens (Read); without it Cloudflare answers HTTP 403 code 9109. GET list_zones List, search, sort, and filter zones. Returns zone_id needed for all zone-scoped endpoints. GET get_zone Get zone details POST create_zone Create a new zone (add a domain to Cloudflare) PATCH update_zone Edit zone properties (paused, type, vanity nameservers) DELETE delete_zone Delete a zone and all associated settings. Irreversible. PUT check_zone_activation Trigger activation check for a PENDING zone. Rate limited (5min paygo/enterprise, 1hr free). GET list_zone_settings Get all zone settings GET get_zone_setting Get a single zone setting by ID PATCH update_zone_setting Update a single zone setting GET get_zone_hold Get zone hold status and metadata POST create_zone_hold Enforce a zone hold (block zone creation with this hostname) DELETE delete_zone_hold Remove zone hold (permanently or temporarily) GET list_zone_plans List available plans the zone can subscribe to GET get_zone_subscription Get zone subscription details POST create_zone_subscription Create zone subscription (plan/add-on) GET list_registrar_domains List all domains managed by Cloudflare Registrar in this account. Returns name, status, expiry, current registrar, and lock/auto-renew/privacy flags. Does not include zones that are merely using Cloudflare DNS. GET get_registrar_domain Get details for a single Cloudflare Registrar domain (status, expiry, contacts, nameservers, lock/auto-renew/privacy). Response is trimmed to key fields; pass a jq filter to override if you need the raw WHOIS object. PUT update_registrar_domain Update an existing Cloudflare Registrar domain. Only auto_renew, privacy (WHOIS redaction), and locked (registrar transfer lock) are editable here; nameservers are managed on the zone. To register a NEW domain use register_registrar_domain instead. GET search_registrar_domains Search for registrable domain suggestions by keyword/phrase (Registrar API beta). Returns candidate domains across TLDs WITH availability and pricing (registration_cost/renewal_cost), same per-domain shape as check_registrar_domains. POST check_registrar_domains Check availability AND pricing for up to 20 domains at once (Registrar API beta). For each domain returns registrable, tier, reason (when not registrable), and pricing (currency, registration_cost, renewal_cost) at Cloudflare's at-cost wholesale rate. POST register_registrar_domain Register a NEW domain via Cloudflare Registrar (Registrar API beta). PLACES A PAID ORDER charged to the account billing profile, using the account's default registrant contact. Run check_registrar_domains first to confirm availability and price. Irreversible billing action. GET list_dns_records List, search, sort, and filter DNS records for a zone GET get_dns_record Get a single DNS record POST create_dns_record Create a new DNS record PATCH update_dns_record Update (partial) a DNS record PUT overwrite_dns_record Overwrite (full replace) a DNS record DELETE delete_dns_record Delete a DNS record POST batch_dns_records Batch create/update/delete DNS records atomically in one transaction POST import_dns_records Import DNS records from a BIND config file GET export_dns_records Export DNS records as BIND zone file POST scan_dns_records Scan for common DNS records and auto-add them GET get_dnssec Get DNSSEC status and configuration PATCH update_dnssec Enable or disable DNSSEC DELETE delete_dnssec Delete DNSSEC records GET get_zone_dns_settings Get DNS settings for a zone PATCH update_zone_dns_settings Update DNS settings for a zone GET get_account_dns_settings Get DNS settings for an account PATCH update_account_dns_settings Update DNS settings for an account GET get_dns_analytics Get summarized aggregate DNS metrics over a time period GET get_dns_analytics_by_time Get aggregate DNS metrics grouped by time interval GET get_secondary_dns_incoming Get the incoming (secondary) zone transfer configuration. Cloudflare pulls this zone from your external primary. POST create_secondary_dns_incoming Create the incoming (secondary) zone transfer config so Cloudflare pulls the zone from your primary. peers references account-scoped peer tags. PUT update_secondary_dns_incoming Update the incoming (secondary) zone transfer configuration DELETE delete_secondary_dns_incoming Delete the incoming (secondary) zone transfer configuration POST force_axfr_secondary_dns Force an immediate AXFR (full zone transfer) from the primary for a secondary zone GET get_secondary_dns_outgoing Get the outgoing (primary) zone transfer configuration. Cloudflare serves this zone as primary and notifies external secondaries. POST create_secondary_dns_outgoing Create the outgoing (primary) zone transfer config so external secondaries can pull this zone from Cloudflare. peers references account-scoped peer tags. PUT update_secondary_dns_outgoing Update the outgoing (primary) zone transfer configuration DELETE delete_secondary_dns_outgoing Delete the outgoing (primary) zone transfer configuration POST enable_secondary_dns_outgoing Enable outgoing zone transfers (resume notifying external secondaries) POST disable_secondary_dns_outgoing Disable outgoing zone transfers (stop notifying external secondaries) POST force_notify_secondary_dns_outgoing Send a DNS NOTIFY to all external secondaries to prompt an immediate pull GET get_secondary_dns_outgoing_status Get the enabled/disabled status of outgoing zone transfers GET list_dns_peers List all secondary DNS peers (nameservers) for an account. Peer tags are referenced from zone incoming/outgoing configs. GET get_dns_peer Get a single secondary DNS peer POST create_dns_peer Create a secondary DNS peer (a primary/secondary nameserver Cloudflare transfers with) PUT update_dns_peer Update a secondary DNS peer DELETE delete_dns_peer Delete a secondary DNS peer GET list_dns_tsigs List all secondary DNS TSIG keys for an account GET get_dns_tsig Get a single secondary DNS TSIG key POST create_dns_tsig Create a TSIG key for authenticated zone transfers PUT update_dns_tsig Update a secondary DNS TSIG key DELETE delete_dns_tsig Delete a secondary DNS TSIG key GET list_dns_acls List all secondary DNS ACLs (IP-range allowlists) for an account GET get_dns_acl Get a single secondary DNS ACL POST create_dns_acl Create a secondary DNS ACL restricting which peer IP ranges may transfer PUT update_dns_acl Update a secondary DNS ACL DELETE delete_dns_acl Delete a secondary DNS ACL GET list_dns_firewall_clusters List all DNS Firewall clusters (account-scoped recursive resolvers). Distinct from authoritative zone DNS and from zone firewall rules. GET get_dns_firewall_cluster Get a DNS Firewall cluster's configuration, including the anycast dns_firewall_ips to point clients at POST create_dns_firewall_cluster Create a DNS Firewall cluster. upstream_ips are your origin resolvers; the response returns anycast IPs to use as your nameservers. PATCH update_dns_firewall_cluster Update a DNS Firewall cluster's configuration (rate limits, cache TTLs, upstreams, mitigation) DELETE delete_dns_firewall_cluster Delete a DNS Firewall cluster GET list_pages_projects List all Cloudflare Pages projects GET get_pages_project Get a Pages project by name POST create_pages_project Create a new Pages project PATCH update_pages_project Update Pages project attributes DELETE delete_pages_project Delete a Pages project and all deployments. Irreversible. POST purge_pages_build_cache Purge all cached build artifacts for a Pages project GET list_pages_deployments List all deployments for a Pages project GET get_pages_deployment Get a specific deployment POST create_pages_deployment Create a new deployment (direct upload via multipart or trigger Git build) DELETE delete_pages_deployment Delete a deployment POST retry_pages_deployment Retry a failed deployment POST rollback_pages_deployment Rollback production to a previous deployment GET get_pages_deployment_logs Get build/deployment logs for a specific deployment GET list_pages_domains List all custom domains for a Pages project GET get_pages_domain Get a specific Pages domain POST add_pages_domain Add a custom domain to a Pages project PATCH retry_pages_domain_validation Retry domain validation for a Pages custom domain DELETE delete_pages_domain Remove a custom domain from a Pages project GET list_worker_scripts List all uploaded Worker scripts GET get_worker_script Fetch raw Worker script content PUT upload_worker_script Upload or update a Worker script (multipart: module content + metadata with bindings) DELETE delete_worker_script Delete a Worker script GET get_worker_script_content Fetch Worker script content only (without metadata) PUT update_worker_script_content Update Worker script content without changing settings/bindings GET list_worker_routes List all Worker routes for a zone GET get_worker_route Get a specific Worker route POST create_worker_route Create a Worker route (map URL pattern to a Worker script) PUT update_worker_route Update a Worker route DELETE delete_worker_route Delete a Worker route GET list_worker_cron_triggers List cron triggers for a Worker PUT update_worker_cron_triggers Set cron triggers for a Worker (replaces all existing triggers) GET list_worker_secrets List secrets bound to a Worker (names only, values not returned) PUT put_worker_secret Add or update a secret binding for a Worker DELETE delete_worker_secret Remove a secret binding from a Worker GET list_worker_deployments List deployments for a Worker (latest first) POST create_worker_deployment Create a Worker deployment (percentage-based rollout) GET list_worker_tails List active tails (live log streams) for a Worker POST create_worker_tail Start a tail to receive live logs and exceptions from a Worker DELETE delete_worker_tail Delete a Worker tail GET get_worker_subdomain Check workers.dev subdomain status for a Worker POST set_worker_subdomain Enable or disable workers.dev subdomain for a Worker GET list_kv_namespaces List all Workers KV namespaces GET get_kv_namespace Get a KV namespace POST create_kv_namespace Create a KV namespace PUT rename_kv_namespace Rename a KV namespace DELETE delete_kv_namespace Delete a KV namespace and all its keys GET list_kv_keys List keys in a KV namespace GET kv_read_value Read a value from KV by key name PUT kv_write_value Write a key-value pair to KV. Eventually consistent (up to 60s propagation). DELETE kv_delete_value Delete a key from KV GET kv_get_metadata Get metadata for a KV key PUT kv_bulk_write Write multiple key-value pairs to KV in one request POST kv_bulk_delete Delete multiple keys from KV in one request POST kv_bulk_read Read multiple keys from KV in one request (up to 100) GET list_r2_buckets List all R2 buckets GET get_r2_bucket Get R2 bucket properties POST create_r2_bucket Create an R2 bucket DELETE delete_r2_bucket Delete an R2 bucket (must be empty) GET get_r2_lifecycle Get R2 bucket lifecycle rules PUT set_r2_lifecycle Set R2 bucket lifecycle rules GET get_r2_cors Get R2 bucket CORS policy PUT set_r2_cors Set R2 bucket CORS policy DELETE delete_r2_cors Delete R2 bucket CORS policy GET list_r2_custom_domains List custom domains for an R2 bucket POST add_r2_custom_domain Add a custom domain to an R2 bucket DELETE delete_r2_custom_domain Remove a custom domain from an R2 bucket GET get_r2_managed_domain Get r2.dev public domain status PUT set_r2_managed_domain Enable or disable r2.dev public access GET list_d1_databases List all D1 databases GET get_d1_database Get D1 database details POST create_d1_database Create a D1 database DELETE delete_d1_database Delete a D1 database POST d1_query Execute SQL query on D1 (results as objects) POST d1_raw_query Execute SQL query on D1 (results as arrays, more compact) POST d1_export Export D1 database as SQL dump POST d1_import Import SQL into a D1 database GET d1_time_travel_bookmark Get current or historical D1 database bookmark (point-in-time) POST d1_time_travel_restore Restore D1 database to a point in time. Overwrites current state. GET list_custom_certificates List all custom SSL certificates for a zone GET get_custom_certificate Get custom certificate details POST upload_custom_certificate Upload a new custom SSL certificate PATCH update_custom_certificate Update a custom SSL certificate or private key DELETE delete_custom_certificate Remove a custom SSL certificate PUT prioritize_certificates Set priority order for custom certificates GET list_certificate_packs List all certificate packs for a zone GET get_certificate_pack Get a specific certificate pack POST order_certificate_pack Order an advanced certificate pack DELETE delete_certificate_pack Delete a certificate pack GET list_custom_hostnames List all custom hostnames for a zone GET get_custom_hostname Get custom hostname details including SSL status and verification POST create_custom_hostname Create a custom hostname and request SSL certificate PATCH update_custom_hostname Update custom hostname SSL config or trigger DCV DELETE delete_custom_hostname Delete a custom hostname and revoke its SSL certificates GET get_ssl_recommendation Get SSL/TLS mode recommendation for a zone GET get_ssl_verification Get SSL verification info and DCV status GET get_universal_ssl_settings Get Universal SSL settings for a zone PATCH update_universal_ssl_settings Update Universal SSL settings (enable/disable) POST purge_cache Purge cached content. Use purge_everything for full purge, or files/tags/hosts/prefixes for selective. GET get_cache_reserve Get Cache Reserve status PATCH update_cache_reserve Enable or disable Cache Reserve GET get_tiered_cache Get Smart Tiered Cache setting PATCH update_tiered_cache Enable or disable Smart Tiered Cache GET list_load_balancers List all load balancers for a zone GET get_load_balancer Get load balancer details POST create_load_balancer Create a load balancer PUT update_load_balancer Update a load balancer DELETE delete_load_balancer Delete a load balancer GET list_lb_pools List all load balancer pools GET get_lb_pool Get load balancer pool details POST create_lb_pool Create a load balancer pool PUT update_lb_pool Update a load balancer pool DELETE delete_lb_pool Delete a load balancer pool GET get_lb_pool_health Get pool health status GET list_lb_monitors List all load balancer monitors GET get_lb_monitor Get load balancer monitor details POST create_lb_monitor Create a load balancer health monitor PUT update_lb_monitor Update a load balancer monitor DELETE delete_lb_monitor Delete a load balancer monitor GET list_firewall_rules List firewall rules for a zone GET get_firewall_rule Get a specific firewall rule POST create_firewall_rules Create one or more firewall rules PUT update_firewall_rule Update a firewall rule DELETE delete_firewall_rule Delete a firewall rule GET list_account_rulesets List all account-level rulesets GET list_zone_rulesets List all zone-level rulesets GET get_zone_ruleset Get a specific zone ruleset POST create_zone_ruleset Create a zone ruleset PUT update_zone_ruleset Update/deploy a zone ruleset (replaces all rules) DELETE delete_zone_ruleset Delete a zone ruleset GET get_zone_ruleset_phase Get the entry point ruleset for a phase (e.g. http_ratelimit, http_request_firewall_custom) PUT update_zone_ruleset_phase Update the entry point ruleset for a phase GET list_page_rules List all page rules for a zone GET get_page_rule Get a specific page rule POST create_page_rule Create a page rule PUT update_page_rule Replace a page rule entirely DELETE delete_page_rule Delete a page rule GET list_access_apps List all Cloudflare Access applications GET get_access_app Get Access application details POST create_access_app Create an Access application PUT update_access_app Update an Access application DELETE delete_access_app Delete an Access application GET list_access_policies List all reusable Access policies GET get_access_policy Get a reusable Access policy POST create_access_policy Create a reusable Access policy PUT update_access_policy Update a reusable Access policy DELETE delete_access_policy Delete a reusable Access policy GET list_access_app_policies List policies for a specific Access application GET get_access_app_policy Get a specific policy for an Access application POST create_access_app_policy Create a policy for a specific Access application PUT update_access_app_policy Update a policy for an Access application DELETE delete_access_app_policy Delete a policy for an Access application GET list_access_groups List all Access groups GET get_access_group Get Access group details POST create_access_group Create an Access group PUT update_access_group Update an Access group DELETE delete_access_group Delete an Access group GET get_email_routing_settings Get the Email Routing state of a zone: enabled, status (ready | unconfigured | misconfigured | misconfigured/locked | unlocked), support_subaddress (plus-addressing), skip_wizard, created/modified. Call this first -- routing rules only take effect while status is 'ready'. PATCH update_email_routing_settings Update Email Routing zone settings: support_subaddress (honor plus-addressing like user+tag@zone when matching rules) and skip_wizard. Omitted fields keep their value. Cannot switch routing on or off -- use enable_email_routing / disable_email_routing for that. GET get_email_routing_dns_records Show the DNS records Email Routing needs on this zone -- MX route1/2/3.mx.cloudflare.net, an SPF TXT record at the apex and the DKIM TXT record cf2024-1._domainkey -- each as {type, name, content, priority, ttl}. Works for zones where routing is not enabled yet (shows what enable_email_routing would create and lock). POST enable_email_routing Enable Email Routing on a zone: Cloudflare adds AND LOCKS the required MX records and the SPF TXT record at the zone apex. Existing foreign MX records must be removed first, otherwise the zone ends up with status 'misconfigured'. Returns the settings object -- check that status == 'ready'. DELETE disable_email_routing Disable Email Routing on a zone and REMOVE the MX/SPF records it added. Incoming mail to the zone stops being routed immediately; routing rules and destination addresses are kept but become inactive. PATCH unlock_email_routing_dns Unlock the MX records that Email Routing locked so they can be edited with the DNS tools (status becomes 'unlocked'). Editing them can break routing; run enable_email_routing again to restore and re-lock the records. GET list_email_routing_rules List the custom-address routing rules of a zone: id, name, enabled, priority, matchers [{type: literal | all, field: to, value}], actions [{type: forward | drop | worker, value: [target]}], source (api | wrangler). The catch-all rule is included as well (matchers [{type: all}], priority 2147483647) -- manage it via get/update_email_routing_catch_all, not via update_email_routing_rule. GET get_email_routing_rule Get one routing rule by id (matchers, actions, enabled, priority, source). POST create_email_routing_rule Create a routing rule for a custom address of the zone. matchers: [{type: 'literal', field: 'to', value: '[email protected]'}]. actions: [{type: 'forward', value: ['[email protected]']}] forwards to exactly ONE destination address that is already VERIFIED in the account (create_email_destination_address + link click), [{type: 'drop'}] discards the mail, [{type: 'worker', value: ['script-name']}] hands it to an Email Worker. Lower priority number wins when several rules match. Requires Email Routing to be enabled on the zone. PUT update_email_routing_rule Replace a routing rule (PUT = full replace: matchers AND actions are required again, omitted name/enabled/priority fall back to their defaults). Use it to change the forward target, disable a rule, or re-prioritize. Forward actions need exactly one verified destination address. DELETE delete_email_routing_rule Delete a routing rule. Mail to that custom address is no longer matched and falls through to the catch-all rule (which drops by default). GET get_email_routing_catch_all Get the zone's catch-all rule -- what happens to mail for addresses no custom rule matches: enabled, actions [{type: forward | drop | worker, value}], matchers [{type: all}]. PUT update_email_routing_catch_all Set the zone's catch-all rule: enable or disable it and choose the action -- forward all unmatched mail to one verified destination address ([{type: 'forward', value: ['[email protected]']}]), drop it ([{type: 'drop'}]), or route it to an Email Worker ([{type: 'worker', value: ['script-name']}]). matchers must be [{type: 'all'}]. PUT = full replace. GET list_email_destination_addresses List the Email Routing destination addresses of the account (the mailboxes forward rules may deliver to): id, email, verified (timestamp, or null while the recipient has not clicked the verification link), created, modified. Without the verified filter ALL addresses are returned (verified and pending); verified=true or verified=false narrows the list. account_id is required; get it via list_accounts. GET get_email_destination_address Get one destination address by id, including its verified timestamp (null = not yet verified). POST create_email_destination_address Register a destination address for forwarding. Cloudflare immediately emails a verification link to that address; until the recipient clicks it, verified stays null and routing rules that forward to it are rejected. Returns the address object (id, email, verified: null). PATCH update_email_destination_address Change a destination address status. With a regular API token this can only reset a verified address to 'unverified' (forcing re-verification); setting 'verified' requires Cloudflare admin privileges and is rejected otherwise. DELETE delete_email_destination_address Delete a destination address. Routing rules that forward to it stop working -- update or delete those rules first. Cloudflare refuses to delete an address that was created only moments ago (HTTP 429 code 2032 'created too recently') -- wait a few minutes and retry. GET list_email_routing_rules_across_zones List the routing rules of ALL zones in the account in one call; each rule carries zone {name, tag} in addition to id, name, enabled, priority, matchers, actions. Use it to audit which custom addresses forward where without iterating zones. Permission caveat: a token whose Email Routing Rules permission is granted per zone gets HTTP 403 (code 10000) here even though the per-zone list_email_routing_rules works -- fall back to iterating zones in that case. POST send_email Send an outbound email through Cloudflare Email Sending. from must be an address on an ENABLED sending subdomain of the account (create_email_sending_subdomain, DNS status 'ready'); recipients can be any external addresses. Every address value is either a plain string '[email protected]' or {address, name}; to/cc/bcc take arrays of those and at least one of the three is required. Provide subject and at least one of text/html. Returns {message_id, delivered[], queued[], permanent_bounces[], suppressed_recipients[]}. Each send counts against the daily quota (get_email_sending_limits). POST send_email_raw Send a pre-built RFC 5322 MIME message (headers + body, optionally multipart) through Email Sending. from and recipients form the SMTP envelope and must be plain addresses; the message's From header must still use an enabled sending subdomain. Prefer send_email unless you need full control over the MIME structure. Returns {message_id, delivered[], queued[], permanent_bounces[], suppressed_recipients[]}. GET get_email_sending_limits Get the account's Email Sending quota and current usage: {quota: {value, unit: day | hour}, usage: {sent, over_quota, resets_at}}. quota and usage are null while no quota is resolved yet (Email Sending not activated). Check before bulk sends. GET get_email_sending_reputation Get the account's Email Sending reputation: status (healthy | warning | at_risk | suspended), status_since, evaluated_at, grace_started_at, and the active_policy thresholds (complaint, customer_bounce and spam_rejection rates with warning_at/at_risk_at/minimum_denominator, suspension_after_hours). While suspended, sends are rejected. Accounts that have not activated Email Sending get HTTP 404 (code 10001 'Unable to authenticate request') from this endpoint even with the right permission -- check get_email_sending_limits (quota null) first. GET get_email_sending_message Fetch the raw RFC 5322 MIME of a message sent via Email Sending, by the message_id returned from send_email / send_email_raw. The body is message/rfc822 (not JSON), so ToolMesh returns a file-broker download URL. Only available for subdomains with preview_enabled=true (activity-log preview). GET list_email_sending_suppressions List active Email Sending suppressions (addresses that will NOT be delivered to): id, email, reason (manual | complaint | hard_bounce | soft_bounce | policy), scope ({type: 'account'} or {type: 'sending_domain', value}), expires_at (null = permanent), read_only, note. Sending-domain suppressions come first, then account-wide ones. CURSOR pagination unlike the rest of the API: the result is {suppressions: [...], next_cursor}; pass next_cursor as cursor to fetch the next page (page/per_page paging does not apply). GET get_email_sending_suppression Get one Email Sending suppression by id (email, reason, scope, expires_at, read_only, note). POST create_email_sending_suppression Suppress an address so Email Sending never delivers to it -- for every sending domain of the account by default, or for one sending domain via scope {type: 'sending_domain', value: 'mail.example.com'}. Creating an already active suppression returns its existing id. Scope is immutable afterwards (delete and recreate to change it). Returns {id, scope}. POST bulk_create_email_sending_suppressions Import up to 1,000 Email Sending suppressions in one request. items: [{email, expires_at?, note?, scope?}] with the same semantics as create_email_sending_suppression; duplicates (same email + scope) are deduplicated. Returns counts (total, processed, deduplicated, invalid, skipped, errors) and per-item results {index, email, status: processed | invalid | error | skipped, id?, error?} in request order. PATCH update_email_sending_suppression Update the expiry or note of a suppression. Send expires_at as null to make it permanent, note as '' to clear it; omitted fields stay unchanged. Scope cannot be changed (400 scope_immutable) and read_only suppressions (reason policy) cannot be edited. DELETE delete_email_sending_suppression Delete a suppression so the address can receive Email Sending mail again. GET list_email_sending_subdomains List the sending-enabled (sub)domains of a zone: tag (this is the subdomain_id for the other subdomain tools), name, enabled, dkim_selector, return_path_domain, preview_enabled, drop_suppressed_recipients. A zone has none until create_email_sending_subdomain is called. GET get_email_sending_subdomain Get one sending subdomain by id (the tag field of list_email_sending_subdomains). POST create_email_sending_subdomain Enable Email Sending on a domain of the zone, e.g. 'mail.example.com' or the apex 'example.com' ('*.example.com' wildcards need the wildcard entitlement). Cloudflare creates and locks the DKIM, SPF, DMARC and return-path DNS records and returns the subdomain (tag = subdomain_id). Run preview_email_sending_subdomain first to detect conflicts with existing MX/SPF/DMARC records, then confirm readiness with get_email_sending_subdomain_dns_status. Also re-enables a previously deleted subdomain. POST preview_email_sending_subdomain Dry run for create_email_sending_subdomain: returns the DNS records Cloudflare would create for the name plus errors[] with codes such as mx.missing, mx.foreign, spf.multiple, dkim.conflict, dmarc.incompatible, sending_subdomain.conflict (each with the existing/missing/multiple records involved). Nothing is created or modified. PATCH update_email_sending_subdomain Update a sending subdomain (at least one field required): preview_enabled lets sent messages be previewed in the activity log (needed for get_email_sending_message); drop_suppressed_recipients=true makes send_email drop suppressed recipients and deliver to the rest instead of failing the whole request. DELETE delete_email_sending_subdomain Disable sending on the subdomain and remove its sending DNS records (DKIM/SPF/DMARC/return-path). Email Routing on the same name is unaffected. Sends with a from address on this subdomain fail afterwards. GET get_email_sending_subdomain_dns Return the DNS records a sending subdomain is expected to have (desired state as {type, name, content, priority, ttl}) -- no live comparison; use get_email_sending_subdomain_dns_status for that. GET get_email_sending_subdomain_dns_status Live DNS health of a sending subdomain: status (ready | unconfigured | unlocked | misconfigured), the desired records, and errors[] (mx.missing, mx.foreign, spf.missing, spf.foreign, spf.multiple, dkim.missing, dkim.conflict, dmarc.missing, dmarc.multiple, dmarc.incompatible, domainkey.delegated, sending_subdomain.conflict). Call this before fix_email_sending_subdomain_dns. POST fix_email_sending_subdomain_dns Idempotently repair a sending subdomain's DNS: re-creates missing sending records and re-applies the lock on unlocked ones. Refuses with HTTP 409 while foreign MX, multiple SPF, multiple DMARC or multiple DKIM records exist at the relevant names -- clean those up with the DNS tools first. Returns the same shape as get_email_sending_subdomain_dns_status. GET get_email_sending_subdomain_complaints Number of spam complaints matched to a sending subdomain in the half-open window [start_at, end_at), at most seven days long. Returns {complaints}. GET get_dmarc_reports_status Get the zone's DMARC Management state: enabled (Cloudflare collects DMARC aggregate reports through its RUA address), rua_prefix, status (missing-dmarc-report | multiple-dmarc-reports | missing-dmarc-rua | cname-on-dmarc-record | unauthorized-reporting-domain; the field is absent when DMARC is configured correctly), approved_sources (sending sources seen in reports, with resolved IPs) and records -- the zone's live SPF, DKIM, DMARC and BIMI TXT/CNAME records grouped by type. A good first call for any email-deliverability audit of a zone. PATCH configure_dmarc_reports Enable or disable Cloudflare DMARC report collection for the zone (at least one of enabled/skip_wizard required). enabled=true ensures the zone's DMARC TXT record carries Cloudflare's rua= reporting address (creating it if needed) so aggregate reports flow into DMARC Management. Returns the same shape as get_dmarc_reports_status. GET inspect_spf_record Parse one SPF TXT record of the zone into a component tree: every mechanism (A, MX, IP4, IP6, INCLUDE, REDIRECT, EXISTS, PTR, ALL) with its qualifier result, nested includes resolved recursively, lookup_count per component and total_lookups (RFC 7208 allows 10), plus errors[] (lookup_failed, spf_not_found, invalid_spf, invalid_domain, loop_detected, invalid_mechanism, ...). id is the DNS record id of the SPF TXT record -- find it with list_dns_records(type='TXT').