Skip to main content

Cloudflare ExecModule

Overview

CloudflareModule connects ValkyrAI workflows to Cloudflare API v4 through the native map I/O ExecModule ABI. Workflow Studio discovers it as CloudflareModule. A scoped API token resolves only from a bound READY IntegrationAccount; workflow input cannot provide credentials or redirect requests to arbitrary hosts.

The first production operation set focuses on the infrastructure controls most useful to governed agents:

  • identity: verify_token;
  • zones: list_zones, get_zone;
  • DNS: list_dns_records, get_dns_record, create_dns_record, update_dns_record, delete_dns_record;
  • cache: purge_cache;
  • settings: get_zone_setting, update_zone_setting.

This surface uses n8n's official Cloudflare node as the functional integration reference and Cloudflare's current zone, DNS, cache, and setting APIs for the production contract. Lists use bounded page pagination. Provider responses and errors are size-limited and redacted. Only GET requests retry automatically; writes run once because their outcome can be ambiguous after a timeout.

Usage

  1. Create a dedicated Cloudflare API token for the automation identity.
  2. Grant only the zone, DNS, cache-purge, and zone-setting permissions the workflow needs.
  3. Restrict the token to the specific Cloudflare account and zones whenever possible.
  4. Store the token in the encrypted apiKey field of an IntegrationAccount and set its status to READY.
  5. Bind the account through ExecModuleConfig.authConfig.integrationAccount.
  6. Use list_zones and list_dns_records to resolve current IDs before any mutation.

Inputs

NameTypeRequirementDefaultDescription and constraints
operationstringRequiredNoneOne of the eleven operations above.
zoneIdstringZone-scoped operationsNoneCloudflare zone ID, 1–64 letters, digits, _, or -.
dnsRecordIdstringGet, update, or delete DNS recordNoneCloudflare DNS record ID with the same bound.
settingIdstringZone-setting operationsNoneOne allowlisted setting: always_online, always_use_https, automatic_https_rewrites, brotli, browser_cache_ttl, cache_level, development_mode, http2, http3, min_tls_version, opportunistic_encryption, or ssl.
settingValuescalar/object/JSON stringupdate_zone_settingNoneProvider-compatible setting value, maximum 16 KiB.
namestringDNS create; optional list filter/updateNoneBounded DNS name or exact zone-name filter.
typestringDNS create; optional list filter/updateNoneSupported Cloudflare DNS type such as A, AAAA, CNAME, MX, TXT, CAA, SRV, HTTPS, or SVCB.
contentstringDNS create; optional list filter/updateNoneDNS record content, 1–4,096 characters.
ttlintegerOptional DNS create/update1 on create1 for automatic or 60–86,400 seconds.
proxiedbooleanOptional DNS list/create/updateNoneCloudflare proxy selection for compatible records.
commentstringOptional DNS create/updateNoneBounded record comment, maximum 500 characters.
recordobject or JSON stringOptional DNS create/updateNoneAllowlisted provider fields only: type, name, content, ttl, proxied, priority, comment, tags, and data; 256 KiB cap.
zoneStatusstringOptional zone listNoneinitializing, pending, active, or moved.
accountIdstringOptional zone listNoneExact Cloudflare account ID filter.
matchstringOptional listsallall or any.
pageintegerOptional list continuation1Starting page from 1 through 1,000,000.
limitintegerOptional lists100Maximum returned resources, 1–10,000.
returnAllbooleanOptional listsfalseFollow pages to exhaustion or the 10,000-item cap.
confirmDeletebooleandelete_dns_recordfalseMust be true before permanent DNS deletion.
purgeFilesarray/JSON stringOne purge selectorNoneOne through 30 HTTPS URLs.
purgeTagsarray/JSON stringOne purge selectorNoneOne through 30 cache tags.
purgeHostsarray/JSON stringOne purge selectorNoneOne through 30 valid hostnames.
purgePrefixesarray/JSON stringOne purge selectorNoneOne through 30 bounded prefixes.
purgeEverythingbooleanOne purge selectorfalseFull-zone cache purge.
confirmPurgeEverythingbooleanFull purge onlyfalseMust be true with purgeEverything.

Typed inputs override matching allowlisted record fields. Create always requires validated type, name, and content. Update requires at least one allowlisted field and cannot pass headers, authentication, arbitrary URLs, or unsupported provider properties.

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation name.
attemptsintegerAlwaysTotal provider attempts across pages.
httpStatusintegerProvider respondedLast Cloudflare HTTP status.
dataobjectSingle-resource/mutation successCloudflare result object or scalar.
id, name, providerStatusstringProvider returns fieldSafe convenience fields.
items / countarray / integerList successBounded provider resources and emitted count.
hasMore / nextPageboolean / integerList successProvider continuation state.
requestIdstringProvider supplies oneCloudflare Ray ID or provider trace reference.
errorobjectFailureSafe {code, message, httpStatus?, retryable} details.

Tokens and authorization headers never enter outputs. Provider messages pass through ValkyrAI's shared workflow sensitive-data policy.

IntegrationAccount Requirements

SettingRequirement
ProviderCloudflare API v4
AuthenticationScoped API token sent as Authorization: Bearer …
accountNameHuman-readable automation identity
accountIdOptional Cloudflare account reference for operators; not used as a credential
apiKeyPreferred encrypted SecureField containing the token
passwordEncrypted fallback only; prefer apiKey
statusMust be READY

Recommended least-privilege token permissions depend on selected operations:

  • token verification: the token itself must be active;
  • zone discovery: Zone / Zone / Read;
  • DNS reads: Zone / DNS / Read;
  • DNS writes: Zone / DNS / Edit;
  • cache purge: Zone / Cache Purge / Purge;
  • zone setting writes: Zone / Zone Settings / Edit.

Do not use a Global API key. Token creation, rotation, revocation, and OAuth refresh belong to the platform IntegrationAccount lifecycle, never workflow inputs.

Configuration

{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:cloudflare-production-dns"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 1000,
"maxDelayMs": 60000,
"jitter": false
},
"executionConfig": {"timeoutMs": 30000},
"payloadConfig": {
"parameters": "{\"operation\":\"list_dns_records\",\"zoneId\":\"023e105f4ecef8ad9ca31a8372d0c353\",\"type\":\"CNAME\",\"limit\":100}"
}
}

The integration-account value is symbolic. Persisted workflows use the generated relationship and never a plaintext token.

Operations

OperationCloudflare behaviorSide effect
verify_tokenReads the current scoped token status.Read-only; safe retries.
list_zonesLists zones with bounded account, name, status, and match filters.Read-only; safe retries.
get_zoneReads one zone.Read-only; safe retries.
list_dns_recordsLists records with bounded name, type, content, proxy, and match filters.Read-only; safe retries.
get_dns_recordReads one DNS record.Read-only; safe retries.
create_dns_recordCreates one allowlisted record.New DNS state; single attempt.
update_dns_recordPartially updates allowlisted record fields.DNS mutation; single attempt.
delete_dns_recordPermanently removes a record after confirmDelete=true.Destructive; single attempt.
purge_cachePurges exactly one selector: files, tags, hosts, prefixes, or the entire zone.Cache invalidation; single attempt.
get_zone_settingReads one allowlisted zone setting.Read-only; safe retries.
update_zone_settingUpdates one allowlisted zone setting.Configuration mutation; single attempt.

Errors and Failure Modes

CodeTypical causeRetryableResolution
VALIDATION_ERRORMissing/invalid account, ID, DNS name/type/content, setting, selector, confirmation, JSON, or bound.NoCorrect input; no unsafe request was sent.
UNSUPPORTED_OPERATIONUnknown operation.NoSelect a documented operation.
INTEGRATION_ACCOUNT_REQUIREDNo bound account.NoBind a Cloudflare IntegrationAccount.
INTEGRATION_ACCOUNT_NOT_READYAccount is not READY.NoRepair or reconnect the account.
CLOUDFLARE_API_ERRORHTTP succeeded but Cloudflare returned success: false.No by defaultInspect the safe provider code/message and correct scope or payload.
CLOUDFLARE_HTTP_400Provider rejected a filter or payload.NoCorrect the bounded request.
CLOUDFLARE_HTTP_401 / 403Token invalid, inactive, or missing minimum scope.NoRotate or re-scope the token.
CLOUDFLARE_HTTP_404Zone, record, or setting is absent or invisible.NoRe-run discovery with the same account.
CLOUDFLARE_HTTP_429 / 5xxRate limit or transient provider failure.Yes for GETHonor provider timing; reconcile writes before repeating.
NETWORK_ERRORTimeout, DNS, TLS, or connectivity failure.Yes for GETVerify connectivity and inspect Cloudflare state before repeating a write.
RESPONSE_TOO_LARGEResponse exceeded 5 MiB.NoNarrow filters or lower the limit.
INVALID_PROVIDER_RESPONSEsuccess, result, list shape, or pagination is inconsistent.NoUse requestId and verify API compatibility.

Example

Create a proxied CNAME after a deployment workflow verifies the origin health:

{
"operation": "create_dns_record",
"zoneId": "023e105f4ecef8ad9ca31a8372d0c353",
"type": "CNAME",
"name": "api.example.com",
"content": "origin.example.net",
"ttl": 1,
"proxied": true,
"comment": "Managed by ValkyrAI deployment workflow"
}

Expected result:

{
"status": "success",
"operation": "create_dns_record",
"attempts": 1,
"httpStatus": 200,
"id": "372e67954025e0ba6aaa6d586b9e0b59",
"name": "api.example.com",
"data": {
"id": "372e67954025e0ba6aaa6d586b9e0b59",
"type": "CNAME",
"name": "api.example.com",
"content": "origin.example.net",
"proxied": true
}
}

Notes

  • Pagination: zone and DNS lists use page, per_page, and result_info.total_pages. Pages request at most 100 resources and total output never exceeds 10,000. An empty page before total_pages fails closed.
  • Rate limits: GET operations retry HTTP 408, 429, 500, 502, 503, and 504 according to RetryPolicy, honoring numeric Retry-After. Creates, updates, deletes, setting changes, and purges never retry automatically.
  • API limits: provider responses are capped at 5 MiB, structured DNS bodies at 256 KiB, setting bodies at 16 KiB, purge selectors at 30 values, and text fields at their documented module bounds. Cloudflare plan and account limits still apply.
  • Idempotency: reads are retry-safe. DNS creates, partial updates, deletes, setting changes, and cache purges are single-attempt. Re-read the zone, record, setting, or cache state before repeating a request whose response was lost.
  • Destructive behavior: DNS deletion requires confirmDelete=true. A full cache purge requires both purgeEverything=true and confirmPurgeEverything=true. purge_cache accepts exactly one selector to prevent unintended broadening.
  • Security: credentials remain in IntegrationAccount SecureFields. The fixed Cloudflare API origin, encoded path segments, allowlisted payloads/settings, bounded responses, and redacted errors prevent arbitrary routing or token reflection.
  • External verification: request construction, pagination, validation, retry safety, redaction, payload mapping, destructive guards, and metadata discovery are deterministic local tests. Live Cloudflare scopes, plan entitlements, DNS propagation, proxy behavior, and cache invalidation require separately authorized provider credentials and are not exercised in repository tests.
  • Deferred operations: zone create/delete, account administration, Workers, R2, Pages, Access, WAF rulesets, load balancing, tunnels, SSL certificate upload, analytics, webhooks/triggers, legacy Global API key auth, and arbitrary raw requests.
  • Functional references: n8n Cloudflare node source, Cloudflare zone API, Cloudflare DNS records API, and Cloudflare cache purge API.