# Use Cloudflare

```yaml
capability_id: cloudflare.use
display_name: Use general Cloudflare API relay
ui_capability_key: use_cloudflare_relay
scope: cloudflare:use
endpoint:
  method: POST
  path: /cloudflare/request
operation: cloudflare.request
billable: true
environment: none
credential:
  name: CLOUDFLARE_API_TOKEN
  kind: encrypted_provider_credential
```

## Purpose and authorization

The `cloudflare:use` scope authorizes an authenticated application to send
bounded native Cloudflare REST API requests through Gateman. Gateman
authenticates the application, checks the scope, retrieves the application's
encrypted `CLOUDFLARE_API_TOKEN`, injects bearer authentication, executes the
request against Cloudflare API v4, and returns the bounded native response.

Cloudflare remains authoritative for account, zone, resource, and operation
permissions. Gateman does not create Cloudflare permission scopes and does not
replace Cloudflare's API-token or account authorization model.

This is a provider-specific HTTP relay, not an infrastructure-as-code system,
Cloudflare resource manager, generic workflow engine, or Cloudflare SDK
abstraction. It does not automatically discover resources, paginate results,
retry requests, reconcile mutations, or interpret Cloudflare policy results.
The application must use [Contract
v1](https://docs.getgateman.com/contract-v1/) and hold `cloudflare:use`.

## Implementation contract

```http
POST /cloudflare/request
Content-Type: application/json
X-GM-App: app_...
X-GM-Ts: 1710000000
X-GM-Sig: <Contract-v1-signature>
X-GM-Idempotency-Key: optional-gateman-key
```

The outer request is authenticated with Contract v1. The optional
`X-GM-Idempotency-Key` is part of the signed Contract v1 input, but this
capability has no Gateman replay ledger and does not deduplicate or make a
Cloudflare request safe to repeat. Cloudflare endpoint-specific semantics, if
any, remain the provider's responsibility.

The outer JSON body contains the native Cloudflare request envelope. It is
validated by Gateman and then translated only into the fixed Cloudflare API v4
origin plus the supplied relative path, encoded query, supported headers, and
body.

The Official PHP, Node.js, Python, and Go clients all support this generic
authenticated request contract and can call `/cloudflare/request`. No
Cloudflare-specific Gateman client helper is required; agents must not invent
provider-specific helper methods.

## Request schema

| Field | Required | Contract |
| --- | --- | --- |
| `method` | No | String; defaults to `POST`; case-insensitive `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`. |
| `path` | Yes | String beginning with `/`, at least 2 bytes and no more than 2,048 bytes. It must not contain a query string, controls, spaces, `#`, `<`, `>`, quotes, backslashes, `..`, or `//`. |
| `query` | No | JSON object/map; defaults to `{}`. Keys are strings and values are scalars or arrays. |
| `headers` | No | JSON object/map; defaults to `{}`. Only the six headers listed below are accepted. |
| `body` | No | String or JSON object/array; defaults to `""`. Structured values are serialized as JSON. |
| `body_encoding` | No | `utf8` or strict `base64`; defaults to `utf8`. |

Unknown top-level fields are ignored by the current validator. Integrations
should send only the documented fields. Invalid JSON, invalid field types,
unsupported methods, invalid paths, invalid headers, invalid base64, and
oversized bodies are rejected before the provider request.

### Fixed destination and path

Gateman always uses:

```text
https://api.cloudflare.com/client/v4
```

The caller cannot select an origin, host, scheme, port, proxy, redirect
destination, or absolute URL. Supply only the relative path. Put parameters in
`query`; do not append `?` or a raw query string to `path`.

### Query encoding

`query` is encoded with PHP RFC 3986 query encoding and appended to the
validated path. The encoded query is limited to 2,048 bytes independently of
the path. Array values use the serializer's indexed/bracket representation.
The field is a structured map, not a raw query string, and duplicate query
keys cannot be represented independently.

### Accepted request headers

The caller may provide only these headers, with case-insensitive names:

- `Accept`
- `Content-Type`
- `If-Match`
- `If-None-Match`
- `Prefer`
- `X-Audit-Log`

Header values must be strings and must not contain carriage returns or line
feeds. The total caller-provided header name/value data is limited to 16 KiB.
`Authorization`, `Host`, `Cookie`, proxy headers, content-length and transfer
framing headers, and arbitrary Cloudflare headers are rejected. Gateman adds
`Authorization: Bearer ...` from the protected application credential; the
caller cannot replace it.

### Body serialization

- A string with `body_encoding: utf8` is forwarded as supplied.
- A JSON object or array is serialized with unescaped slashes and Unicode.
- A string with `body_encoding: base64` is strictly decoded before forwarding.
- The decoded body must be no larger than 1 MiB (1,048,576 bytes).
- A non-empty body with no `Content-Type` receives
  `Content-Type: application/json`.
- A caller-provided accepted `Content-Type` is preserved.

The nested body is not parsed for Cloudflare semantics after serialization.
Cloudflare validates the native JSON document, form, or other representation.
Multipart form-data and arbitrary binary upload contracts are not supported by
this envelope.

## Cloudflare-native compatibility

This relay forwards native Cloudflare REST requests; it does not expose an
operation-name or resource abstraction. Representative control-plane families
that fit the contract include:

| Family | Representative bounded use |
| --- | --- |
| Accounts | List accounts, inspect an account, and follow Cloudflare pagination. |
| Zones | List zones and inspect a zone. |
| DNS records | List, create, update, and delete records using native JSON bodies and resource paths. |
| Zone settings | Inspect or update supported zone settings. |
| Rulesets and WAF | List and update rulesets using Cloudflare's native nested JSON. |
| Cache | Submit supported cache-purge requests with native JSON. |
| Access | Inspect Access applications and manage supported policies. |
| Workers configuration | Inspect or update supported routes and account/worker settings. |
| Token verification | Verify the configured Cloudflare API token with the native user-token endpoint. |

These are compatibility examples, not a Gateman allowlist or a guarantee
that every Cloudflare operation is representable. Cloudflare's current API
documentation, token permissions, account context, and resource state remain
authoritative.

## Administrative examples

The following are illustrative nested request envelopes. They use placeholders,
not real account, zone, record, ruleset, or application identifiers. Each is
sent as the authenticated body of `POST /cloudflare/request`.

### List accounts

```json
{
  "method": "GET",
  "path": "/accounts",
  "query": {
    "page": 1,
    "per_page": 50
  }
}
```

### Inspect DNS records

```json
{
  "method": "GET",
  "path": "/zones/zone_example_id/dns_records",
  "query": {
    "page": 1,
    "per_page": 100,
    "type": "A"
  },
  "headers": {
    "Accept": "application/json"
  }
}
```

### Update a DNS record

```json
{
  "method": "PATCH",
  "path": "/zones/zone_example_id/dns_records/record_example_id",
  "body": {
    "content": "192.0.2.10",
    "name": "www.example.com",
    "proxied": true,
    "ttl": 300,
    "type": "A"
  }
}
```

Because `body` is an array, Gateman serializes this example as JSON and adds
`Content-Type: application/json`. Cloudflare must authorize the mutation, and
the application should read the record afterward to verify the resulting state.

### Inspect a ruleset

Inspect a ruleset collection:

```json
{
  "method": "GET",
  "path": "/zones/zone_example_id/rulesets",
  "query": {
    "per_page": 100,
    "cursor": "<cursor_from_previous_response>"
  }
}
```

Inspect one existing ruleset:

```json
{
  "method": "GET",
  "path": "/zones/zone_example_id/rulesets/ruleset_example_id"
}
```

Inspect an existing ruleset before modifying it. Cloudflare ruleset update
operations may replace the existing rule collection, so construct mutations
using the exact provider API semantics and verify the resulting configuration.

## Live account-discovery compatibility

Live verification through the deployed Gateman route confirmed that an
appropriately permitted bearer API token can successfully call Cloudflare's
account-list endpoint and then retrieve account details using the returned
account identifier. Token verification also succeeded.

This conclusion is about the tested bearer-token configuration and route
compatibility. It is not a universal statement about every token or account.
Cloudflare token permissions still determine whether account discovery and
subsequent account-scoped operations are authorized. Do not add a legacy
`X-Auth-Email` or `X-Auth-Key` requirement to an integration based on older
Cloudflare examples; Gateman supplies the configured bearer token.

## Workers and large-transfer boundary

Workers route and settings requests that fit this JSON/HTTP contract can use
the relay. This capability does not provide a general Workers script or static
asset deployment transport. In particular, do not assume that multipart
uploads, streaming uploads, large script bundles, large asset transfers, or
deployment-specific upload protocols fit the relay.

Use a provider-native or dedicated transfer path when Cloudflare's Workers
operation requires multipart, streaming, a large body, or a deployment
protocol outside this request envelope. Do not work around the relay's limits
by splitting or replaying a mutation without understanding the provider's
semantics.

## Response contract

For a provider response within the transport limit, Gateman returns the native
Cloudflare HTTP status and raw response body. There is no universal Gateman
success envelope and no automatic JSON, XML, text, or binary interpretation.
Cloudflare 4xx and 5xx responses remain native Cloudflare responses.

Only these provider response headers are forwarded when present:

- `content-type`
- `content-encoding`
- `etag`
- `location`
- `retry-after`
- `ratelimit`
- `ratelimit-policy`
- `x-amzn-requestid`
- `x-amz-request-id`
- `x-request-id`
- `cf-ray`

Gateman does not forward every Cloudflare response header. Redirects are
disabled, and the caller must interpret Cloudflare response fields, pagination,
validation errors, and provider rate limits.

### Response-size and compression behaviour

The maximum provider response body is 4 MiB (4,194,304 bytes). Gateman's
transport disables automatic decompression and enforces this limit while
receiving the provider representation. Therefore compressed bytes count
toward the transport ceiling; the limit is not a promise about the size of a
decompressed document. `content-encoding`, when supplied by Cloudflare, is
forwarded.

An oversized response is not returned partially. Gateman responds with HTTP
`502` and a Gateman JSON error such as:

```json
{
  "ok": false,
  "error": "Provider response exceeded Gateman transport limits"
}
```

Failure to return a response does not prove that Cloudflare did not receive or
execute a mutation.

## Credentials and Cloudflare authorization

The application-scoped encrypted provider credential is:

- `CLOUDFLARE_API_TOKEN`

Gateman retrieves it internally and sends it only as the provider bearer
credential. It never returns the token through `/cloudflare/request`. This
capability does not require `secrets:read`; generic application-secret
retrieval is a separate authorization path.

Do not put the Cloudflare token in source, configuration committed to an
application, prompts, logs, browser code, or client-visible request bodies.
Cloudflare API-token permissions decide which accounts, zones, resources, and
operations are available. Gateman does not broaden or replace them.

## Request and response limits

| Limit | Value |
| --- | ---: |
| Outer Gateman JSON envelope | 1,572,864 bytes (1.5 MiB) |
| Decoded Cloudflare request body | 1,048,576 bytes (1 MiB) |
| Cloudflare response representation | 4,194,304 bytes (4 MiB) |
| Request headers | 16 KiB |
| Path | 2,048 bytes |
| Encoded query | 2,048 bytes |
| Provider connect timeout | 5 seconds |
| Provider total timeout | 20 seconds |

These are Gateman transport limits, separate from Cloudflare API quotas,
pagination limits, and resource-specific constraints. Streaming, redirects,
multipart transfers, automatic pagination, and automatic retries are not part
of this capability.

## Operation accounting and concurrency

The billable operation is `cloudflare.request`. One invocation that passes
authentication, validation, provider admission, and monthly allowance checks
consumes one operation whether Cloudflare returns success, a native error, or
execution becomes uncertain.

Authentication failures, invalid envelopes, request-size rejections,
pre-admission concurrency rejections, provider-admission failures, and monthly
allowance rejections do not consume an operation. Credential lookup, network,
timeout, oversized-response, and Cloudflare 4xx/5xx failures occur after
admission and consume the operation.

Gateman may reject temporary application or provider-bound admission with
HTTP `429`, normally with `Retry-After`. An unavailable admission or accounting
dependency may return HTTP `503`. Monthly allowance exhaustion returns HTTP
`403` with `monthly_operation_limit_reached`. Internal slot capacities and
reservation implementation details are not part of this public contract.

The signed `X-GM-Idempotency-Key` does not change these accounting rules. It
does not create a replay record or prevent a second accepted provider request.

## Error matrix

| Condition | Response | Accounting | Provider execution |
| --- | --- | --- | --- |
| Invalid Contract v1 authentication or missing scope | `401` Gateman response | Before admission; no operation | Cloudflare was not called. |
| Authentication dependency unavailable | `503` Gateman response | Before admission; no operation | Cloudflare was not called. |
| Invalid JSON or invalid request envelope | `400` Gateman JSON | Before admission; no operation | Cloudflare was not called. |
| Outer envelope exceeds 1.5 MiB | `413` Gateman response | Before admission; no operation | Cloudflare was not called. |
| Invalid path, query, method, header, body, or body encoding | `400` Gateman JSON | Before admission; no operation | Cloudflare was not called. |
| Application/provider admission rejected | `429`, normally with `Retry-After` | Before operation admission; no operation | Cloudflare was not called. |
| Admission dependency unavailable | `503` Gateman JSON | Before operation admission; no operation | Cloudflare was not called. |
| Monthly allowance exhausted | `403` with `monthly_operation_limit_reached` | Before reservation; no operation | Cloudflare was not called. |
| Operation accounting unavailable | `503` with `Operation accounting unavailable` | No usable admission | Cloudflare was not called. |
| Missing credential or provider transport failure | `502` with `Cloudflare provider unavailable` | After admission; consumed | Cloudflare may not have been called or outcome may be uncertain. |
| Response exceeds 4 MiB | `502` with `Provider response exceeded Gateman transport limits` | After admission; consumed | Cloudflare may already have executed the request. |
| Cloudflare returns 4xx or 5xx | Native Cloudflare status and body | After admission; consumed | Cloudflare returned a response. |

Gateman-generated errors commonly use `{ "ok": false, "error": "..." }`.
Native Cloudflare responses do not use that envelope, and Cloudflare's own
error schema remains authoritative.

## Provider execution uncertainty

A timeout, connection failure after transmission, or oversized response can
return `502` even if Cloudflare received or executed the request. It is not a
safe-to-retry signal by itself. Inspect resource state, use any
Cloudflare-native idempotency or conditional request mechanism supported by
the selected endpoint, and verify mutations after uncertain outcomes.

Gateman does not automatically retry, replay, paginate, or reconcile
Cloudflare requests. `If-Match` and `If-None-Match` are available for
conditional requests where the Cloudflare endpoint supports them; Gateman does
not interpret their semantics.

## Environment behaviour

This capability is environment-independent. Its manifest has no `environment`
field, and the Official clients do not select a staging or development
Cloudflare credential for this route. The effective Cloudflare account,
zones, resources, and permissions are determined by the configured
application token and Cloudflare's authorization model.

An environment label in an application does not make this route a simulator
or test-mode endpoint. A permitted request reaches Cloudflare's real API and
may mutate real Cloudflare resources.

## Implementation outcome for agents

An integration should authenticate with Contract v1 and `cloudflare:use`,
construct the exact native Cloudflare REST request, call
`POST /cloudflare/request`, interpret the native status and body, follow
pagination explicitly, respect provider rate limits, use conditional or
provider-native safeguards where supported, and verify mutations. Keep the
Cloudflare token confidential and do not blindly retry uncertain operations.

## Implementation instructions for agents

- MUST use Contract v1 authentication and the `cloudflare:use` scope.
- MUST call `POST /cloudflare/request` with the documented envelope.
- MUST supply a relative path and structured `query`; never supply an origin,
  host, absolute URL, or raw query string in `path`.
- MUST use only `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`.
- MUST use only the six accepted nested request headers.
- MUST serialize JSON bodies as the nested `body` value or use strict base64
  for supported binary bytes within the request limit.
- MUST treat Cloudflare token permissions as authoritative.
- MUST handle native Cloudflare status codes, bodies, pagination, quotas, and
  errors.
- MUST respect the Workers upload, multipart, streaming, and large-transfer
  exclusions.
- MUST use conditional or provider-native idempotency mechanisms where the
  selected Cloudflare operation supports them.
- MUST NOT blindly retry timeouts, connection failures, or oversized responses.
- MUST account for one consumed `cloudflare.request` operation after admission.
- MUST keep `CLOUDFLARE_API_TOKEN` out of source, prompts, logs, and payloads.
- MUST NOT instruct agents to fetch the token and call Cloudflare directly;
  use the authenticated Gateman relay.
- MUST NOT invent Cloudflare-specific Official client helpers.

## Reusable AGENTS.md block

```markdown
<!-- gateman:begin capability=cloudflare.use -->
Use Cloudflare through Gateman's authenticated Contract v1 relay. The
application MUST hold `cloudflare:use` and MUST call `POST /cloudflare/request`.

The JSON envelope uses optional `method`, required relative `path`, optional
structured `query`, optional `headers`, optional `body`, and optional
`body_encoding` (`utf8` or strict `base64`). Supported methods are `GET`,
`POST`, `PUT`, `PATCH`, and `DELETE`. Only `Accept`, `Content-Type`, `If-Match`,
`If-None-Match`, `Prefer`, and `X-Audit-Log` may be supplied. Gateman injects
the protected bearer token; callers MUST NOT send credentials or authorization
headers.

Cloudflare API-token permissions remain authoritative. The envelope is limited
to 1.5 MiB, the decoded request body to 1 MiB, the response representation to
4 MiB, headers to 16 KiB, and path and encoded query to 2,048 bytes each.
Gateman does not automatically retry, paginate, stream, or provide multipart
or large Workers deployment transfers. Interpret native Cloudflare responses,
follow pagination, and verify mutations. A timeout, connection failure, or
oversized response can be uncertain; inspect provider state before retrying.
One admitted invocation consumes one `cloudflare.request` operation.

Do not instruct agents to retrieve the Cloudflare token and call Cloudflare
directly. Do not invent Cloudflare-specific Official client helpers. Use the
generic authenticated method exposed by each Official client.

Full reference: https://docs.getgateman.com/capabilities/cloudflare.use/
<!-- gateman:end capability=cloudflare.use -->
```

## Related references

- [Contract v1](https://docs.getgateman.com/contract-v1/)
- [Authentication and signing](https://docs.getgateman.com/authentication/)
- [Operation Accounting](https://docs.getgateman.com/operation-accounting/)
- [Rate limits and concurrency](https://docs.getgateman.com/rate-limits-and-concurrency/)
- [Idempotency](https://docs.getgateman.com/idempotency/)
- [Errors and responses](https://docs.getgateman.com/errors-and-responses/)
- [Official PHP client](https://docs.getgateman.com/canonical-client-php/)
- [Official Node.js client](https://docs.getgateman.com/canonical-client-node/)
- [Official Python client](https://docs.getgateman.com/canonical-client-python/)
- [Official Go client](https://docs.getgateman.com/canonical-client-go/)
- [Cloudflare API documentation](https://developers.cloudflare.com/api/)
