Connect Cloudflare in Composio

Use this when an agent needs Cloudflare DNS, zones, or Access through Composio (custom domains, team.docs hostnames, email MX, orange-cloud vs grey-cloud). MCP install is separate: Composio MCP setup.

Credential vocabulary: API key vs token. GitHub Pages + Cloudflare HTTPS: GitHub Pages custom domain.

Two Composio apps that look the same

Composio lists Cloudflare and Cloudflare API Key as nearly identical catalog entries. Tool metadata may even call the first one "OAuth." Trust the connect form, not the catalog name.

Observed connect screens (verbatim fields):

Composio toolkit Form asks for Cloudflare secret that belongs there

Cloudflare

Global API Key and Cloudflare account email

My Profile → API Tokens → Global API Key, plus the login email for that account

Cloudflare API Key

Cloudflare API token (key-only field; no email)

A Cloudflare API Token from My Profile → API Tokens → Create Token. Not the Global API Key.

Connect one. Putting a Global API Key into the key-only app (or an API Token into the email + Global API Key app) still shows ACTIVE, then zone calls fail with Cloudflare 9109 Invalid access token. Composio has no refresh for a wrong-kind secret. Disconnect and reconnect on the matching toolkit.

Why 9109 happens

Cloudflare’s HTTP auth is two different schemes:

  • Global API Key — X-Auth-Email + X-Auth-Key. Needs the email. That is the Cloudflare Composio app.

  • API Token — Authorization: Bearer …​. No email. That is the Cloudflare API Key Composio app.

Send a Global API Key as a Bearer token (or a token as X-Auth-Key without email) and Cloudflare answers 9109.

Architectural types (API key vs token): both of these dashboard secrets are API keys (long-lived). Cloudflare’s "API Token" is a scoped API key, not an OAuth access token. Composio may still file the first toolkit under an "OAuth" slug.

Minimum scopes for DNS work on an API Token

Zone:Read to list; Zone:Edit (DNS) to create/update records.

Access is a different permission set. A Pages-scoped token (typical wrangler pages deploy secret) can look healthy and still fail Access:

  • GET /accounts/{account_id}/access/apps200 with an empty list

  • GET …​/access/identity_providers, …​/organizations, …​/policies403 / 10000 Authentication error

Use the Cloudflare toolkit (Global API Key + email) for Access writes, or mint a token that includes Access: Apps and Policies and Access: Organizations / Identity Providers. Do not create Access applications until a GitHub identity provider exists (GitHub OAuth Apps have no create API — an operator pastes Client ID/secret). Order and mocks: Protect a static site with Cloudflare Access · Agents and API credentials.

Pages API token 403s on Access IdPs; Global API Key can write Access
Figure 1. Pages-scoped token vs Global API Key (redacted)

ACTIVE is not a smoke test

Composio ACTIVE means "we stored something." It does not mean Cloudflare accepted it.

  1. After connect, run a real list: zones for the intended domain (e.g. devcentr.org).

  2. Success: zone id, name, status.

  3. 9109 Invalid access token — wrong toolkit or wrong secret kind. Match the table above.

  4. 10502 Too many authentication failures — Cloudflare rate-limited the bad attempts. Wait several minutes; do not hammer retries.

Machine does not matter. Composio stores the credential server-side; a connection that "worked on the laptop" is the same object on every studio.

After it lists zones

Typical next steps (confirm with the user before writes):

  1. List DNS records on the zone (name filter for the hostname).

  2. Create or update records only after an explicit go-ahead.

  3. For GitHub Pages custom domains, keep the Pages hostname DNS-only (grey cloud) while GitHub issues Let’s Encrypt — see GitHub Pages custom domain.