Cloudflare
Connect Cloudflare with an API token or OAuth app to call REST endpoints and receive supported alerts.
What your agents can do
Helios uses a pinned version of Cloudflare's OpenAPI spec to look up REST endpoints. It attaches your token or OAuth credentials to API calls. Access depends on the token's permissions or the OAuth scopes you approve.
- Create, update, and delete DNS records, and change zone settings such as the security level
- Purge cached files after a deploy
- Inspect Workers, their versions and deployments, and set secrets
- Read and write Workers KV, manage R2 buckets, and query D1 databases
- Manage Access applications, WAF rules, and Cloudflare Tunnels
Agents can also produce and consume K2 stream records on each stream's own host, <STREAM_ID>.k2.cloudflarestorage.com. These calls need the full stream URL and an API token with the K2 Produce or K2 Consume permission. The GraphQL Analytics API is not included in endpoint lookup.
Authentication
| Method | Type | Description |
|---|---|---|
| Helios Cloudflare App | OAuth 2.0 | Helios's Cloudflare app, plus your account ID. You don't need to create an app |
| Cloudflare API Token | API Key | A Cloudflare account or user API token, plus your account ID |
| Your own Cloudflare OAuth app | OAuth 2.0 | An OAuth client you create in your Cloudflare account, plus your account ID |
See Integration authentication for how credentials are stored and injected.
Every method needs your account ID. In the Cloudflare dashboard, open Workers & Pages and copy Account ID from Account Details.
Helios Cloudflare App
Connect through Helios's Cloudflare app. You don't need to create an app in Cloudflare.
- In Helios, choose Helios Cloudflare App.
- Enter Account ID. Turn on Admin access to also ask for the admin scopes.
- Save, then approve access in Cloudflare. On the consent screen, choose the account whose ID you entered. If you leave it out, Helios doesn't save the connection and asks you to check the account ID.
Helios asks for every scope listed under Scopes Helios asks for below, and for the admin scopes when Admin access is on. Helios refreshes the access token when it expires. To change Admin access, edit it through Manage and connect again.
If Cloudflare refuses the authorization, an admin of your Cloudflare account may have turned off third-party apps. A Super Administrator can turn them on under Manage Account → Members → Settings → Public OAuth App access.
Cloudflare API Token
To create an account API token, you need the Super Administrator role or the API Token Provisioning capability. Any member can create a user token, which acts as that member. A token can only have permissions that its creator has.
- In the Cloudflare dashboard, go to Manage account → Account API tokens and select Create Token. A user token from My Profile → API Tokens also works.
- Select Create Custom Token and add permissions:
- For full access, add every permission group under Account and Zone, each at its highest level, such as Edit. For a user token, also add the User permissions. Cloudflare lists them all in API token permissions.
- Triggers need Notifications Edit. Alerts that Cloudflare limits to chosen zones also need Zone Read, and Pages alerts need Cloudflare Pages Read.
- Under Zone Resources, include all zones from the account.
- Select Continue to summary, then Create Token, and copy the token.
- In Helios, choose Cloudflare API Token. Enter Account ID, paste the token into API Token, and save.
A token with fewer permissions still works for the endpoints those permissions cover. For user tokens, the connection test verifies token validity. Account access is checked when you call account endpoints or set up triggers. If the token expires or you roll it, enter the new one through Manage. If you add permissions for more alerts, save the connection again so Helios creates them.
Cloudflare suggests account API tokens for integrations like this one. They keep working after the person who created them leaves your Cloudflare account.
Your own Cloudflare OAuth app
To create an OAuth client, you need the Super Administrator, Administrator, or OAuth Client Write role.
-
In the Cloudflare dashboard, go to Manage Account → OAuth clients and select Create client.
-
Enter a client name. Set the response type to
code, the grant types toauthorization_codeandrefresh_token, and the token authentication method toclient_secret_basic. With therefresh_tokengrant, Cloudflare adds theoffline_accessscope that Helios needs for a refresh token. -
Add this redirect URL:
https://api.heliosapp.com/integrations/cloudflare/oauth_callback -
Select Continue and add every scope in the table below. Helios asks for all of them, so the client needs every one. To let people decline some scopes on the consent screen, turn off Required for those scopes under Choose optional scopes.
-
If you'll turn on Admin access, also add
account-api-tokens.write,account-settings.write, andscim-provisioning.write. -
Select Create client and copy the Client ID and Client Secret. Cloudflare shows the secret only once.
-
In Helios, choose Your own Cloudflare OAuth app. Enter Account ID, Client ID, and Client Secret. Turn on Admin access to also ask for the admin scopes.
-
Save, then approve access in Cloudflare. Select the same account on the consent screen.
Admin access adds the scopes that manage the account itself: account-api-tokens.write creates and edits account API tokens, account-settings.write changes account settings and members, and scim-provisioning.write provisions members through SCIM. Cloudflare lets only a Super Administrator manage members and create account API tokens.
Cloudflare's list of OAuth scopes has no billing scopes, so OAuth connections can't read or change billing. Use an API token with the billing permissions for that.
A new client is private, so only members of your Cloudflare account can approve it. Helios refreshes the access token when it expires. If you rotate the client secret, enter the new one through Manage and connect again. To change Admin access, edit it through Manage and connect again.
Triggers
Cloudflare can start a Workflow when it sends an alert. Webhooks are available on all Cloudflare plans. When you save the connection, Helios adds a webhook destination named Helios to your account. It attempts to create an alert named Helios: ... for each supported alert type your account offers. Deleting the connection removes the alerts and the destination.
This needs the Notifications Edit permission on the token, or the notifications.write scope for an OAuth app. Without it, agents still work, but no events reach Helios.
Each supported alert type has its own event:
| Event | Description | Filters |
|---|---|---|
abuse_report_alert.sent | Someone filed an abuse report against a website in the account | none |
access_custom_certificate_expiration_type.sent | An Access mTLS certificate expires in 30 or 14 days | zone |
advanced_ddos_attack_l4_alert.sent | Cloudflare mitigated a Layer 3/4 DDoS attack above the configured packet rate | none |
advanced_ddos_attack_l7_alert.sent | Cloudflare mitigated an HTTP DDoS attack above the configured request rate | zone |
advanced_http_alert_error.sent | Cloudflare detected a rise in edge or origin errors | zone |
bgp_hijack_notification.sent | Your IP prefixes were advertised where they should not be | none |
billing_budget_alert.sent | Usage charges reached a budget threshold you set | none |
billing_usage_alert.sent | A product's usage went above a threshold you set | none |
block_notification_block_removed.sent | Cloudflare Trust & Safety removed a block from a website | none |
block_notification_new_block.sent | Cloudflare Trust & Safety placed a block on a website | none |
block_notification_review_rejected.sent | Cloudflare Trust & Safety rejected a request to remove a block | none |
bot_traffic_basic_alert.sent | Cloudflare detected a spike in bot traffic on a zone | zone |
brand_protection_alert.sent | A saved Brand Protection query matched a new domain | none |
brand_protection_digest.sent | A digest of the domains that match saved Brand Protection queries | none |
casb_weekly_digest.sent | A weekly digest of CASB findings | none |
clickhouse_alert_fw_anomaly.sent | Security events spiked on a zone | zone |
clickhouse_alert_fw_ent_anomaly.sent | Security events from the chosen services spiked on a zone | zone |
closed_port_scan_alert.sent | Cloudflare detected newly closed ports | none |
cloudforce_one_request_notification.sent | Cloudflare sent a Cloudforce One request notification | none |
cni_maintenance_notification.sent | Maintenance is planned that might affect a Classic CNI connection | none |
containers_security_alert.sent | Cloudforce One found a potential threat in Containers | none |
custom_analytics.sent | A Custom Alert's SQL query met its detection criteria | none |
custom_bot_detection_alert.sent | Cloudflare detected a spike in bot traffic on a zone | zone |
custom_ssl_certificate_event_type.sent | A custom hostname certificate was validated, issued or renewed, or is expiring | zone |
dedicated_ssl_certificate_event_type.sent | An advanced certificate was validated, issued or renewed, or is expiring | zone |
device_connectivity_anomaly_alert.sent | The number of devices connected to the WARP client spiked or dropped | none |
dos_attack_l4.sent | Cloudflare mitigated a Layer 3/4 DDoS attack | none |
dos_attack_l7.sent | Cloudflare mitigated an HTTP DDoS attack on a zone | zone |
expiring_service_token_alert.sent | An Access service token expires soon | none |
failing_logpush_job_disabled_alert.sent | Cloudflare disabled a Logpush job that kept failing | none |
fbm_auto_advertisement.sent | Magic Transit started advertising prefixes after an attack | none |
fbm_dosd_attack.sent | Network flow data shows a DDoS attack | none |
fbm_volumetric_attack.sent | Network flow data shows a volumetric attack | none |
health_check_status_notification.sent | A health check's origin became healthy or unhealthy | zone |
hostname_aop_custom_certificate_expiration_type.sent | A hostname-level Authenticated Origin Pulls certificate expires in 30 or 14 days | zone |
http_alert_edge_error.sent | Cloudflare sent an edge error rate alert | zone |
http_alert_origin_error.sent | Cloudflare could not reach the origin for more requests than usual | zone |
image_notification.sent | Cloudflare Images sent a notification about a direct creator upload | none |
image_resizing_notification.sent | The account used up its free image transformations | none |
incident_alert.sent | A Cloudflare incident was created, updated or resolved | none |
leaked_service_token_alert.sent | An Access service token was detected as leaked | none |
load_balancing_health_alert.sent | A load balancer pool or origin became healthy or unhealthy | none |
load_balancing_pool_enablement_alert.sent | A load balancer pool was enabled or disabled | none |
log_explorer_scheduled_query_results_alert.sent | A scheduled Log Explorer query returned results | none |
logo_match_alert.sent | Security Center found a new domain that uses an uploaded logo | none |
magic_tunnel_health_check_event.sent | A Magic Tunnel's health check success rate dropped below its SLO | none |
magic_wan_tunnel_health.sent | An IPsec or GRE tunnel's health check success rate dropped below its SLO | none |
maintenance_event_notification.sent | Maintenance at a Cloudflare data center was scheduled, changed or canceled | none |
mtls_certificate_store_certificate_expiration_type.sent | A certificate uploaded for mTLS expires in 30 or 14 days | none |
open_port_scan_alert.sent | Cloudflare detected newly open ports | none |
pages_event_alert.sent | A Pages deployment started, failed or succeeded | none |
radar_notification.sent | Radar found a traffic anomaly, outage, route hijack or route leak for a location or network | none |
real_origin_monitoring.sent | Cloudflare cannot reach an origin | zone |
scriptmonitor_alert_new_code_change_detections.sent | The code of a monitored script changed | zone |
scriptmonitor_alert_new_hosts.sent | A page loaded a resource from a domain not seen before | zone |
scriptmonitor_alert_new_malicious_hosts.sent | A page loaded a resource from a domain reported as malicious | zone |
scriptmonitor_alert_new_malicious_scripts.sent | Cloudflare classified a script on a page as malicious | zone |
scriptmonitor_alert_new_malicious_url.sent | A page loaded a resource from a URL reported as malicious | zone |
scriptmonitor_alert_new_max_length_resource_url.sent | A page loaded a resource whose URL is longer than the maximum | zone |
scriptmonitor_alert_new_resources.sent | A page loaded a resource not seen before | zone |
secondary_dns_all_primaries_failing.sent | Every primary nameserver of a secondary zone is failing | zone |
secondary_dns_primaries_failing.sent | A primary nameserver of a secondary zone is failing | zone |
secondary_dns_warning.sent | A transferred zone issued a warning | zone |
secondary_dns_zone_successfully_updated.sent | A zone transfer to a secondary zone succeeded | zone |
secondary_dns_zone_validation_warning.sent | Cloudflare sent a secondary DNS zone validation warning | zone |
security_insights_alert.sent | Security Center found a new security insight | none |
sentinel_alert.sent | Cloudflare sent a Sentinel alert | none |
stakeout_credential_leak_alert.sent | Cloudforce One found leaked credentials that match your domain | none |
stakeout_saved_query_daily_digest_alert.sent | A daily digest of new threat events for a saved query | none |
stakeout_saved_query_immediate_alert.sent | Cloudforce One found new threat events for a saved query | none |
stream_live_notifications.sent | A Stream live input changed state | none |
synthetic_test_latency_alert.sent | A DEX test's latency spiked or dropped | none |
synthetic_test_low_availability_alert.sent | A DEX test's success rate dropped below its SLO | none |
traffic_anomalies_alert.sent | A zone's traffic spiked or dropped unexpectedly | zone |
tunnel_health_event.sent | A Cloudflare Tunnel's health status changed | none |
tunnel_update_event.sent | A Cloudflare Tunnel was created or deleted | none |
universal_ssl_event_type.sent | A Universal SSL certificate was validated, issued or renewed, or is expiring | zone |
web_analytics_metrics_update.sent | Cloudflare sent the weekly Web Analytics summary of a site | none |
workers_observability_alert.sent | A Workers Observability alert started firing or returned to normal | none |
workers_observability_real_time_issue.sent | Workers Observability detected an issue on a Worker | none |
zone_aop_custom_certificate_expiration_type.sent | A zone-level Authenticated Origin Pulls certificate expires in 30 or 14 days | zone |
- Zone matches the zone that the alert is about, chosen from your zones. It's optional. Alerts that aren't about a zone never match a zone filter.
Cloudflare offers each alert type only on some plans or with some products. The trigger picker marks the events your account doesn't offer as unavailable, with the reason.
Some alert types need filters. Helios uses the values listed by Cloudflare, known status values, or resources it can list in your account:
- Health check status alerts cover healthy and unhealthy changes.
- Pool enablement alerts cover pools being enabled and disabled.
- Pages alerts cover the projects Helios lists, both environments, and deployments that start, fail, or succeed.
- Alerts that require chosen zones cover the zones Helios lists in the account.
Helios reads up to 1,000 zones and 200 Pages projects when you save the connection. Save the connection again after you add a zone or a Pages project.
Some alert types need a value that only you can choose, such as a usage threshold, a budget, a service-level objective, a saved query, or a custom alert's SQL query. Helios can't create those alerts, so the trigger picker shows them as unavailable.
Some alerts send one notification when they start and another when they end. The payload's alert_event field is ALERT_STATE_EVENT_START or ALERT_STATE_EVENT_END, so say in the prompt which one the agent should act on.
Helios manages the alerts that send to the Helios destination. It updates them each time the connection is saved, so edits you make to them in Cloudflare don't last. If Helios can't update an alert it created before, it keeps the old alert, and the event stays available.
An agent's fix can lead to another alert. For example, an origin that the agent brings back can send a health check alert when it turns healthy, which starts another run. A Pages deployment that the agent starts sends its own deployment alerts. Say in the prompt which alerts to ignore, such as ALERT_STATE_EVENT_END events or origins that are healthy. See Guarding against events you don't want.
Cloudflare doesn't sign notifications. It sends the destination's secret in the cf-webhook-auth header, and Helios compares it with the secret it generated for the connection. Notifications whose ts is more than an hour old are rejected.
Check that it works
- The connection: after you save, the connection's status shows Connected. Error means Cloudflare rejected the token, or the token can't reach the account ID.
- The destination: in the Cloudflare dashboard, go to Alerts → Destinations. The Webhooks card should list Helios. Under Alerts → Overview, the Helios: ... alerts should be listed.
- A trigger:
- Add
universal_ssl_event_type.sentto a workflow with no filters. Any event works if your account offers it. - In Alerts → Overview, open the menu of the matching Helios: ... alert and choose Test. Cloudflare sends a test alert with sample data.
- Check that a run starts. Then open the connection in Helios and click Webhook events to see the event.
- Add
Common errors
| What you see | Cause | Fix |
|---|---|---|
The Cloudflare API token is … | The token is disabled or expired | Create a new token and enter it through Manage |
Cloudflare did not allow access to account … Check the account ID. | Account ID is wrong, or the token or OAuth approval doesn't cover that account | Copy the account ID from Workers & Pages, and select the same account on the consent screen |
Cloudflare access token not found. Finish connecting the OAuth app first. | The OAuth approval wasn't finished | Open the connection and connect again |
| Cloudflare refuses the sign-in | The OAuth client doesn't have every scope that Helios asks for | Add every scope from the table to the client, then connect again |
| No Helios destination under Alerts → Destinations, and no runs start | The token lacks Notifications Edit, or the OAuth app lacks notifications.write. Helios reports this as Cloudflare did not save the webhook destination | Add the permission, then save the connection again |
| An event is unavailable in the trigger picker | The account doesn't offer the alert, the alert needs a value you choose, or Cloudflare rejected it. The picker shows which | Get the plan or product that offers it, or add the missing permission and save the connection again |
An agent gets 403 from an endpoint | The token or OAuth app lacks the permission for it | Add the permission to the token, or the scope to the OAuth client and connect again |
| No run starts, and the alert looks fine | The zone filter doesn't match, or the alert is about a zone or Pages project added after you saved the connection | Try the trigger with no filters, and save the connection again |
Limits
Cloudflare allows 1,200 API requests per five minutes for each user or account token, across the dashboard and the API. Accounts without a paid zone can have up to 100 webhook destinations. See Cloudflare's API rate limits and webhook setup.
Last updated on
Zoho CRM
The Zoho CRM integration lets Helios agents call the Zoho CRM REST API through your own OAuth app, and run agents automatically when records in Zoho CRM's built-in modules are created, updated, or deleted.
Discord
The Discord integration lets Helios agents interact with Discord to read/send messages, manage channels, automate community interactions and much more.