---
description: Identify and address API vulnerabilities with discovery, schema validation, and abuse detection.
title: Cloudflare API Shield
image: https://developers.cloudflare.com/api-shield/og.png?v=4def62fcf84999fc
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Cloudflare API Shield

Last updated Aug 19, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Identify and address your API vulnerabilities.

Enterprise-only paid add-on

Note

Enterprise customers can preview this product as a [non-contract service](https://developers.cloudflare.com/billing/understand/preview-services/), which provides full access, free of metered usage fees, limits, and certain other restrictions.

## Why care about API security?

APIs have become the [backbone of popular web services ↗︎](https://blog.postman.com/intro-to-apis-history-of-apis/), helping the Internet become more accessible and useful.

As APIs have become more prevalent, however, so have their problems:

- Many companies have [thousands of APIs](https://developers.cloudflare.com/api-shield/security/api-discovery/), including ones they do not even know about.
- To support a large base of users, many APIs are protected by a negative security model that makes them vulnerable to credential-stuffing attacks and automated scanning tools.
- With so many endpoints and users, it is difficult to recognize brute-force attacks against [specific endpoints](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/).
- Sophisticated attacks are even harder to recognize, often because even development teams are unaware of common and uncommon [usage patterns](https://developers.cloudflare.com/api-shield/security/sequence-analytics/).

Refer to the [Get started](https://developers.cloudflare.com/api-shield/get-started/) guide to set up API Shield.

## Features

[Security features](https://developers.cloudflare.com/api-shield/security/)

Secure your APIs using API Shield's security features.

Use Security features

[Management, monitoring, and more](https://developers.cloudflare.com/api-shield/management-and-monitoring/)

Monitor the health of your API endpoints.

Use Management, monitoring, and more

## Use Schema Profiles

[Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/) provides a shared detection, analytics, and mitigation model. Schema Profile is its only current profile type.

API Shield provides two Schema Profile sources. [Schema Learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) learns from traffic, while [Schema Validation](https://developers.cloudflare.com/api-shield/security/schema-validation/) uses uploaded OpenAPI schemas.

Use API Shield for API inventory, OpenAPI governance, profile export, automation, and higher-scale API workflows. Use the WAF Application Profiles pages for Profile Analysis and Custom Rule enforcement.

## Availability

Cloudflare API Security products are available to Enterprise customers only. Anyone can set up [Mutual TLS](https://developers.cloudflare.com/api-shield/security/mtls/) with a Cloudflare-managed certificate authority.

The full API Shield security suite is available as an Enterprise paid add-on. Refer to [API Shield plans](https://developers.cloudflare.com/api-shield/plans/) for feature-specific availability.

Customers with API Security already have access to Schema Profiles through Schema Learning and Schema Validation. Cloudflare is opening a closed beta to invited Enterprise customers without API Security. Interested customers can contact their account team to express interest. Closed beta access does not imply future plan availability or pricing.

Note

API Shield currently does not work for JDCloud customers.

## Related products

[DDoS Protection](https://developers.cloudflare.com/ddos-protection/)

Cloudflare DDoS protection secures websites, applications, and entire networks while ensuring the performance of legitimate traffic is not compromised.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/api-shield/#page","headline":"Cloudflare API Shield","description":"Identify and address API vulnerabilities with discovery, schema validation, and abuse detection.","url":"https://developers.cloudflare.com/api-shield/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/og.png?v=4def62fcf84999fc","dateModified":"2026-08-19","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Set up API Shield to identify and address API security best practices.
title: Get started with API Shield
image: https://developers.cloudflare.com/api-shield/get-started/og.png?v=35fb7f680c1d55f0
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Get started with API Shield

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/get-started/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

API Shield protects your APIs by discovering endpoints, validating request schemas, and detecting abuse patterns. This guide walks through the initial setup from configuring session identifiers to enabling advanced protections.

## Session identifiers

While not strictly required, it is recommended that you configure your session identifiers when getting started with API Shield. When Cloudflare inspects your API traffic for individual sessions, we can offer more tools for visibility, management, and control.

If you are unsure of the session identifiers that your API uses, consult with your development team.

Session identifiers should uniquely identify API clients. A common session identifier for API traffic is the `Authorization` header. When a [JSON Web Token (JWT)](https://developers.cloudflare.com/api-shield/security/jwt-validation/) is used by the API for client authentication, its value may change over time. You can use a claim value inside the JWT such as `sub` or `email` as a session identifier to uniquely identify the session over time.

If no session identifiers are configured and the `Authorization` header appears on more than 1% of eligible sampled client requests with `2xx` responses, Cloudflare automatically configures that header as the API Shield session identifier. Cloudflare does not overwrite an existing session identifier configuration.

An API Shield subscription or eligible API Shield trial is required to configure session identifiers, including cookie-based identifiers. Configured identifiers can provide optional evidence for [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), and are used by [Sequence Mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [rate limiting recommendations](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/), [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/), and [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/).

### To set up session identifiers

You can configure up to 10 session identifiers.

1. In the Cloudflare dashboard, go to the **Security Settings** page. [Go to **Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Session identifiers**, select **Configure session identifiers**.
4. Select **Manage identifiers**.
5. Choose the type of session identifier (cookie, HTTP header, or JWT claim).

   Note

   The session identifier cookie must comply with RFC 6265. Otherwise, it will be rejected.

   If you are using a JWT claim, choose the [Token Configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations) that will verify the JWT, then specify the claim using a supported [RFC 9535 JSONPath ↗︎](https://www.rfc-editor.org/rfc/rfc9535.html) expression. Token Configurations are required to use JWT claims as session identifiers. Refer to [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) for more information.
6. Enter the name of the session identifier.
7. Select **Save**.

API Shield generates rate limiting recommendations for eligible saved operations. Recommendations require API Shield access, a configured session identifier that matches operation traffic, sufficient data, and completed processing. After these requirements are met, you can view per-operation and per-session recommendations and create rate limiting rules.

Discovery can use configured session identifiers as one signal when identifying API traffic. Session identifiers also support session traffic analysis in [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/).

## Create a Schema Profile

[Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/) provides one Schema Profile with two sources. Schema Learning derives a profile from traffic, while Schema Validation uses an uploaded OpenAPI schema.

Both sources provide an **always-on detection** after their profile becomes available. Mitigation requires a separate WAF Custom Rule.

If you maintain an OpenAPI schema, follow the [Schema Validation upload procedure](https://developers.cloudflare.com/api-shield/security/schema-validation/#upload-a-schema). API Shield remains the reference for OpenAPI compatibility, schema governance, and automation.

## Enable the Sensitive Data Detection ruleset and accompanying rules

API Shield works with the Cloudflare [WAF](https://developers.cloudflare.com/waf/) [Sensitive Data Detection](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#sensitive-data-detection) ruleset to identify API endpoints that return sensitive data, such as social security or credit card numbers, in their HTTP responses. Review these endpoints to verify that sensitive data is only returned where expected.

Note

Sensitive Data Detection requires a separate subscription. Contact your account team if your plan does not include this feature.

You can identify endpoints returning sensitive data by selecting the icon next to the path in a row. Expand the endpoint to see details on which rules were triggered and view more information by exploring events in **Firewall Events**.

## Manage operations

Web Assets continuously discovers operations from traffic. An operation represents an endpoint by HTTP method, hostname pattern, and path pattern.

You can also add operations manually under **Web Assets** > **Operations**. Discovery and manual creation only add inventory entries.

To start Schema Learning, select **Learn profile** from the operation overflow menu. Review the learned schema through **View details** > **Security overview**.

For the complete workflow and traffic thresholds, refer to [Get started with Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/get-started/).

## Add rate limits to your most sensitive endpoints

[Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) allow you to define rate limits for requests matching an expression, and choose the action to perform when those rate limits are reached.

API Shield generates rate limit recommendations for eligible saved operations. Recommendations require API Shield access, a configured session identifier that matches operation traffic, sufficient data, and completed processing. These recommendations are scoped per operation and per session rather than applied across your entire site or based on IP address.

Per-session rate limits track traffic from individual visitors during their session to a specific endpoint. This reduces false positives from broadly scoped rules while still limiting abusive traffic.

## Export a learned schema

A learned-schema export is a point-in-time OpenAPI snapshot for a selected hostname. It includes learned operations by method and path and detected path variables (for example, `/users/{id}`). It can also include detected query parameters, their formats, and rate limit recommendations.

You can export your learned schemas in the [Cloudflare dashboard](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/#export-a-schema) or via the [API](https://developers.cloudflare.com/api/resources/api_gateway/subresources/schemas/methods/list/).

The export uses OpenAPI `v3.0.0`. To use a fixed profile, upload that file through [Schema Validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).

## View and configure Sequence Analytics

[Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) identifies common patterns of API requests — for example, a user checking their account balance before initiating a funds transfer.

Sequences are ranked by precedence score, which measures how likely specific API requests are to occur together in a consistent order. High-scoring sequences contain API requests that are likely to be preceded by the other operations in the sequence.

[Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) allows you to enforce request patterns for authenticated clients communicating with your API. Use Sequence Analytics to identify the sequences your API clients follow, then apply API Shield protections (rate limiting, Schema validation, JWT validation, and mTLS) to the endpoints in your high-scoring sequences. Verify the expected endpoint order with your development team.

For more information, refer to [Detecting API abuse automatically using sequence analysis ↗︎](https://blog.cloudflare.com/api-sequence-analytics) blog post.

## Additional configuration

### Set up JSON Web Tokens (JWT) validation

[JSON Web Tokens (JWT) validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) verifies that tokens sent by clients have not been tampered with and have not expired. Configure JWT validation using the Cloudflare dashboard or API.

### Set up GraphQL malicious query protection

If your origin uses GraphQL, you may consider setting limits on GraphQL query size and depth.

[GraphQL malicious query protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/api/) scans GraphQL traffic for queries with excessive nesting or size that could overload your origin and result in a denial of service. You can create rules that set maximum query depth and size to block these queries before they reach your origin.

For more information, refer to the [blog post ↗︎](https://blog.cloudflare.com/protecting-graphql-apis-from-malicious-queries/).

### Mutual TLS (mTLS) authentication

If you operate an API that requires or would benefit from an extra layer of protection, you may consider using Mutual TLS (mTLS).

[Mutual TLS (mTLS) authentication](https://developers.cloudflare.com/api-shield/security/mtls/) requires both the client and server to verify each other's identity using certificates. In standard TLS, only the server proves its identity. mTLS adds client verification, which is useful for devices like IoT hardware that do not authenticate via an identity provider.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/get-started/#page","headline":"Get started with API Shield","description":"Set up API Shield to identify and address API security best practices.","url":"https://developers.cloudflare.com/api-shield/get-started/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/get-started/og.png?v=35fb7f680c1d55f0","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Compare API Shield feature availability and endpoint limits across Cloudflare plans.
title: Plans
image: https://developers.cloudflare.com/api-shield/plans/og.png?v=261ae43b8dc50384
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Plans

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/plans/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Customers with API Security already have access to Schema Profiles through Schema Learning and Schema Validation. Cloudflare is opening a closed beta to invited Enterprise customers without API Security. Interested customers can contact their account team to express interest. Closed beta access does not imply future plan availability or pricing.

To subscribe to API Shield, upgrade to an Enterprise plan and contact your account team.

Existing operation and uploaded schema limits remain based on your zone plan. These limits do not determine Application Profiles availability.

The uploaded schema allowance counts schemas enabled for validation. Cloudflare calculates schema size after processing an upload, so it may differ from the original file size.

| Plan type | Saved endpoints | Enabled uploaded schemas | Combined size of enabled schemas | Rule action |
| --- | --- | --- | --- | --- |
| **Free** | 100 | 5 | 200 KiB | `Block` only |
| **Pro** | 250 | 5 | 500 KiB | `Block` only |
| **Business** | 500 | 10 | 2 MiB | `Block` only |
| **Enterprise without API Shield** | 3000 | 10 | 5 MiB | `Log` or `Block` |
| **Enterprise with API Shield** | 10,000 | 10 | 10+ MiB | `Log` or `Block` |

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/api-shield/plans/#page","headline":"Plans","description":"Compare API Shield feature availability and endpoint limits across Cloudflare plans.","url":"https://developers.cloudflare.com/api-shield/plans/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/plans/og.png?v=261ae43b8dc50384","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Discover, validate, and protect API endpoints with API Shield security features.
title: Security
image: https://developers.cloudflare.com/api-shield/security/og.png?v=f4c2f4c55f5796cb
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Security

Last updated Aug 19, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

[Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/) provides the shared profile detection, analytics, and mitigation model. Schema Profile is its only current profile type.

[Schema Learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) learns a Schema Profile from traffic. [Schema Validation](https://developers.cloudflare.com/api-shield/security/schema-validation/) supplies the same profile type through uploaded OpenAPI schemas.

API Shield provides API inventory, schema governance, OpenAPI export, and automation. Cloudflare also offers these API security features:

| Discovery & management | Posture management | Runtime protection |
| --- | --- | --- |
| [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/) | [Volumetric Abuse Detection](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/) | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/) |
| [Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) | [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/) | [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) |
| [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) | [BOLA vulnerability detection](https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/) | [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) |
|  | [Risk labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#risk-labels) | [Mutual TLS (mTLS)](https://developers.cloudflare.com/api-shield/security/mtls/) |
|  | [Vulnerability Scanner](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/) | [GraphQL query protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/) |

## Example Cloudflare solutions

Cloudflare API Shield, together with other Cloudflare products, helps protect your API from the [OWASP API Security Top 10 ↗︎](https://owasp.org/www-project-api-security/). These are the most common API security risks, ranging from unauthorized data access to denial of service.

The following table maps each OWASP vulnerability to the Cloudflare features that address it:

| OWASP issue | Example Cloudflare solution |
| --- | --- |
| Broken Object Level Authorization | [BOLA vulnerability detection](https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/), [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), [Vulnerability Scanner](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/) |
| Broken Authentication | [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/), [mTLS](https://developers.cloudflare.com/api-shield/security/mtls/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [Exposed Credential Checks](https://developers.cloudflare.com/waf/managed-rules/check-for-exposed-credentials/), [Bot Management](https://developers.cloudflare.com/bots/) |
| Broken Object Property Level Authorization | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) |
| Unrestricted Resource Consumption | [Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Bot Management](https://developers.cloudflare.com/bots/), [GraphQL Query Protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/) |
| Broken Function Level Authorization | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) |
| Unrestricted Access to Sensitive Business Flows | [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Bot Management](https://developers.cloudflare.com/bots/), [GraphQL Query Protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/) |
| Server Side Request Forgery | [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/), [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/) |
| Security Misconfiguration | [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/), [GraphQL Query Protection](https://developers.cloudflare.com/api-shield/security/graphql-protection/) |
| Improper Inventory Management | [Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), [Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) |
| Unsafe Consumption of APIs | [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/) |

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"WebPage","@id":"https://developers.cloudflare.com/api-shield/security/#page","headline":"Security","description":"Discover, validate, and protect API endpoints with API Shield security features.","url":"https://developers.cloudflare.com/api-shield/security/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/og.png?v=f4c2f4c55f5796cb","dateModified":"2026-08-19","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Map out and understand your API attack surface with Discovery.
title: Discovery
image: https://developers.cloudflare.com/api-shield/security/api-discovery/og.png?v=aa24516174af0538
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Discovery

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/api-discovery/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Most development teams struggle to keep track of their APIs. Cloudflare Discovery helps you map out and understand your API attack surface — the full set of endpoints that could be targeted by attackers.

## Process

Cloudflare produces a map of API endpoints by applying heuristic path normalization to qualifying sampled traffic. The heuristics group requests by path structure and variable-like segment patterns.

For example, you might have thousands of APIs, but a lot of the calls look similar, such as:

- `api.example.com/profile/238`
- `api.example.com/profile/392`

Discovery might group both paths as `api.example.com/profile/{var1}`. Generated `{varN}` placeholders identify variable-like segments. They do not assign semantic names.

The resulting endpoint map might look like:

```txt
/api/login/{var1}
/api/auth
/api/account/{var1}
/api/password_reset
/api/logout
```

Cloudflare can also consolidate common normalized operations across compatible subdomains. Operations unique to one hostname can remain on that hostname.

```txt
us-api.example.com/api/v1/users/{var1}
de-api.example.com/api/v1/users/{var1}
fr-api.example.com/api/v1/users/{var1}
jp-api.example.com/api/v1/users/{var1}
```

Cloudflare may consolidate these common operations to `{hostVar1}.example.com/api/v1/users/{var1}`.

For more technical details, refer to the [blog post ↗︎](https://blog.cloudflare.com/ml-api-discovery-and-schema-learning/).

### Discovered operations

Discovery results can appear as candidate or shadow operations. Candidate operations are matched at the edge. Shadow operations are not.

When a request matches a published candidate, the match can provide operation context for logs, rules, analytics, and applicable detections. You do not need to save every discovered operation.

You do not need to save every discovered operation. Save an operation to move it to the `full` state. Full operations support persisted API profiles, risk findings, and protections that require a known API endpoint.

To save a discovered operation:

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Operations** tab.
3. Open the row actions for a candidate or shadow operation.
4. Select **Learn profile**.

Cloudflare moves the operation to the `full` state. The row action then displays **Learning profile**, which does not indicate that learning is complete. For more information, refer to [Start profile learning](https://developers.cloudflare.com/security/web-assets/manage-operations/#start-profile-learning).

### Discovering operations

Discovery uses multiple signals, including machine learning and configured session identifiers, to identify API traffic. Configuring a session identifier is optional.

To review Discovery results:

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Operations** tab.
3. Select the **Discovered** quick filter, which applies the **Candidate** and **Shadow** state filters. You can also select both states manually.

You can direct any feedback about your Discovery results to your account team.

## Requirements

Discovery requires an active API Shield subscription at both the account and zone level. If your subscription is active at the account level but not assigned to the zone, Discovery will not run for that zone.

Discovery analyzes sampled proxied traffic. Eligible requests use supported HTTP methods, use paths outside `/cdn-cgi`, and contain qualifying Discovery signals.

For an endpoint to appear in Discovery results, qualifying sampled traffic must meet the following conditions:

- The request must return a `2xx` response code from the Cloudflare edge.
- The request must not originate directly from a Cloudflare Worker. Traffic sent through the Cloudflare traffic simulator or other Worker-based test harnesses will not be counted toward Discovery thresholds.
- The endpoint must receive at least 500 requests within a continuous 10-day period.

For more information, refer to [Discovery requirements](https://developers.cloudflare.com/security/web-assets/manage-operations/#discovery-requirements/).

## Availability

Discovery requires the paid API Shield add-on, which is available to Enterprise customers. Contact your account team for more information.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/api-discovery/#page","headline":"Discovery","description":"Map out and understand your API attack surface with Discovery.","url":"https://developers.cloudflare.com/api-shield/security/api-discovery/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/api-discovery/og.png?v=aa24516174af0538","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Identify authentication misconfigurations for API endpoints with Authentication Posture.
title: Authentication Posture
image: https://developers.cloudflare.com/api-shield/security/authentication-posture/og.png?v=e99b68f98d51e88e
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Authentication Posture

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/authentication-posture/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Authentication Posture detects API endpoints where all or some successful requests lack a configured session identifier and alerts you to potential misconfigurations.

For example, a security team member may expect that their API endpoints `/api/v1/users` and `/api/v1/orders` require authentication. However, bugs in origin API authentication policies can create broken authentication vulnerabilities — allowing unauthenticated access to protected resources. Authentication Posture does not validate credentials. Instead, it reports whether configured session identifiers are present on successful requests to help you identify potential misconfigurations.

Consider a typical e-commerce application. Users can browse items and prices without logging in. However, to retrieve order details via `GET /api/v1/orders/{order_id}`, users must log in and pass an Authorization HTTP header with all requests. Cloudflare alerts you via [Security Center Insights](https://developers.cloudflare.com/security/security-insights/) and [Endpoint labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/) if successful requests reach this endpoint or any other endpoint without a configured session identifier.

## Process

After configuring [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers), API Shield scans successful requests for the presence of those identifiers and updates endpoint labels approximately once a day. The labeling methodology explains how API Shield assigns authentication posture labels.

| Description | 2xx response codes | 4xx, 5xx response codes |
| --- | --- | --- |
| If all successful requests lack a configured session identifier, Cloudflare applies the label: | `cf-risk-missing-auth` | Requests with these response codes are not used to apply the label. |
| If some successful requests contain a configured session identifier and some lack one, Cloudflare applies the label: | `cf-risk-mixed-auth` | Requests with these response codes are not used to apply the label. |

### Examine an endpoint's authentication details

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Operations** tab.
3. Filter your endpoints by the `cf-risk-missing-auth` or `cf-risk-mixed-auth` labels.
4. Select an endpoint to see its authentication posture details on the endpoint details page.
5. Choose between the 24-hour and 7-day view options, and note any authentication changes over time.

The main authentication widget displays how many successful requests over the last seven days had session identifiers included with them, and which identifiers were included with the traffic.

The authentication-over-time chart shows a detailed breakdown over time of how clients successfully interacted with your API and which identifiers were used. A large increase in unauthenticated traffic may signal a security incident. Similarly, any successful unauthenticated traffic on an endpoint that is expected to be 100% authenticated can be a cause for concern.

Work with your development team to understand which authentication policies may need to be corrected on your API to stop unauthenticated traffic.

### Stop unauthenticated traffic with Cloudflare

In this context, an unauthenticated request is one that does not include a configured API Shield session identifier.

To block unauthenticated requests, create a [custom rule](https://developers.cloudflare.com/waf/custom-rules/) using the `cf.api_gateway.auth_id_present` field. This field evaluates to `true` when the configured API Shield session identifiers are present on a request. You can also match on absence to detect unauthenticated traffic. Add a host and path match to scope the rule to specific endpoints.

## Limitations

Authentication Posture can only apply when customers accurately set up session identifiers in API Shield. Session identifiers must uniquely identify authenticated users of your API. If you are unsure of your API's session identifier, consult with your development team.

## Availability

Authentication Posture is available for all Enterprise customers with an API Shield subscription.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/authentication-posture/#page","headline":"Authentication Posture","description":"Identify authentication misconfigurations for API endpoints with Authentication Posture.","url":"https://developers.cloudflare.com/api-shield/security/authentication-posture/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/authentication-posture/og.png?v=e99b68f98d51e88e","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["Authentication"]}
```

---

---
description: Detect endpoints at risk of Broken Object Level Authorization attacks.
title: Broken Object Level Authorization vulnerability detection
image: https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/og.png?v=fd62015f645a0c05
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Broken Object Level Authorization vulnerability detection

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

A Broken Object Level Authorization (BOLA) vulnerability is where an application or API fails to properly verify if a user has permission to access specific data.

Bugs in the application or API allow attackers to bypass authorization checks and access potentially sensitive information by manipulating and iterating through object identifiers (such as user IDs or order IDs).

Vulnerabilities can occur at any time, including in the original application's deployment. However, changes or upgrades to authentication and authorization policies can also introduce these bugs.

BOLA vulnerabilities are as dangerous as an account takeover. Successfully exploiting a BOLA vulnerability allows the attacker to access or change data that they should not have ownership over.

Cloudflare labels endpoints with BOLA risk when it detects two distinct signals common with attacks exploiting BOLA: **Parameter pollution** and **Enumeration**.

## Enumeration

Cloudflare estimates how many distinct combinations of all path-parameter values each session with a configured session identifier requests from an endpoint. It compares each session's count with the distribution observed for the same endpoint.

Note

Sessions that have more random behavior or repetition have a higher chance of triggering an alert.

The BOLA enumeration label requires more than approximately 10,000 sessions with a configured session identifier and at least one path-parameter value during the seven-day detection window before an endpoint is eligible for outlier detection.

<details>

<summary>

Enumeration example

</summary>

**Endpoint**: <code>GET /api/v1/users/{userId}/credit-cards</code>

- **Normal behavior**: Users request credit cards using only their own <code>userId</code>.
- **Attack behavior**: Attackers request hundreds of <code>userId</code> values per session by brute-force iterating through <code>userIds</code> found via other methods.
- **Result**: If the origin authorization policy is broken for this endpoint, the attacker gains credit card information on every user account they request it for.

</details>

## Parameter pollution

Cloudflare detects requests with an HTTP response status below `400` where the same parameter appears both in a schema-defined location (path, query string, header, or cookie) and in an unexpected request location, with different values in each location. API Shield applies a risk label only when the resulting pattern meets the detector's anomaly criteria.

<details>

<summary>

Parameter pollution example

</summary>

**Endpoint**: <code>GET /api/v1/orders/{orderId}</code>

- **Normal behavior**: <code>orderId</code> sent in a path variable like <code>GET /api/v1/orders/12345</code>
- **Attacker behavior**: <code>orderId</code> is also sent as a query parameter, triggering old, undocumented code that looks for orders in the query parameter and happens to lack an authorization check: <code>GET /api/v1/orders/12345?orderId=67890</code>
- **Result**: By passing in a fake order or an order that the attacker owns (<code>12345</code>), they are able to trigger the old, undocumented code and access an order that they do not own (<code>67890</code>)

</details>

## Process

API Shield detects BOLA attacks by learning visitor traffic patterns and identifying anomalous access to specific objects. Affected endpoints are automatically labeled with the following [risk labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#risk-labels):

- `cf-risk-bola-enumeration`: Automatically added when some sessions request unusually many distinct combinations of path parameter values for an endpoint compared with other sessions.
- `cf-risk-bola-pollution`: Automatically added when Cloudflare detects an unusual pattern of requests that send different values for the same parameter in its schema-defined location and an unexpected request location. Only requests whose responses have status codes below `400` contribute.

If you see one of these labels on your API endpoints, check its authorization policy with your developer team to find any authorization bugs. You can also contact Cloudflare for a report including attacker identifiers to confirm attack reach and impact.

BOLA attack information can be found in your [Security Overview](#security-overview), [Security Analytics](#security-analytics), and [Endpoint details](#endpoint-details).

### Security Overview

If BOLA vulnerabilities have been detected on your endpoints, you can view a summary of the attack and suggestions to mitigate it via the Cloudflare dashboard.

1. In the Cloudflare dashboard, go to the **Security** page. [Go to **Overview** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/overview)
2. Go to **API abuse** or **All suggestions**.
3. Depending on the type of attack, select **Review traffic from potential BOLA enumeration attack** or **Review traffic from potential parameter pollution attack** to view details of the attack and suggested actions.
4. Select **View all affected endpoints** or **View details** on a specific endpoint to review suspicious sessions in [Web Assets](#endpoint-details).

Cloudflare evaluates your session requests for both enumeration and parameter pollution attacks and provides you with a list of at-risk endpoints and the number of anomalous sessions where an attack was detected. You can follow the suggested actions to address your BOLA vulnerabilities and prevent future attacks against your endpoints.

Note

If the insight has been archived but attacks are still present, you can filter by **Show archived**.

### Security Analytics

You can view analytics of your zone's traffic profile and suspicious requests associated with enumeration or parameter pollution attacks in the Cloudflare dashboard.

[Go to **Analytics** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)

Filter requests by the hashed session IDs shown in the detection and the corresponding BOLA vulnerability risk label. Security Analytics queries adaptively sampled request data for the combined detection period of the selected reports.

Note

API Shield creates each hashed session ID from the combined traffic values selected by your configured session identifiers. The displayed ID is not a configured selector or a raw traffic value.

The Security Analytics insight considers up to 50 reports per BOLA detection type whose detection periods ended within the previous seven days and up to 50 sessions from each report. Its filters are not limited by operation ID, so they can include sampled requests from the selected sessions to other operations carrying the same BOLA risk label.

Review the top statistics and details of managed API endpoints, paths and values targeted by the attack, source IPs, source user agents, and source fingerprints.

Review your traffic profile for unusual patterns, such as spikes in unique object requests or unexpected parameter locations.

### Endpoint details

You can expand the endpoint details in Web Assets to access information on suspicious sessions' activity on the endpoint, including both enumeration attack and parameter pollution attack details.

[Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)

Under **Security overview**, select **View attack** to review affected sessions with associated IP addresses and JA4 fingerprints (TLS client fingerprints that help identify the software making the request).

You can export the `.csv` file containing all the IP addresses and JA4 fingerprints for all or only a specific session.

The details specify the parameter that was affected, the number of sessions involved in the attack, and how far their behavior deviated from baseline.

If unauthorized access to the parameter was obtained, consider the potential impact to your application, users, and data. As a best practice, consult with your application and API developers to confirm unauthorized access by reviewing your API origin logs for the IP address and JA4 fingerprint of the abusive sessions.

You can view attack data in [Security Analytics](#security-analytics).

[Go to **Analytics** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)

The link from endpoint details filters Security Analytics by the managed operation and the report's detection period. You can also filter by suspicious IP addresses and fingerprints found in the attack details.

---

## Availability

Broken Object Level Authorization vulnerability detection is only available for Enterprise customers. If you are an Enterprise customer interested in this product, contact your account team.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/#page","headline":"Broken Object Level Authorization vulnerability detection","description":"Detect endpoints at risk of Broken Object Level Authorization attacks.","url":"https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/bola-vulnerability-detection/og.png?v=fd62015f645a0c05","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Scan GraphQL traffic and block queries that could overload your origin.
title: GraphQL malicious query protection
image: https://developers.cloudflare.com/api-shield/security/graphql-protection/og.png?v=28a2d411af4a980b
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# GraphQL malicious query protection

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/graphql-protection/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

GraphQL is a query language for APIs. In addition to protecting RESTful APIs, Cloudflare can also protect GraphQL APIs.

GraphQL malicious query protection scans your GraphQL traffic for queries that could overload your origin and result in a denial of service. Query size is the number of terminal fields, or leaves, in a query. You can build rules that limit the query depth and size of incoming GraphQL queries in order to block suspiciously large or complex queries.

## Availability

GraphQL malicious query protection is available for all API Shield customers. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service ↗︎](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team.

## Limitations

The following limitations apply:

- Parsing is limited to GraphQL `POST` bodies up to 20 KiB. This limit will be raised in a future release.
- Only `POST` requests with content types of `application/json` or `application/graphql` are inspected.
- Queries containing fragments or multiple operations are not supported.
- Parsing and rules are limited to paths with the case-sensitive `/graphql` suffix.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/graphql-protection/#page","headline":"GraphQL malicious query protection","description":"Scan GraphQL traffic and block queries that could overload your origin.","url":"https://developers.cloudflare.com/api-shield/security/graphql-protection/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/graphql-protection/og.png?v=28a2d411af4a980b","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Use the GraphQL API to configure query size and depth limits for your API.
title: Configure GraphQL malicious query protection via the API
image: https://developers.cloudflare.com/api-shield/security/graphql-protection/api/og.png?v=5fe3f58bb103ab4d
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configure GraphQL malicious query protection via the API

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/graphql-protection/api/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Use the [Cloudflare GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/getting-started/) to gather data about your GraphQL API’s current usage and configure Cloudflare’s GraphQL malicious query protection to log or block malicious queries.

## Introduction

Query size is defined as the number of terminal fields (leaves) in the query, whereas query depth is the deepest level at which a leaf is present. For example, the size of this query will be reported as `4 (terminalField[1-4] all contribute to this counter)`, and the depth will be reported as `3 (terminalField3 and terminalField4 are at depth level 3)`.

*GraphQL querygraphql*

```graphql
{
	terminalField1
	nonTerminalField1(filter: 123) {
		terminalField2
		nonTerminalField2 {
			terminalField3
			terminalField4
		}
	}
}
```

## Gather GraphQL statistics

Using the new `apiGatewayGraphqlQueryAnalyticsGroups` node in the Cloudflare GraphQL API, you can retrieve `apiGatewayGraphqlQuerySize` and `apiGatewayGraphqlQueryDepth` dimensions.

*GraphQL querygraphql*

```graphql
query ApiGatewayGraphqlQueryAnalytics(
	$zoneTag: string
	$start: Time
	$end: Time
) {
	viewer {
		zones(filter: { zoneTag: $zoneTag }) {
			apiGatewayGraphqlQueryAnalyticsGroups(
				limit: 100
				orderBy: [
					apiGatewayGraphqlQuerySize_DESC
					apiGatewayGraphqlQueryDepth_DESC
				]
				filter: { datetime_geq: $start, datetime_leq: $end }
			) {
				count
				dimensions {
					apiGatewayGraphqlQuerySize
					apiGatewayGraphqlQueryDepth
				}
			}
		}
	}
}
```

With the above query, you will get the following response:

*Responsejson*

```json
{
	"data": {
		"viewer": {
			"zones": [
				{
					"apiGatewayGraphqlQueryAnalyticsGroups": [
						{
							"count": 10,
							"dimensions": {
								"apiGatewayGraphqlQueryDepth": 1,
								"apiGatewayGraphqlQuerySize": 11
							}
						},
						{
							"count": 10,
							"dimensions": {
								"apiGatewayGraphqlQueryDepth": 1,
								"apiGatewayGraphqlQuerySize": 2
							}
						}
					]
				}
			]
		}
	},
	"errors": null
}
```

In the response example, Cloudflare observed 10 requests with depth 1 and size 11, and 10 requests with depth 1 and size 2 in the selected timeframe.

## Analyze GraphQL statistics

You can use the response to compute percentiles across the attributes and set a threshold on what is allowed. For example, you can use a simple heuristic like `1.5 * p99` for query size or depth.

Here is a simple Python script that will report query size and depth p-levels given the GraphQL API response output above (as a JSON file):

*Python scriptpython*

```python
#!/usr/bin/env python3

import json
import numpy as np
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--response", help="Path to the API JSON response file with the apiGatewayGraphqlQueryAnalyticsGroups node", required=True)
args = parser.parse_args()
with open(args.response) as f:
    query_sizes = np.array([], dtype=np.uint16)
    query_depths = np.array([], dtype=np.uint8)
    data = json.load(f)['data']['viewer']['zones'][0]['apiGatewayGraphqlQueryAnalyticsGroups']
    for datapoint in data:
        query_sizes = np.append(query_sizes, [datapoint['dimensions']['apiGatewayGraphqlQuerySize']] * datapoint['count'])
        query_depths = np.append(query_depths, [datapoint['dimensions']['apiGatewayGraphqlQueryDepth']] * datapoint['count'])

    quantiles = [0.99, 0.95, 0.75, 0.5]
    print('\n'.join([f"Query size {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_sizes, quantiles))]))
    print('\n'.join([f"Query depth {int(q * 100)}th percentile is {v}" for q, v in zip(quantiles, np.quantile(query_depths, quantiles))]))
```

With the above query, you will get the following output:

*Example outputjson*

```json
./calculator.py --response=response.json
Query size 99th percentile is 11.0
Query size 95th percentile is 11.0
Query size 75th percentile is 11.0
Query size 50th percentile is 6.5
Query depth 99th percentile is 1.0
Query depth 95th percentile is 1.0
Query depth 75th percentile is 1.0
Query depth 50th percentile is 1.0
```

## Set limits on incoming GraphQL queries

API Shield customers now have three new fields available in custom rules:

- `cf.api_gateway.graphql.query_size` describes the size of a GraphQL query.
- `cf.api_gateway.graphql.query_depth` describes the depth of a GraphQL query.
- `cf.api_gateway.graphql.parsed_successfully` describes whether Cloudflare was able to parse the query. Presently, we run best-effort parsing, meaning we might not be able to parse some valid queries. This means that you must use a `and cf.api_gateway.graphql.parsed_successfully` filter in your custom rules when deploying GraphQL security rules.

For example, you can deploy the following rule via the API or the dashboard to block queries that are deeply nested and ask for over 30 fields.

```txt
(cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)
```

Note

You are not able to configure which endpoints the GraphQL parsing runs on. Requests are parsed if they target a path with the case-sensitive `/graphql` suffix.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/graphql-protection/api/#page","headline":"Configure GraphQL malicious query protection via the API","description":"Use the GraphQL API to configure query size and depth limits for your API.","url":"https://developers.cloudflare.com/api-shield/security/graphql-protection/api/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/graphql-protection/api/og.png?v=5fe3f58bb103ab4d","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["GraphQL"]}
```

---

---
description: Verify incoming JWTs to detect token tampering and invalid tokens at the edge.
title: JSON Web Tokens validation
image: https://developers.cloudflare.com/api-shield/security/jwt-validation/og.png?v=10ef6f4cc8c50699
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# JSON Web Tokens validation

Last updated Oct 1, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/jwt-validation/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

JSON web tokens (JWT) are often used as part of an authentication component on many web applications. Since JWTs are crucial to identifying users and their access, ensuring the token's integrity is important.

API Shield's JWT validation cryptographically verifies incoming JWTs before they reach your API origin. It detects tokens that are expired, tampered with, or not yet valid. You then create a rule to act on the validation results.

## Process

JWT validation has two parts: a token configuration that tells Cloudflare how to find and verify JWTs, and a rule that acts on the validation results.

After you create a token configuration, Cloudflare checks every request in the zone for a JWT at the configured locations. When Cloudflare finds a JWT, it validates the token and makes the verified claims available in `http.request.jwt.claims` fields. For available fields and standard claims, refer to the [JWT validation fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?field-category=JWT+validation) reference. You do not need a rule or an operation in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) for validation. Rules determine how Cloudflare acts on the results.

### Add a token validation configuration

1. In the Cloudflare dashboard, go to the **Security Settings** page. [Go to **Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Token configurations**, select **Configure tokens**.
4. Add a name for your configuration.
5. Choose where Cloudflare can locate the JWT for this configuration on incoming requests, such as a header or cookie and its name.
6. Copy and paste your JWT issuer's verification keys (JWKS). You can provide asymmetric public keys or symmetric keys used with HMAC algorithms.

JWT issuers that use asymmetric algorithms typically publish public keys (JWKS) for verification at a known URL on the Internet. Issuers that use HMAC algorithms share a symmetric credential with the validator. If you do not know where to get your issuer's verification keys or symmetric credential, contact your identity administrator.

For supported algorithms and symmetric key requirements, refer to [Configure JWT validation via the API](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#credentials).

Token configurations do not automatically retrieve or refresh keys from a JWKS URL. Add updated JWK values directly, or use a Worker to synchronize the token configuration with your identity provider. To configure automatic updates, refer to [Configure Workers to automatically update keys](https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/).

### Act on JWT validation results

For new security policies, Cloudflare generally recommends using WAF custom rules.

- **[WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/)** — use these for zone-wide policies based on verified JWT claims. Custom rules can combine claims with other signals, such as [attack score](https://developers.cloudflare.com/waf/detections/attack-score/). Endpoints do not need to be in Endpoint Management.
- **JWT validation rules** — use these when enforcement must apply only to specific operations in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/). These rules support the `is_jwt_valid()` and `is_jwt_present()` functions, which are not available in custom rules.

Cloudflare validates JWTs the same way regardless of which rule type you choose.

For example, to reference a simple string claim in a rule expression, use [`lookup_json_string()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#lookup_json_string) with your token configuration ID and the claim name:

```txt
lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "claim_name")
```

For a complete example, refer to [Issue challenge for admin user in JWT claim based on attack score](https://developers.cloudflare.com/waf/custom-rules/use-cases/check-jwt-claim-to-protect-admin-user/). For all available fields, refer to the [JWT validation fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?field-category=JWT+validation) reference.

### Add a JWT validation rule

JWT validation rules use operations from Endpoint Management to control where Cloudflare applies their `log` or `block` action.

1. In the Cloudflare dashboard, go to the **Security rules** page. [Go to **Security rules** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. On API JWT validation rules, select **Create rule**.
3. Add a name for your rule.
4. Select a hostname to protect requests with saved endpoints using the rule.
5. Deselect any endpoints that you want to exclude from the JWT validation rule's enforcement.
6. Select the token configuration that corresponds to the incoming requests.
7. Choose whether to strictly enforce token presence on these endpoints.
   - You may not expect 100% of clients to send in JWTs with their requests. If this is the case, choose *Ignore*. JWT validation will still validate JWTs that are present.
   - You may otherwise expect all requests to the selected hostname and endpoints to contain JWTs. If this is the case, choose *Mark as non-compliant*.
8. Choose an action to take for non-compliant requests. For example, JWTs that do not pass validation (expired, tampered with, or bad signature tokens) or requests with missing JWTs when *Mark as non-compliant* is selected in the previous step.
9. Select **Save**.

Note

JWT validation rules automatically apply to new endpoints added to Endpoint Management if those endpoints also match the rule's selector.

---

## Special cases

### Validate two JWTs with different identity providers on a single request

If you expect that two different JWTs should be present in a request and you want to validate both, you must create two different token configurations. When selecting the two configurations in your validation rule, select *Validate all configurations* under **Validation behavior for multiple configurations**.

### Support a migration from one identity provider to another

If you expect to migrate between two different identity providers, you must create two different token configurations and two different validation rules, each corresponding to its own configuration. With this setup, you can change the action for different validation rules depending on the state of your migration.

### JSON Web Tokens with the `Bearer` prefix

API Shield will verify JSON Web Tokens regardless of whether they have the `Bearer` prefix.

### Rate limit by JWT claim

Rate Limiting can use string claims from a valid JSON Web Token (JWT) as rate-limit characteristics. This includes registered claims, such as `sub`, and custom claims.

For nested claims, pass each object key separately to [`lookup_json_string()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#lookup_json_string). For example, use `"user", "email"` to access `user.email`.

Only valid JWTs populate JWT claim fields. If a rule also matches requests without the selected claim, those requests use a separate missing-value counter. Refer to [Missing field versus empty value](https://developers.cloudflare.com/waf/rate-limiting-rules/parameters/#missing-field-versus-empty-value).

For per-user limits, select a claim that uniquely identifies the user, such as `sub` when it is unique within your application. Requests with the same characteristic value share a rate-limit counter.

### Rate limit by user tier

To apply different per-user limits by tier, create one rate limiting rule for each tier. Match the tier claim in the rule expression and use a separate user identifier claim as the rate-limit characteristic.

For example, a free-tier rule can use:

*Example rule expressiontxt*

```txt
lookup_json_string(http.request.jwt.claims["<JWT_TOKEN_CONFIGURATION_ID>"][0], "tier") eq "free"
```

Use `sub` as the rate-limit characteristic and set the limit to five requests per minute. Create another rule that matches `"tier" eq "premium"` and applies the appropriate premium-tier limit.

### Ignore `OPTIONS` pre-flight CORS requests

Due to cross-origin resource sharing (CORS) security, web browsers will send "pre-flight" requests using the `OPTIONS` verb to API endpoints before sending a `GET` (or other verb) request. By definition, `OPTIONS` preflight requests do not include credentials (authentication headers or cookies) and are anonymous.

If you expect web browsers to be valid clients of your API, and to prevent blocking `OPTIONS` requests from those browsers, Cloudflare recommends adding `or http.request.method eq "OPTIONS"` to your JWT validation rules.

---

## Availability

JWT validation is available for all API Shield customers. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service ↗︎](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team.

---

## Limitations

JWT validation only operates on JWTs sent in client request headers or cookies. If your clients send JWTs in a `POST` body, contact your account team.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/jwt-validation/#page","headline":"JSON Web Tokens validation","description":"Verify incoming JWTs to detect token tampering and invalid tokens at the edge.","url":"https://developers.cloudflare.com/api-shield/security/jwt-validation/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/jwt-validation/og.png?v=10ef6f4cc8c50699","dateModified":"2026-10-01","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["JSON web token (JWT)"]}
```

---

---
description: Configure JWT validation and act on its results using the Cloudflare API.
title: Configure JWT validation via the API
image: https://developers.cloudflare.com/api-shield/security/jwt-validation/api/og.png?v=2a0c992fe482f981
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configure JWT validation via the API

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Use the Cloudflare API to configure [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/). A token configuration defines how Cloudflare finds and validates JWTs. You then use a WAF custom rule or a token validation rule to [act on the results](#act-on-validation-results).

## Token configurations

A token configuration defines the JSON Web Key Set (JWKS) used to validate JSON Web Tokens (JWTs). It also defines where Cloudflare finds JWTs in requests.

Note

Each zone supports up to 32 token configurations by default, with up to 16 keys per configuration. Contact your account team if you need a different allocation.

Token configurations require the following information:

| Field name | Description | Example | Notes |
| --- | --- | --- | --- |
| `title` | A human-readable name for the configuration that allows you to quickly identify the purpose of the configuration. | Production JWT configuration | Limited to 50 characters. |
| `description` | A human-readable description that gives more details than `title` which serves as a means to allow customers to better document the use of the configuration. | This configuration checks the JWT in the authorization header. | Limited to 500 characters. |
| `token_sources` | A list of possible locations where then JWT can be found on the request. | `http.request.headers[\"authorization\"][0]` <br> `http.request.cookies[\"Authorization\"][0]` | Refer to the [information](#token-sources) below. |
| `token_type` | This specifies the type of token to validate. | `jwt` | Only `jwt` is currently supported. |
| `credentials` | This describes the cryptographic keys that should be used to validate JWTs. Each key must be a JSON Web Key (JWK). | Refer to the example below. | Refer to the [information](#credentials) below. |

### Token sources

Each item must be a Ruleset Engine expression that resolves to a string.

Currently supported fields are `http.request.headers` and `http.request.cookies`.

You can set up to four token sources. The sources use `OR` logic: a valid token from any one source is sufficient. This supports clients using different token locations, including during a migration. If a request contains values in multiple configured sources, Cloudflare evaluates them one at a time and stops after the first valid token. Cloudflare does not combine token values or require multiple sources to be valid.

A source can contain an unprefixed JWT. It can also use the exact `Bearer` prefix, with a capital `B`, no colon, and one space after `Bearer`.

Refer to the [Ruleset Engine documentation](https://developers.cloudflare.com/ruleset-engine/rules-language/fields) for details on working with Ruleset Engine fields.

### Credentials

API Shield supports asymmetric RSA and elliptic curve keys and symmetric hash-based message authentication code (HMAC) keys:

| Key type | Supported algorithms | Requirements |
| --- | --- | --- |
| RSA | `RS256`, `RS384`, `RS512`, `PS256`, `PS384`, and `PS512` | RSA keys must be 2,048, 3,072, or 4,096 bits. |
| EC | `ES256` and `ES384` | Use curve `P-256` with `ES256` and curve `P-384` with `ES384`. |
| HMAC | `HS256`, `HS384`, and `HS512` | Use a symmetric secret of at least 32, 48, or 64 bytes, respectively. |

Provide an `alg` value for every JWK. Each JWK must also have a `kid`. The effective algorithm and key ID must match the `alg` and `kid` values in the JWT header.

For compatibility with identity providers that omit `alg`, API Shield defaults RSA keys to `RS256`, P-256 EC keys to `ES256`, and P-384 EC keys to `ES384`. Because an RSA key does not identify its signing algorithm, specify `alg` explicitly if the identity provider uses another supported RSA algorithm. HMAC keys must always specify `alg`.

For an HMAC key, set `kty` to `oct`. Set `k` to the raw symmetric credential encoded with unpadded Base64url. The decoded credential must meet the minimum length for its algorithm.

Caution

For new JWT deployments, Cloudflare recommends asymmetric, public-key algorithms such as RSA or elliptic curve algorithms. API Shield then needs only the public verification key, while the issuer retains the private signing key.

HMAC uses a shared credential. Anyone with that credential can sign and validate JWTs. Treat it as a secret and do not expose it in source code or logs. Cloudflare never stores symmetric credentials in plaintext. API responses do not include the credential.

Cloudflare will remove any fields that are unnecessary from each key and will drop keys that we do not support.

It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended.

## Token configuration JSON object

The example below shows a JSON object with all of the information necessary to create a token configuration using the Cloudflare API. If you would like to create JWKs for testing, refer to [mkjwk JSON Web Key Generator ↗︎](https://mkjwk.org/).

*Examplejson*

```json
{
	"title": "Production JWT configuration",
	"description": "This configuration checks the JWT in the authorization header or cookie.",
	"token_sources": [
		"http.request.headers[\"authorization\"][0]",
		"http.request.cookies[\"Authorization\"][0]"
	],
	"token_type": "jwt",
	"credentials": {
		"keys": [
			{
				"kty": "EC",
				"use": "sig",
				"crv": "P-256",
				"kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",
				"x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",
				"y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",
				"alg": "ES256"
			}
		]
	}
}
```

### Symmetric key example

The following example configures JWT validation with an `HS256` symmetric key. Replace `<BASE64URL_ENCODED_SECRET>` with an unpadded Base64url-encoded credential containing at least 32 decoded bytes.

*HS256 token configurationjson*

```json
{
	"title": "Production HMAC JWT configuration",
	"description": "This configuration checks the JWT in the authorization header.",
	"token_sources": ["http.request.headers[\"authorization\"][0]"],
	"token_type": "jwt",
	"credentials": {
		"keys": [
			{
				"kty": "oct",
				"alg": "HS256",
				"kid": "production-hmac-key",
				"k": "<BASE64URL_ENCODED_SECRET>"
			}
		]
	}
}
```

The response includes `kty`, `alg`, and `kid`, but does not include `k`:

*Symmetric key responsejson*

```json
{
	"credentials": {
		"keys": [
			{
				"kty": "oct",
				"alg": "HS256",
				"kid": "production-hmac-key"
			}
		]
	}
}
```

## Create a token configuration using the Cloudflare API

Use cURL or any other API client tool to send the new configuration to Cloudflare’s API to enable JWT validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) header.

*Example using cURLbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config" \
--header 'Content-Type: application/json' \
--data '{
    "title": "Production JWT configuration",
    "description": "This configuration checks the JWT in the authorization header or cookie.",
    "token_sources": [
        "http.request.headers[\"authorization\"][0]",
        "http.request.cookies[\"Authorization\"][0]"
    ],
    "token_type": "jwt",
    "credentials": {
        "keys": [
            {
                "kty": "EC",
                "use": "sig",
                "crv": "P-256",
                "kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",
                "x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",
                "y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",
                "alg": "ES256"
            }
        ]
    }
}'
```

The response will be in a Cloudflare `v4` response envelope and the result contains the created configuration. Note the returned ID. You can use it to reference the token configuration in JWT claim fields or token validation rules.

*Example responsejson*

```json
{
	"result": {
		"id": "d5902294-00c3-4aed-b517-57e752e9cd58",
		"token_type": "JWT",
		"title": "Production JWT configuration",
		"description": "This configuration checks the JWT in the authorization header or cookie.",
		"token_sources": [
			"http.request.headers[\"authorization\"][0]",
			"http.request.cookies[\"Authorization\"][0]"
		],
		"credentials": {
			"keys": [
				{
					"x": "QG3VFVwUX4IatQvBy7sqBvvmticCZ-eX5-nbtGKBOfI",
					"y": "A3PXCshn7XcG7Ivvd2K_DerW4LHAlIVKdqhrUnczTD0",
					"alg": "ES256",
					"crv": "P-256",
					"kid": "93UrzmNu1mqXs5cZcvCPkTlMHB2Jya30vSTkiBb0vhU",
					"kty": "EC"
				}
			]
		},
		"created_at": "2023-11-08T16:45:17.236841Z",
		"last_updated": "2023-11-08T16:45:17.236841Z"
	},
	"success": true,
	"errors": [],
	"messages": []
}
```

If API Shield defaults an omitted algorithm, the response includes the effective algorithm in `result`. The `messages` array also contains one message for each defaulted key:

*Example message for a defaulted algorithmjson*

```json
{
	"code": 110003,
	"message": "keys[0].alg was omitted and defaulted to \"RS256\" (kid \"key-1\")"
}
```

Inspect both `result` and `messages` to confirm the effective credentials.

## Act on validation results

After you create a token configuration, Cloudflare checks every request in the zone for a JWT at the configured token sources and validates any token it finds. You do not need a token validation rule or an operation in Endpoint Management for validation. Rules determine how Cloudflare acts on the results.

For new security policies, Cloudflare generally recommends using WAF custom rules.

- **[WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/)** — use these for zone-wide policies based on verified JWT claims. Custom rules can combine claims with other signals, such as [attack score](https://developers.cloudflare.com/waf/detections/attack-score/). Endpoints do not need to be in Endpoint Management.
- **Token validation rules** — use these when enforcement must apply only to specific operations in Endpoint Management. These rules support the `is_jwt_valid()` and `is_jwt_present()` functions, which are not available in custom rules.

To reference a custom claim in a rule expression, you can use `lookup_json_*` functions like [`lookup_json_string()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#lookup_json_string) with your token configuration ID and the claim name. For a complete example, refer to [Issue challenge for admin user in JWT claim based on attack score](https://developers.cloudflare.com/waf/custom-rules/use-cases/check-jwt-claim-to-protect-admin-user/). For all available fields and standard claims, refer to the [JWT validation fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/?field-category=JWT+validation) reference.

## Token validation rules

Token validation rules enforce a security policy using existing token configurations and operations in Endpoint Management.

Token validation rules can be configured using the Cloudflare API or [dashboard](https://developers.cloudflare.com/api-shield/security/jwt-validation/#add-a-jwt-validation-rule).

| Field name | Description | Example | Notes |
| --- | --- | --- | --- |
| `title` | A human-readable name allowing you to quickly identify it. | JWT validation on `v1` and `v2.example.com` | Limited to 50 characters. |
| `description` | A human-readable description that gives more details than `title` and helps to document it. | Log requests without a valid `authorization` header. | Limited to 500 characters. |
| `action` | The Firewall Action taken on requests that do not meet `expression`. | `log` | Possible: `log` or `block` |
| `enabled` | Enable or disable the rule. | `true` | Possible: `true` or `false` |
| `expression` | The rule's security policy. | `is_jwt_valid ("00170473-ec24-410e-968a-9905cf0a7d03")` | Make sure to escape any quotes when creating rules using the Cloudflare API. <br> Refer to [Define a security policy](#define-a-security-policy) below. |
| `selector` | Configure what operations are covered by this rule. |  | Refer to [Applying a rule to operations](#apply-a-rule-to-operations) below. |

### Selectors

Selectors control to which operations from Endpoint Management Cloudflare applies the action of a token validation rule.

If you only need enforcement on specific hostnames or subdomains of your apex domain, use the hostname in a selector to include matching operations in the JWT validation rule.

If you need to exclude endpoints from enforcement, use the endpoint's operation ID in a selector. For example, you can exclude an endpoint that issues or refreshes JWTs.

To find the operation ID, refer to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) or use the [Cloudflare API](https://developers.cloudflare.com/api/resources/api_gateway/subresources/operations/methods/list/).

## Define a security policy

Note

A request must also match an operation covered by this rule to trigger an action.

Refer to [Apply a rule to operations](#apply-a-rule-to-operations) for more information.

A token validation rule's expression defines a security policy that a request must meet.

For example, the expression `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("fddfc39e-3686-4683-ab23-bf917da6bb43")` will trigger if an incoming request does not have at least one valid authentication token.

These expressions are similar to [expressions used in Ruleset Engine](https://developers.cloudflare.com/ruleset-engine/rules-language/), with a few key differences:

- The token validation rule actions trigger if the expression evaluates `false`, as opposed to Ruleset expressions.
- The token validation rules can use dedicated functions that reference token configurations.

Operators such as `or`, `and`, `eq`, and more are usable in expressions in the same way as in expressions used in Ruleset Engine.

The following functions can be used to interact with JWT Tokens on a request:

- [`is_jwt_valid(token_configuration_id)`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#is_jwt_valid) — Returns true if the request has a valid token according to the token configuration with the ID `token_configuration_id`.
- [`is_jwt_present(token_configuration_id)`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#is_jwt_present) — Returns true if the request has a token as configured in the token configuration with the ID `token_configuration_id`.

These functions are only available in token validation rules. They are not available in WAF custom rules.

### Common use cases

Refer to the following example use cases to understand which security policy to use. For most use cases, Cloudflare recommends requiring a valid token across your API and excluding any paths that are used to establish or refresh tokens using selectors.

#### Require a token

The `is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")` expression will trigger an action if a request is missing a JWT.

It can be combined with a `log` action in the token validation rule to log requests that are missing an authentication header.

#### Require a valid token

The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e")` expression will trigger an action if a request does not have a valid JWT.

It can be combined with a `block` action in the token validation rule to block requests with no or invalid credentials.

#### Require at least one of two possible tokens

The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or is_jwt_valid("fddfc39e-3686-4683-ab23-bf917da6bb43")` expressions will trigger an action if a request does not have at least one valid token.

This can occur when your API accepts tokens from two different identity providers.

#### Require a valid token but ignore requests without a token

The `is_jwt_valid("51231d16-01f1-48e3-93f8-91c99e81288e") or not is_jwt_present("51231d16-01f1-48e3-93f8-91c99e81288e")` expressions will trigger an action if a request has an invalid token, ignoring requests with no tokens at all.

## Apply a rule to operations

Only one token validation rule can apply to an operation. If an operation is covered by multiple rules, then the rule with highest precedence will take effect.

You can configure which operations JWT validation is enforced on using the `selector` field.

Note

Selectors will also apply to new operations. New operations that match an existing selector will automatically be covered by that token validation rule.

For example, the following selector will apply a rule to all operations in `v1.example.com` and `v2.example.com`, except for two operations on these hosts:

*Selector examplejson*

```json
{
	"include": [
		{
			"host": ["v1.example.com", "v2.example.com"]
		}
	],
	"exclude": [
		{
			"operation_ids": [
				"f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
				"56828eae-035a-4396-ba07-51c66d680a04"
			]
		}
	]
}
```

Operations can be included at a host level and ignored on a per-operation basis.

You can use the `POST /zones/{zone_id}/token_validation/rules/preview` endpoint to see the operations covered by this rule.

Use the `page` and `per_page` query parameters to paginate operations. They default to page `1` and `20` operations per page. Each response includes one page in `result.operations` and pagination metadata in `result_info`.

*Example using cURLbash*

```bash
curl --request POST \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/preview?page=1&per_page=20' \
--header 'Content-Type: application/json' \
--data '{
    "include": [
        {
            "host": [
                "v1.example.com",
                "v2.example.com"
            ]
        }
    ],
    "exclude": [
        {
            "operation_ids": [
                "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
                "56828eae-035a-4396-ba07-51c66d680a04"
            ]
        }
    ]
}'
```

The response includes one page of operations on a zone with an additional `state` field.

The `state` field can be `ignored`, `excluded`, or `included`. Included operations will match the hostname selectors you specified. Excluded operations will match the operation IDs you specified in the selector. Ignored operations are those that do not match anything specified in the selector.

*Resultjson*

```json
{
	"result": {
		"operations": [
			{
				"operation_id": "ed15fcb6-5a73-41cd-91af-8c61e5bb1cdb",
				"method": "GET",
				"host": "example.com",
				"endpoint": "/api/accounts/{var1}",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "ignored"
			},
			{
				"operation_id": "e7a582cd-3cfb-4061-ab5b-722e6e42f545",
				"method": "GET",
				"host": "v1.example.com",
				"endpoint": "/api/accounts/{var1}",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "included"
			},
			{
				"operation_id": "ddd5df5a-795c-40ce-b38c-38e9d7ef9ae8",
				"method": "GET",
				"host": "v2.example.com",
				"endpoint": "/api/accounts/{var1}",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "included"
			},
			{
				"operation_id": "4d20befb-0120-45d5-9b29-5835fd41b44e",
				"method": "GET",
				"host": "v3.example.com",
				"endpoint": "/api/accounts/{var1}",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "ignored"
			},
			{
				"operation_id": "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
				"method": "POST",
				"host": "v1.example.com",
				"endpoint": "/login",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "excluded"
			},
			{
				"operation_id": "56828eae-035a-4396-ba07-51c66d680a04",
				"method": "POST",
				"host": "v2.example.com",
				"endpoint": "/login",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "excluded"
			},
			{
				"operation_id": "cf86874c-8d0c-4337-ae14-4e2459b541ac",
				"method": "GET",
				"host": "v3.example.com",
				"endpoint": "login",
				"last_updated": "2023-05-24T14:54:34.806506Z",
				"state": "ignored"
			}
		],
		"total": 7,
		"included": 2,
		"excluded": 2,
		"ignored": 3,
		"selected_hosts": ["v1.example.com", "v2.example.com"],
		"available_hosts": [
			"example.com",
			"v1.example.com",
			"v2.example.com",
			"v3.example.com"
		]
	},
	"success": true,
	"errors": [],
	"messages": [],
	"result_info": {
		"page": 1,
		"per_page": 20,
		"count": 7,
		"total_count": 7
	}
}
```

Operations with an `included` state will be covered by the token validation rule. The response also shows the hostnames of included operations in `result.selected_hosts` and shows all hostnames used by all zone operations in `result.available_hosts`.

You can also send an empty object in the request body:

*Example using cURLbash*

```bash
curl --request POST \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/preview' \
--header 'Content-Type: application/json' \
--data '{ }'
```

The response shows one page of zone operations and all possible hosts, which you can use to build your own selector.

## Token validation rule JSON object

The example below shows a JSON object with all the necessary information to create a token validation rule using the Cloudflare API.

Replace any token configurations IDs and operation IDs with the IDs that exist in your zone.

*Token Validation Rule JSON examplejson*

```json
[
	{
		"title": "JWT Validation on v1 and v2.example.com",
		"description": "Log requests without a valid authorization header.",
		"action": "log",
		"enabled": true,
		"expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",
		"selector": {
			"include": [
				{
					"host": ["v1.example.com", "v2.example.com"]
				}
			],
			"exclude": [
				{
					"operation_ids": [
						"f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
						"56828eae-035a-4396-ba07-51c66d680a04"
					]
				}
			]
		}
	}
]
```

## Create a token Validation rule using the Cloudflare API

Use cURL or any other API client tool to send the new configuration to Cloudflare's API to enable JWT validation. Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) header.

Replace any token configurations IDs and operation IDs with the IDs that exist in your zone.

A single request can create multiple rules. To do so, pass multiple rule objects in the JSON array of the request body.

*Example using cURLbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \
--header 'Content-Type: application/json' \
--data '[
    {
        "title": "JWT Validation on v1 and v2.example.com",
        "description": "Log requests without a valid authorization header.",
        "action": "log",
        "enabled": true,
        "expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",
        "selector": {
            "include": [
                {
                    "host": [
                        "v1.example.com",
                        "v2.example.com"
                    ]
                }
            ],
            "exclude": [
                {
                    "operation_ids": [
                        "f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
                        "56828eae-035a-4396-ba07-51c66d680a04"
                    ]
                }
            ]
        }
    }
]'
```

The response will be in a Cloudflare `v4` response envelope and the result contains the created rules. Note the returned ID for each rule, which can be used to edit or delete an existing rule.

*Resultjson*

```json
{
	"result": [
		{
			"id": "5ec7c417-6964-4b24-b82c-a23a7ec8f90c",
			"title": "JWT Validation on v1 and v2.example.com",
			"description": "Log requests without a valid authorization header.",
			"action": "log",
			"enabled": true,
			"expression": "is_jwt_valid(\"00170473-ec24-410e-968a-9905cf0a7d03\")",
			"selector": {
				"include": [
					{
						"host": ["v1.example.com", "v2.example.com"]
					}
				],
				"exclude": [
					{
						"operation_ids": [
							"f9c5615e-fe15-48ce-bec6-cfc1946f1bec",
							"56828eae-035a-4396-ba07-51c66d680a04"
						]
					}
				]
			},
			"created_at": "2023-10-18T12:08:09.575388Z",
			"last_updated": "2023-10-18T12:08:09.575388Z",
			"modified_by": "user@cloudflare.com"
		}
	],
	"success": true,
	"errors": [],
	"messages": []
}
```

## Maintenance

### Update token configuration

It is best practice to rotate keys regularly. You can add a new key, start issuing JWTs with that key, and then remove the old key.

The input to updating the keys is the same as when creating a configuration where you supplied the initial keys using the credentials key and needs to be a JWK.

Note

Cloudflare will remove any fields that are unnecessary from each key and will drop keys that we do not support.

It is highly recommended to validate the output of the API call to check that the resulting keys appear as intended.

Credential updates use the same algorithm defaulting behavior as configuration creation. The response includes normalized credentials in `result` and one message for each defaulted algorithm.

Use `PUT` to replace the complete key set. Every symmetric key in a `PUT` request must include `k`. Keys omitted from the request are removed.

*Example using cURLbash*

```bash
curl --request PUT \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config/{config_id}/credentials' \
--header 'Content-Type: application/json' \
--data '{
    "keys": [
        {
            "kty": "EC",
            "use": "sig",
            "kid": "test",
            "x": "-0LNzBheJPn-Zy6JmanTIUX7xc3jgqU714IQY0oU6mw",
            "y": "KONxBybUcRsJQmtu17jMAHsILSw009AuU3ulfUGv3FI",
            "alg": "ES256"
        },
        {
            "kty": "EC",
            "crv": "P-256",
            "kid": "test-2",
            "x": "iIbPRbOeLzjGPvv7iwmzCOTU03R0xDqbenp2D6GUcWo",
            "y": "tDkEh95PnfWwIXciCtdBBVA7wfghx_egmZ1Zcvu2lWw",
            "alg": "ES256"
        }
    ]
}'
```

Make sure to replace `{zone_id}` with the relevant zone ID and add your [authentication credentials](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) header.

#### Preserve or rotate a symmetric credential

Use `PATCH` to update the complete key set without resubmitting stored symmetric credentials. Cloudflare matches an existing key using its `alg` and `kid` values.

- Omit `k` for a matching symmetric key to preserve its credential.
- Include a new `k` value to rotate the credential.
- Include `k` when adding a symmetric key that does not already exist.
- Omit a key from `keys` to remove it from the configuration.
- Do not set `k` to `null`.

This example preserves the credential for `production-hmac-key` while adding an EC key:

*Preserve a symmetric credentialbash*

```bash
curl --request PATCH \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config/{config_id}/credentials' \
--header 'Content-Type: application/json' \
--data '{
    "keys": [
        {
            "kty": "oct",
            "alg": "HS256",
            "kid": "production-hmac-key"
        },
        {
            "kty": "EC",
            "alg": "ES256",
            "crv": "P-256",
            "kid": "production-ec-key",
            "x": "<BASE64URL_ENCODED_X_COORDINATE>",
            "y": "<BASE64URL_ENCODED_Y_COORDINATE>"
        }
    ]
}'
```

This example rotates the credential for the existing HMAC key:

*Rotate a symmetric credentialbash*

```bash
curl --request PATCH \
'https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/config/{config_id}/credentials' \
--header 'Content-Type: application/json' \
--data '{
    "keys": [
        {
            "kty": "oct",
            "alg": "HS256",
            "kid": "production-hmac-key",
            "k": "<NEW_BASE64URL_ENCODED_SECRET>"
        }
    ]
}'
```

### Update token validation rules

Token validation rules can be updated with a `PATCH` request. A single `PATCH` request can update multiple rules.

A `PATCH` request is specified as a JSON array in the request body. Each item in that array contains updates to a single rule, defined by `id`.

The following example updates one rule and disables another:

*Example using cURLbash*

```bash
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk"  \
--header "Content-Type: application/json" \
--data '[
    {
        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
        "action": "log",
        "title": "updated title"
    },
    {
        "id": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb",
        "enabled": false
    }
]'
```

Rules can be reordered by setting a position field in the `PATCH` body.

This example places rule `714d3dd0-cc59-4911-862f-8a27e22353cc` after rule `7124f9bc-d6b5-430d-b488-b6bc2892f2fb`:

*Example using cURLbash*

```bash
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \
--header 'Content-Type: application/json' \
--data '[
    {
        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
        "position": {
            "after": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb"
        }
    }
]'
```

This example places rule `714d3dd0-cc59-4911-862f-8a27e22353cc` before rule `7124f9bc-d6b5-430d-b488-b6bc2892f2fb`:

*Example using cURLbash*

```bash
curl --request PATCH \
"https://api.cloudflare.com/client/v4/zones/{zone_id}/token_validation/rules/bulk" \
--header 'Content-Type: application/json' \
--data '[
    {
        "id": "714d3dd0-cc59-4911-862f-8a27e22353cc",
        "position": {
            "before": "7124f9bc-d6b5-430d-b488-b6bc2892f2fb"
        }
    }
]'
```

## Perform JWT validation

Here is an overview of how JWT validation processes incoming requests:

1. We extract the JWT in accordance with the configuration from the incoming request.
2. We decode the JWT and look for the JWTs header KID claim.
3. We use the KID and ALG claim to find the correct keys in the list of supplied keys.

Note

The absence of matching keys directly marks the JWT as invalid.

4. We validate the authenticity of the JWT by checking the signature using the selected key.
5. Should the JWT contain an EXP claim (expiration time), we validate that the JWT is not expired.

Note

We allow a mismatch of up to 60 seconds to account for clock drifts between the Cloudflare network and the JWT issuer. A token may still be regarded as valid one minute after it was supposed to expire when both clocks are perfectly in sync.

6. Should the JWT contain a NBF claim (not before time), we validate that the JWT is already valid.

Note

The same accuracy applies as for EXP claims. As such, a token may be already regarded as valid one minute before its NBF claim in case of perfect synchronization between issuer and validator.

7. Cloudflare makes verified claims available as `http.request.jwt.claims` fields. WAF custom rules can act on these claims. Token validation rules can act on token presence and validity.
8. Security Analytics events in the Cloudflare dashboard for the `API Shield - Token Validation` service will explain violation reasons in the `Token validation violations` section of the event.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#page","headline":"Configure JWT validation via the API","description":"Configure JWT validation and act on its results using the Cloudflare API.","url":"https://developers.cloudflare.com/api-shield/security/jwt-validation/api/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/jwt-validation/api/og.png?v=2a0c992fe482f981","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["JSON web token (JWT)"]}
```

---

---
description: Use a Worker to keep your identity provider public keys updated for JWT validation.
title: Configure the Worker
image: https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/og.png?v=6411790a1866f55f
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configure the Worker

Last updated May 5, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Use a Worker to automatically keep your identity provider’s latest public key in the JWT validation configuration.

## Prerequisites

- Find your zone ID. You can locate this ID in your zone overview in the [Cloudflare dashboard ↗︎](https://dash.cloudflare.com/).
- Find your identity provider’s JSON Web Key Set (JWKs) URL. Identity providers commonly list it in Open Authorization (OAuth) settings.
- Create a [token validation configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/#add-a-token-validation-configuration).
- [Create a new API token ↗︎](https://dash.cloudflare.com/profile/api-tokens) with the API Gateway `Write` permission.

## Process

You must manually query the JWKs endpoint to ensure the JWKs exists in the expected location and format. Then, create a Worker to automate updating of the JWKs and a [Worker Secret](https://developers.cloudflare.com/workers/configuration/secrets/#via-the-dashboard) to house the API key used for updating API Shield settings. You can then schedule the Worker to automatically update the JWKs.

### Manually query the JWKs endpoint

Find your Identity Provider’s URL and fetch the keys using `curl` and `jq`. Your URL may return more than just the issuer’s keys, so Cloudflare recommends using `jq` to filter the response to only return the keys. You must update the provided Worker sample code if your JWKs do not have a `keys` object.

Note

The keys listed below are for example purposes only and must not be used in your production environment, as they will never match the keys used by your identity provider to sign JWTs.

*Query the JWKs endpointsh*

```sh
curl https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/certs -s | jq .keys
```

```sh
[
  {
    "kid": "ca96ae653935dbfb49b4e19de600cc5f9d5c63e3ac2dbee406ed4bf0ae100cce",
    "kty": "RSA",
    "alg": "RS256",
    "use": "sig",
    "e": "AQAB",
    "n": "9dG9Ph4ffncvEA9FO9pVMfJ1dh_5mtuyiIE4ap9ScrufVPq1I34St_dhcFavKiytK7Id7gTlgQgaouoJ0I5OJ_bytgX-B7oOUQHO-nJOAMycORXN8ZNaMBPKg9nBLL_BFY0YX5HggqrkXkZjJ--R4JpB30ENS8A6hxmEJ__yGMZTE2LHZoiYj9iyGNu3s3JflAoRlmziI8LsFXwyFAJUWRZq4SkSfyrRJ89pXPxIqBn9uYBtnxWzUpWG3xKZu0JAbi9YiwFCJrSe_CarvpARoWsOldtrty5yT1yJ1PZlImlF-yuEwjOoZxeib4WSidABZH0O3pbDACo8MfxR5rghHQ"
  },
  {
    "kid": "1e590a6dcd60e3e2306c21eca19144c59d591531267a3ebde8d521f40894329d",
    "kty": "RSA",
    "alg": "RS256",
    "use": "sig",
    "e": "AQAB",
    "n": "6uj6PgDq-bPsdFjiQ6M3yaxMxBUnnYj20xtLciHNafqrygAjnZKjl8LfCO_mtZ7jxfJNCARsz0L3sF9LAtARZqcsUvYLUlNDzflwNTe8woCT7yw0Ml2ZV5BWDbc3izEQnvjlBDGWv9p5jv-D-YNExtIzZKsRKyoy7hSu5FhyxmPfiAXo8b67f0dNy8V8HZfQJ5i9VGyK4Z5xKM-FjHOrC2uIbhzUE6wDe_0M23RTCxj7ZxzXUzZzc-_EBjmZDAI3tI2zBYymO55_gw8zHrNsZ4-32YvNTjBAiTLsjvKlsvNtPTN8q3saoZJWQMSiMi8dRalgA6pUDgcNs5lB9E7tWw"
  }
]
```

### Configure the Worker

1. [Create a new Worker](https://developers.cloudflare.com/workers/get-started/guide/).
2. Copy and paste the example code below into your new Worker, completely replacing any code that already exists.
3. Replace the current zone ID with your zone ID.
4. Replace the current token validation configuration ID with your token validation configuration.
5. Replace the current identity provider’s URL with your identity provider’s key URL.

   Note

   Identity provider URLs can typically be accessed at a known URL specific to your deployment. If you are unsure of the URL, contact your identity provider.
6. If your JWKs URL returns the keys in any JSON object other than `keys`, update the `fetchCredentials()` function to return only the key data.
7. Select **Create** > **Deploy**.
8. In the Worker settings, go to **Variables** and add an environment variable named `CF_API_TOKEN` with the value of the API token that you have created.
9. In the Worker Triggers, assign a [cron trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) to the Worker. Cloudflare recommends a frequent update interval to ensure you always have the latest keys and that an immediate key rotation by your identity provider causes minimal downtime.

   *JavaScript example codejs*

   

   ```js
   /**
   * Update Token Validation Credentials
   *
   * This example shows how a Cloudflare Workers cron trigger can be used to
   * automatically rotate a JWKs for a Token Configuration.
   *
   * To configure this Worker:
   *
   *   1. Replace `token_config_id` with the ID of the Token Config to update
   *   2. Replace `zone_id` with your Zone ID
   *   3. Replace `url` with a publicly accessible URL with the JWKs you want to use
   *   4. Create a new API Token with "Zone.API Gateway Edit" permissions and add it as a secret with the name `CF_API_TOKEN` (see https://developers.cloudflare.com/workers/configuration/secrets/)
   *
   * This worker also handles GET and POST requests:
   *   - GET will fetch and show the credentials from the provided URL (`GET https://random-worker-name-c134.example.workers.dev/`)
   *   - POST triggers an update and returns the Cloudflare API response of that update (`POST https://random-worker-name-c134.example.workers.dev/`)
   *
   * Use these to test that the Worker is properly configured.
   *
   * After setting up the worker, you can create a cron trigger to run it periodically.
   * For more information on cron triggers, refer to https://developers.cloudflare.com/workers/configuration/cron-triggers/
   *
   * Learn more about Workers at https://developers.cloudflare.com/workers/
   */

   var zone_id = "760549bc17c54280d6e6ae256c3dd6ae";
   var token_config_id = "91007e72-8f17-46b7-a223-5e57bd333b78";
   var url = "https://cfdata.cloudflareaccess.com/cdn-cgi/access/certs"; // JWKs

   /**
   * fetchCredentials fetches new Token Configuration credentials using the URL defined above.
   * This returns a JSON string with the credentials.
   *
   * Use this function to fetch and parse credentials.
   *
   * @returns {string} credentials
   */
   async function fetchCredentials() {
   	var requestOptions = {
   		method: "GET",
   		redirect: "follow",
   	};
   	const keys = await fetch(url, requestOptions)
   		.then((e) => e.json())
   		.then((e) => e.keys);
   	return JSON.stringify({ keys: keys });
   }

   /**
   * updateCredentials updates Token Configuration credentials using the Cloudflare API.
   * Credentials are fetched using fetchCredentials, which also does any required processing.
   *
   * @param {string} bearer Cloudflare API Bearer token with "Zone.API Gateway Edit" permissions
   * @returns {string} Cloudflare API response from the update request
   */
   async function updateCredentials(bearer) {
   	// Cloudflare API endpoint for credentials update
   	const url = `https://api.cloudflare.com/client/v4/zones/${zone_id}/token_validation/config/${token_config_id}/credentials`;
   	const init = {
   		body: await fetchCredentials(),
   		method: "PUT",
   		headers: {
   			Authorization: `Bearer ${bearer}`,
   			"content-type": "application/json;charset=UTF-8",
   		},
   	};
   	const response = await fetch(url, init);
   	return response.text();
   }

   // Export a default object containing event handlers
   export default {
   	/**
   	* fetch handles requests made directly to the Worker.
   	*
   	*/
   	async fetch(request, env, ctx) {
   		let responseBody = "";
   		if (request.method === "GET") {
   			responseBody = await fetchCredentials();
   		} else if (request.method === "POST") {
   			responseBody = await updateCredentials(env.CF_API_TOKEN);
   		}
   		return new Response(responseBody, {
   			headers: { "content-type": "application/json;charset=UTF-8" },
   		});
   	},

   	/**
   	* scheduled is the handler for cron triggers.
   	*
   	* For details, refer to https://developers.cloudflare.com/workers/configuration/cron-triggers/
   	*
   	*/
   	async scheduled(request, env, ctx) {
   		ctx.waitUntil(updateCredentials(env.CF_API_TOKEN));
   	},
   };
   ```



Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/#page","headline":"Configure the Worker","description":"Use a Worker to keep your identity provider public keys updated for JWT validation.","url":"https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/jwt-validation/jwt-worker/og.png?v=6411790a1866f55f","dateModified":"2026-05-05","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["JSON web token (JWT)","JavaScript"]}
```

---

---
description: Forward verified JWT claims to your origin using Request Header Transform Rules.
title: Enhance Request Header Transform Rules
image: https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/og.png?v=2b6743ba9c467e87
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Enhance Request Header Transform Rules

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

You can forward verified claims from a [JSON Web Token (JWT)](https://developers.cloudflare.com/api-shield/security/jwt-validation/) to your origin in a header by creating a [Request Header Transform Rule](https://developers.cloudflare.com/rules/transform/request-header-modification/).

Verified claims are available to Request Header Transform Rules through the `http.request.jwt.claims` fields. They are not available to [URL Rewrite Rules](https://developers.cloudflare.com/rules/transform/url-rewrite/).

For example, the following expression will extract the user claim from a token processed by the token configuration with `TOKEN_CONFIGURATION_ID`:

```txt
lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "claim_name")
```

Refer to [Configure JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/) for more information about creating a token configuration.

## Create a Request Header Transform Rule

As an example, create a Request Header Transform Rule to send the `x-send-jwt-claim-user` request header to the origin:

1. In the Cloudflare dashboard, go to the **Rules overview** page. [Go to **Overview** ↗](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview)
2. Select **Create rule** > **Request Header Transform Rules**.
3. Enter a rule name and a filter expression, if applicable.
4. Choose **Set dynamic**.
5. Set the header name to `x-send-jwt-claim-user`.
6. Set the value to:

   ```txt
   lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "claim_name")
   ```

   `<TOKEN_CONFIGURATION_ID>` is your token configuration ID found in JWT validation and `claim_name` is the JWT claim you want to add to the header.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/#page","headline":"Enhance Request Header Transform Rules","description":"Forward verified JWT claims to your origin using Request Header Transform Rules.","url":"https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/og.png?v=2b6743ba9c467e87","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["JSON web token (JWT)"]}
```

---

---
description: Require client certificates to authenticate API requests with mutual TLS.
title: Mutual TLS (mTLS)
image: https://developers.cloudflare.com/api-shield/security/mtls/og.png?v=230ffde4112b78da
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Mutual TLS (mTLS)

Last updated May 6, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/mtls/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Note

While API Shield is not required to use mTLS, many teams may use mTLS to protect their APIs.

[Mutual TLS (mTLS)](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/) authentication is a common security practice that uses client certificates to ensure traffic between client and server is bidirectionally secure and trusted. mTLS also allows requests that do not authenticate via an identity provider — such as Internet-of-things (IoT) devices — to demonstrate they can reach a given resource.

Use mTLS when you need to verify the identity of API clients, such as mobile applications, IoT devices, or services that connect to your API.

![mTLS sequence diagram](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=900,height=1256,format=webp/_astro/api-shield-call-sequence.DjXyNgan.png)

mTLS also supports [gRPC ↗︎](https://grpc.io/docs/what-is-grpc/introduction/)-based APIs, which use binary formats such as protocol buffers rather than JSON.

## Setup

To set up mTLS for one or more hosts using the dashboard, refer to [Configure mTLS](https://developers.cloudflare.com/api-shield/security/mtls/configure/).

## Availability

All Cloudflare plans can set up mTLS with a Cloudflare-managed certificate authority (CA). Enterprise customers can [upload up to five non-Cloudflare CAs](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/). For higher limits, contact your account team.

## Limitations

When using Yubikeys, the browser may prompt for unlocking the key due to a problem in Yubikey's PKCS#11 library.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/mtls/#page","headline":"Mutual TLS (mTLS)","description":"Require client certificates to authenticate API requests with mutual TLS.","url":"https://developers.cloudflare.com/api-shield/security/mtls/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/mtls/og.png?v=230ffde4112b78da","dateModified":"2026-05-06","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["mTLS"]}
```

---

---
description: Cloudflare mTLS now supports client certificates that have not been issued by Cloudflare CA. Learn how you can bring your own CA and use it with Cloudflare mTLS.
title: Bring your own CA for mTLS
image: https://developers.cloudflare.com/ssl/client-certificates/byo-ca/og.png?v=c020e73e6b5686bc
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ssl/llms.txt  
> Use this file to discover all available pages before exploring further.

# Bring your own CA for mTLS

Last updated Sep 8, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

This page explains how you can manage client certificates that have not been issued by Cloudflare CA. For a broader overview, refer to the [mTLS at Cloudflare learning path](https://developers.cloudflare.com/learning-paths/mtls/concepts/).

Bring your own CA (BYOCA) is especially useful if you already have mTLS implemented and [client certificates are already installed](https://developers.cloudflare.com/ssl/client-certificates/#how-it-works) on devices.

## Availability

- This feature is only available on Enterprise accounts.
- Each Enterprise account can upload up to five CAs. This quota does not apply to CAs uploaded through [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/).
- The CA certificate quota is shared across [API Shield](https://developers.cloudflare.com/api-shield/security/mtls/configure/), [Workers mTLS](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/), and [Cloudflare Gateway](https://developers.cloudflare.com/cloudflare-one/traffic-policies/).
- To increase this quota, contact your account team.

Note

If you exceed the CA certificate quota, the API returns error `1489` with the message "Hit maximum CA cert allocation." Contact your account team to request a quota increase.

Cloudflare Access uses a separate quota

CAs uploaded through [Cloudflare Access](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/) use a separate quota that is not counted against the five-CA limit. If you see error `12130` ("maximum number of certificates has been reached") in Access, this relates to the Access certificate quota, not the BYOCA CA quota.

## When to use BYOCA

BYOCA works well if:

- You already have an internal CA and client certificates are installed on your devices.
- You issue certificates at high volume or high churn — for example, one certificate per ephemeral virtual machine, container, or device. With BYOCA, Cloudflare stores only your CA certificate, not individual issued certificates, so there is no per-certificate quota.
- You want full control over certificate validity periods, key types, and revocation through your own CA tooling.

If you only have a small, stable set of devices or services to authenticate, the [Cloudflare-managed CA](https://developers.cloudflare.com/ssl/client-certificates/create-a-client-certificate/) is simpler to set up.

## CA certificate requirements

When you upload your CA, Cloudflare validates the certificate according to certain requirements.

- The CA certificate can be from a publicly trusted CA or self-signed.
- In the certificate `Basic Constraints`, the attribute `CA` must be set to `TRUE`.
- The certificate must use one of the signature algorithms listed below:<details><summary>

  Allowed signature algorithms</summary>

<code>x509.SHA1WithRSA</code>

  <code>x509.SHA256WithRSA</code>

  <code>x509.SHA384WithRSA</code>

  <code>x509.SHA512WithRSA</code>

  <code>x509.ECDSAWithSHA1</code>

  <code>x509.ECDSAWithSHA256</code>

  <code>x509.ECDSAWithSHA384</code>

  <code>x509.ECDSAWithSHA512</code></details>

Note

Uploading the CA private key is only required if you wish to use [Zero Trust's block page](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/user-side-certificates/custom-certificate/). To upload your own CA with the private key, use the [Upload mTLS certificate](https://developers.cloudflare.com/api/resources/mtls_certificates/methods/create/) endpoint.

## Set up mTLS with your CA

1. In the Cloudflare dashboard, go to the **Client Certificates** page. [Go to **Client Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select **Add Certificate**.
3. In the **Certificate Authority** dropdown, select **Bring your own CA**.
4. Upload your CA certificate file (PEM encoded) and enter a name for the CA.
5. Select **Continue**.
6. On the **Associate Hostnames** page, enter the hostname that should use this CA for mTLS validation and select **Add** for each one. You can also skip this step and associate hostnames later.
7. Select **Save** to confirm.

1. Use the [Upload mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls_certificates/methods/create/) to upload the CA root certificate.

- `ca` boolean required
  - Set to `true` to indicate that the certificate is a CA certificate.
- `certificates` string required
  - Insert content from the `.pem` file associated with the CA certificate, formatted as a single string with `\n` replacing the line breaks.
- `name` string optional
  - Indicate a unique name for your CA certificate.
- `private_key` string optional
  - Insert content from the `.pem` file associated with the private key for the certificate, formatted as a single string with `\n` replacing the line breaks.

2. Take note of the certificate ID ( `id`) that is returned in the API response.
3. Use the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate_authorities/subresources/hostname_associations/methods/update/) to enable mTLS in each hostname that should use the CA for mTLS validation. Use the following parameters:

- `hostnames` array required
  - List the hostnames that will be using the CA for client certificate validation.

    Caution

    Submitting an empty array will remove all hostname associations.
- `mtls_certificate_id` string required
  - Indicate the certificate ID obtained from the previous step.

    Caution

    If no `mtls_certificate_id` is provided, the action will be performed against the [Cloudflare-managed CA](https://developers.cloudflare.com/ssl/client-certificates/).

4. (Optional) Make a [GET request](#list-ca-hostname-associations) to confirm the CA hostname associations.

After uploading the CA and associating hostnames, create a custom rule to enforce client certificate validation. You can do this [via the dashboard](https://developers.cloudflare.com/learning-paths/mtls/mtls-app-security/#3-validate-the-client-certificate-in-the-waf) or [via API](https://developers.cloudflare.com/waf/custom-rules/create-api/).

```txt
  "expression": "(http.host in {\"<HOSTNAME_1>\" \"<HOSTNAME_2>\"} and not cf.tls_client_auth.cert_verified)",
  "action": "block"
```

Note

When using [CNAME records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#cname), enforce mTLS on the specific hostname where it should be checked. It is not enough to have it set on the CNAME target.

### Multiple CAs for one hostname

There can be multiple CAs (Cloudflare-managed or BYOCA) associated with the same hostname. For BYOCA certificates, the most recently deployed certificate will be prioritized.

If you wish to remove the association from the Cloudflare-managed certificate and only use your BYOCA certificate(s):

1. In the Cloudflare dashboard, go to the **Client Certificates** page. [Go to **Client Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. On the **Hosts** section under **Cloudflare-issued Client Certificates**, select **Edit**.
3. Select the cross next to the hostname you want to remove.
4. Select **Save** to confirm.

1. [List the hostname associations](https://developers.cloudflare.com/api/resources/certificate_authorities/subresources/hostname_associations/methods/get/) **without** the `mtls_certificate_id` parameter.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>SSL and Certificates Write</code>
- <code>SSL and Certificates Read</code>

</details>

*List Hostname Associationsbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations" \
	--request GET \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

2. Copy the `hostnames` array returned by the API and update it, removing the hostname that should no longer use the Cloudflare-managed CA.
3. Use the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate_authorities/subresources/hostname_associations/methods/update/) **without** the `mtls_certificate_id` parameter to perform the action against the Cloudflare-managed CA. For `hostnames` use the list from the previous step.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>SSL and Certificates Write</code>

</details>

*Replace Hostname Associationsbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations" \
	--request PUT \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
	--json '{
		"hostnames": [
				"<UPDATED_HOSTNAME_ASSOCIATIONS>"
		]
	}'
```

## Delete an uploaded CA

If you want to remove a CA that you have previously uploaded, you must first remove any hostname associations that it has.

1. In the Cloudflare dashboard, go to the **Client Certificates** page. [Go to **Client Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the **BYOCA** tab.
3. Find the CA you want to delete and select the three dots next to it.
4. Remove all associated hostnames first, if any exist.
5. Select the delete option and confirm.

1. Make a request to the [Replace Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate_authorities/subresources/hostname_associations/methods/update/), with an empty array for `hostnames` and specifying your CA certificate ID in `mtls_certificate_id`:

```txt
  "hostnames": [],
  "mtls_certificate_id": "<CERTIFICATE_ID>"
```

2. Use the [Delete mTLS certificate endpoint](https://developers.cloudflare.com/api/resources/mtls_certificates/methods/delete/) to delete the certificate.

## List CA hostname associations

1. In the Cloudflare dashboard, go to the **Client Certificates** page. [Go to **Client Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select the **BYOCA** tab.
3. Find the CA you want to inspect and select the three dots next to it.
4. Select **Edit hostnames**. The **Certificate Details** panel displays the associated hostnames.

Use the [List Hostname Associations endpoint](https://developers.cloudflare.com/api/resources/certificate_authorities/subresources/hostname_associations/methods/get/) with the `mtls_certificate_id` query parameter set to the certificate ID of the uploaded CA.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>SSL and Certificates Write</code>
- <code>SSL and Certificates Read</code>

</details>

*List Hostname Associationsbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/certificate_authorities/hostname_associations?mtls_certificate_id=ID_FROM_STEP_2" \
	--request GET \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/ssl/client-certificates/byo-ca/#page","headline":"Bring your own CA for mTLS","description":"Cloudflare mTLS now supports client certificates that have not been issued by Cloudflare CA. Learn how you can bring your own CA and use it with Cloudflare mTLS.","url":"https://developers.cloudflare.com/ssl/client-certificates/byo-ca/","inLanguage":"en","image":"https://developers.cloudflare.com/ssl/client-certificates/byo-ca/og.png?v=c020e73e6b5686bc","dateModified":"2026-09-08","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["mTLS"]}
```

---

---
description: Set up mTLS authentication rules to require client certificates for API hosts.
title: Configure mTLS
image: https://developers.cloudflare.com/api-shield/security/mtls/configure/og.png?v=c33eefe4e6db8977
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configure mTLS

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/mtls/configure/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

When you configure [mTLS authentication](https://developers.cloudflare.com/api-shield/security/mtls/) for API hosts, Cloudflare can block requests that do not have a [client certificate](https://developers.cloudflare.com/ssl/client-certificates/) for mTLS authentication. Blocking applies only to requests that match the hostname and path conditions in your mTLS rule.

## Prerequisites

Before you can protect your API or web application with mTLS rules, you need to:

- Check that the certificate installed on your origin server matches the hostname of the client certificate, for example `api.example.com`. Origin server wildcard certificates such as `*.example.com` are not supported.
- [Create a client certificate](https://developers.cloudflare.com/ssl/client-certificates/create-a-client-certificate/).
- [Configure your mobile app or IoT device](https://developers.cloudflare.com/ssl/client-certificates/configure-your-mobile-app-or-iot-device/) to use your Cloudflare-issued client certificate.
- [Enable mutual Transport Layer Security (mTLS) for a host](https://developers.cloudflare.com/ssl/client-certificates/enable-mtls/) in your zone.

Note

While API Shield is not required to use mTLS, many teams may use mTLS to protect their APIs.

Caution

By default, API Shield mTLS uses client certificates issued by a Cloudflare-managed CA. If you need to use certificates issued by another CA, refer to [Bring your own CA for mTLS](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

## Create an mTLS rule via the Cloudflare dashboard

1. In the Cloudflare dashboard, go to **Client Certificates** page. [Go to **Client Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/client-certificates)
2. Select **Create a mTLS rule**.
3. In **Custom rules**, several rule parameters have already been filled in. Enter the URI path you want to protect in **Value**.
4. (Optional) Add a `Hostname` field and enter the mTLS-enabled hostnames you wish to protect in **Value**.
5. In **Choose action**, select `Block`.
6. Select **Deploy** to make the rule active.

Once you have deployed your mTLS rule, requests without a [valid client certificate](https://developers.cloudflare.com/ssl/client-certificates/) are blocked only when they match the hostname and URI path conditions configured in the rule.

### Expression Builder

To review your mTLS rule in the Expression Builder, select the **wrench icon** associated with your rule.

In the **Expression Preview**, your mTLS rule includes a [compound expression](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/#compound-expressions) formed from two [simple expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/#simple-expressions) joined by the `and` operator.

The first expression — `not cf.tls_client_auth.cert_verified` — returns `true` when a request to access your API or web application does not present a valid client certificate.

The second expression uses the `http.request.uri.path` field, combined with the `in` operator, to capture the URI paths your mTLS rule applies to.

Because the [action](https://developers.cloudflare.com/ruleset-engine/rules-language/actions/) for your rule is *Block*, requests that match the configured hostname and path conditions must present a valid client certificate.

Cloudflare recommends also validating the issuer Subject Key Identifier (SKI) hash. Without this check, any valid client certificate is accepted regardless of which certificate authority (CA) issued it. Adding the SKI hash restricts access to certificates from a specific CA.

You can implement this by using an expression similar to the following:

```txt
not (cf.tls_client_auth.cert_verified and cf.tls_client_auth.cert_issuer_ski eq "A5AC554235DBA6D963B9CDE0185CFAD6E3F55E9F")
```

To obtain the issuer Subject Key Identifier (SKI) hash of a client certificate stored in the `mtls.crt` file, you can run the following OpenSSL command:

```sh
openssl x509 -noout -ext authorityKeyIdentifier -in mtls.crt | tail -n1 | tr -d ': '
```

```txt
A5AC554235DBA6D963B9CDE0185CFAD6E3F55E9F
```

### Check for revoked certificates

To check for [revoked client certificates](https://developers.cloudflare.com/ssl/client-certificates/revoke-client-certificate/), you can either add a new mTLS rule or add a new expression to the [default rule](#expression-builder). To check for revoked certificates, you must use the Expression Builder.

When a request includes a revoked certificate, the `cf.tls_client_auth.cert_revoked` field is set to `true`. If you combined this with the [default mTLS rule](#expression-builder), it would look similar to the following:

```sql
((not cf.tls_client_auth.cert_verified or cf.tls_client_auth.cert_revoked) and http.request.uri.path in {"/admin"})
```

Caution

This check only applies to client certificates issued by the Cloudflare-managed CA. Cloudflare currently does not check certificate revocation lists (CRL) for [CAs that have been uploaded](https://developers.cloudflare.com/ssl/client-certificates/byo-ca/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/mtls/configure/#page","headline":"Configure mTLS","description":"Set up mTLS authentication rules to require client certificates for API hosts.","url":"https://developers.cloudflare.com/api-shield/security/mtls/configure/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/mtls/configure/og.png?v=c33eefe4e6db8977","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["mTLS"]}
```

---

---
description: Supply Schema Profiles through uploaded OpenAPI schemas.
title: Schema validation
image: https://developers.cloudflare.com/api-shield/security/schema-validation/og.png?v=79e7231a72607932
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Schema validation

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/schema-validation/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Note

Schema Validation is the uploaded source for a Schema Profile. For the shared detection and mitigation model, refer to [Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/).

The API schema defines which API requests are valid based on several request properties like target endpoint, path or query variable format, and HTTP method.

Schema Validation compares incoming requests with an uploaded OpenAPI schema. The uploaded schema supplies expected request structure for a Schema Profile.

After the uploaded profile becomes available, Cloudflare generates an **always-on detection**. Use `cf.schema_validation.uploaded.violated` to analyze and mitigate violations.

The detection does not mitigate traffic by itself. Review results in [Profile Analysis](https://developers.cloudflare.com/waf/detections/application-profiles/analyze-profile-detections/) before [enforcing the profile with Custom Rules](https://developers.cloudflare.com/waf/detections/application-profiles/enforce-profiles-with-custom-rules/).

Schema Validation 2.0 is the current version. For previous-version reference, refer to [Configure Classic Schema Validation](https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/).

## Configure an uploaded schema

Endpoints must exist as saved operations in **Web Assets** > **Operations**. Uploading through the dashboard adds schema operations automatically.

When using the API or Terraform, add schema operations separately. For automation details, refer to [API configuration](https://developers.cloudflare.com/api-shield/security/schema-validation/api/) or [Terraform](https://developers.cloudflare.com/api-shield/reference/terraform/#manage-schema-validation).

### Upload a schema

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Add validation**.
4. Upload an OpenAPI schema file.
5. Select **Add schema and endpoints**.

Changes may take several minutes, depending on the operation count.

### Manage uploaded schemas

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Schema validation** tab.
3. Select **Schema settings**.
4. Filter by **API abuse**.
5. Under **Schema validation** > **Active schemas**, review uploaded schemas.
6. From the schema overflow menu, download or delete the schema.

Deleting an uploaded schema stops its profile evaluation. Associated operations remain in the Web Assets inventory.

### Add a fallthrough rule

A fallthrough rule matches requests that do not match saved operations. Requests that match candidate operations also match the fallthrough rule. Use this WAF Custom Rule to protect against unidentified endpoints.

1. In the Cloudflare dashboard, go to the **Security rules** page. [Go to **Security rules** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Templates**.
3. Find `Mitigate API requests to unidentified endpoints` and select **Preview template**.
4. Enter a descriptive rule name.
5. Choose the intended hostnames and rule action.
6. Select **Save as draft** or **Deploy**.

For custom logic, use `cf.api_gateway.fallthrough_detected`. Scope the rule to your API hostname or root path.

---

## Specifications

Cloudflare accepts [OpenAPI v3.0 schemas ↗︎](https://spec.openapis.org/oas/v3.0.3.html). OpenAPI v3.1 uploads can succeed when they use v3.0-compatible semantics. OpenAPI v3.1-only semantics are not supported. The accepted file formats are YAML (`.yml` or `.yaml` file extension) and JSON (`.json` file extension).

OpenAPI schemas generated by different tooling may not be specific enough to import to Schema validation. Use a third-party tool such as [Swagger Editor ↗︎](https://swagger.io/tools/swagger-editor/) to ensure that schemas are compliant to the OpenAPI specification.

---

## Limitations

Cloudflare API Shield's Schema validation (importing) and [Schema learning](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/) (exporting) capabilities rely on [OpenAPI Specification (OAS) v3.0 ↗︎](https://spec.openapis.org/oas/v3.0.3) semantics.

This support includes all patch versions, such as OAS v3.0.x. Cloudflare processes compatible OAS v3.1 uploads with v3.0 semantics, but does not support v3.1-only semantics. OpenAPI 2.0 is not supported.

Note

Cloudflare recommends using a third-party tool like [Swagger Editor ↗︎](https://editor.swagger.io/) to ensure that all schemas are fully compliant with the OAS v3.0 specification before upload.

Currently, API Shield does not support some features of API schemas, including the following: all responses, external references, non-basic path templating, or unique items.

There is a limit of 10,000 total operations for enabled schemas for Enterprise customers subscribed to [API Shield](https://developers.cloudflare.com/api-shield/). To raise this limit, contact your account team.

### Body size for validation

Schema Validation structurally inspects request bodies up to a plan-specific maximum size. For an operation with an applicable body schema, an oversized body produces a Schema Validation body-size violation.

The default body size limits are:

| Plan | Default body size limit |
| --- | --- |
| Free | 1 KiB |
| Pro | 8 KiB |
| Business | 8 KiB |
| Enterprise | 128 KiB |

Note

This limit is separate from the [WAF maximum body inspection size](https://developers.cloudflare.com/waf/managed-rules/#maximum-body-size), which controls how much of the request payload the WAF scans. Increasing one does not affect the other.

#### Identify requests exceeding the body size limit

Use request logs to compare body sizes with your plan limit.

For limits on Free, Pro, Business, or Enterprise customers not subscribed to API Shield, refer to [Plans](https://developers.cloudflare.com/api-shield/plans/).

### Required fields

Schema Validation requires the following fields in the listed contexts. It can infer some parameter schema types as described in this section.

#### `schema`

- [`type` ↗︎](https://spec.openapis.org/oas/v3.0.3#schema-object)
  - Parameter schemas require a supported type unless Schema Validation can infer one from `items`, `properties`, single-type `enum` values, or unambiguous composition branches. If the specific type is not supported by Schema Validation, set the type to `string` instead.

#### `parameter`

- [`schema` ↗︎](https://spec.openapis.org/oas/v3.0.3#schema-object)
  - Schema validation does not support the content field in parameters. For more details, refer to the [notes on validated and supported fields](#notes-on-validated-and-supported-fields) below. Instead, a schema is strictly required on all parameters objects.

### Notes on validated and supported fields

Refer to the information below for more details on Schema validation's current support for various OpenAPI specification (OAS) objects and fields.

#### `servers`

- [`url` ↗︎](https://spec.openapis.org/oas/v3.0.3#server-object)
  - Schema validation does not support relative URLs.
- [`variables` ↗︎](https://spec.openapis.org/oas/v3.0.3#server-variable-object)
  - Server variables are not validated.

#### `parameter`

- [`style` ↗︎](https://spec.openapis.org/oas/v3.0.3#parameter-object)
  - Only the default values are supported: `"simple"` (path or header parameters) and `"form"` (query or cookie parameters).
- [`explode` ↗︎](https://spec.openapis.org/oas/v3.0.3#parameter-object)
  - Only the default values are supported: `true` (for form) and `false` (for simple).
- [`content` ↗︎](https://spec.openapis.org/oas/v3.0.3#parameter-object)
  - The content field is not supported in parameters. Use the schema field instead.
- [`type` ↗︎](https://spec.openapis.org/oas/v3.0.3#parameter-object)
  - Cloudflare currently does not validate object type parameters.

#### `reference`

- [`$ref` ↗︎](https://spec.openapis.org/oas/v3.0.3#reference-object)
  - Local component references, such as `#/components/schemas/Pet`, are supported. External references and other relative references are not supported. Before uploading a schema with unsupported references, use an OpenAPI bundling tool, such as the [Redocly CLI `bundle` command ↗︎](https://redocly.com/docs/cli/commands/bundle), to convert it to a single-file schema.

#### `requestBody`

- `content`
  - [Request Body Object ↗︎](https://spec.openapis.org/oas/v3.0.3#request-body-object)
  - [Media Type Object ↗︎](https://spec.openapis.org/oas/v3.0.3#media-type-object)
    - Schema Validation can validate `application/json` and compatible `application/x-www-form-urlencoded` documents. If a schema allows other content types, Schema Validation accepts those requests without body validation.

#### `parameter/schema`

- `anyOf`
  - [Parameter Object ↗︎](https://spec.openapis.org/oas/v3.0.3#parameter-object)
  - [Schema Object ↗︎](https://spec.openapis.org/oas/v3.0.3#schema-object)
    - `anyOf` schemas are currently not supported in parameter schemas.

#### `schema`

- [`format` ↗︎](https://spec.openapis.org/oas/v3.0.3#schema-object)
  - Validated formats:
    - `date-time`
    - `time`
    - `date`
    - `email`
    - `hostname`
    - `ipv4`
    - `ipv6`
    - `uri`
    - `uri-reference`
    - `iri`
    - `iri-reference`
    - `int32`
    - `int64`
    - `float`
    - `double`
    - `password`
    - `uuid`
    - `byte`
    - `uint64`
- [`pattern` ↗︎](https://spec.openapis.org/oas/v3.0.3#schema-object)
  - Patterns follow the [syntax documented for version 1 of the Rust `regex` crate ↗︎](https://docs.rs/regex/1/regex/#syntax). Unsupported constructs include look-around and backreferences. Invalid or unsupported patterns cause the schema upload to fail.
- [`uniqueItems` ↗︎](https://spec.openapis.org/oas/v3.0.3#schema-object)
  - This field is currently not validated by Schema validation.

---

## Body inspection

API Shield validates incoming request bodies against matching body schemas. Schema Validation supports `application/json` and compatible `application/x-www-form-urlencoded` bodies.

Cloudflare allows the following media ranges in the OpenAPI request body content map:

- `*/*`
- `application/*`
- `application/json`
- `application/x-www-form-urlencoded`

Wildcard media ranges can permit other content types without validating their body structure. For example, `application/*` permits `application/xml`, but Schema Validation does not structurally validate the XML body. Keep media ranges as specific as possible and disable [MIME sniffing ↗︎](https://mimesniff.spec.whatwg.org/) at your origin.

### Form-urlencoded bodies

To validate a form body, define `application/x-www-form-urlencoded` explicitly. Its top-level schema must be an object. Properties can be primitives or flat arrays of primitives. Cloudflare does not apply a form body schema that contains nested objects, nested arrays, `byte` or `binary` formats, or nondefault encoding directives.

Form field names and values must decode to valid UTF-8. Repeat a key to supply array values. A scalar key can appear only once, while one occurrence is valid for an array. A form body can contain up to 8,192 key-value pairs. Additional pairs produce a body violation.

For validated JSON and form requests, `charset` is optional and is the only accepted media type parameter. If present, its value must be `utf-8`. A `charset` parameter in the uploaded schema does not require requests to include it.

---

## Troubleshooting

This section addresses common issues you may encounter when using schema validation.

### Resolve a `OneOf` constraint violation

A `OneOf` constraint error means a request violated its uploaded profile. Its body did not match exactly one [`oneOf` ↗︎](https://swagger.io/docs/specification/v3_0/data-models/oneof-anyof-allof-not/) option.

The request was invalid for one of two reasons:

- **Matches Zero**: The payload did not correctly match any of the available subschemas. This is common when a discriminator field is set, but the payload is missing other required fields for that type.
- **Matches Multiple**: The payload was ambiguous and matched more than one subschema. This happens with generic schemas (for example, if a payload includes both an `email` and a `phone` field, it might match both an `email` and a `phone` schema definition, violating the "exactly one" rule).

To fix this, compare the sampled request with its schema definition. The request may omit required fields or match conflicting types.

---

## Availability

Customers with API Security already have access to Schema Profiles through Schema Learning and Schema Validation. Cloudflare is opening a closed beta to invited Enterprise customers without API Security. Interested customers can contact their account team to express interest. Closed-beta access does not imply future plan availability or pricing.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/schema-validation/#page","headline":"Schema validation","description":"Supply Schema Profiles through uploaded OpenAPI schemas.","url":"https://developers.cloudflare.com/api-shield/security/schema-validation/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/schema-validation/og.png?v=79e7231a72607932","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Manage uploaded OpenAPI schemas with the Cloudflare API.
title: API configuration
image: https://developers.cloudflare.com/api-shield/security/schema-validation/api/og.png?v=66c08eadff5f7d12
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# API configuration

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/schema-validation/api/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Use the API to upload, activate, list, and delete OpenAPI schemas. An uploaded schema supplies a Schema Profile for its operations.

Note

[Classic Schema validation documentation](https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/) is available for reference only.

## Configure an uploaded schema

1. Upload a schema with `validation_enabled` set to `false`.
2. Add the schema operations as saved operations in the Web Assets inventory.
3. Activate the schema by setting `validation_enabled` to `true`.
4. Send representative traffic through the configured operations.
5. Analyze `cf.schema_validation.uploaded.violated` in [Profile Analysis](https://developers.cloudflare.com/waf/detections/application-profiles/analyze-profile-detections/).
6. Configure mitigation with [WAF Custom Rules](https://developers.cloudflare.com/waf/detections/application-profiles/enforce-profiles-with-custom-rules/).

Settings changes may take a few minutes to implement.

Note

Operations must exist as saved operations in Web Assets for Schema Validation matching.

## Configuration

### Upload a schema

Upload a schema with `POST`. Keep validation inactive while you configure operations.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>Account API Gateway</code>
- <code>Domain API Gateway</code>

</details>

*Upload a schemabash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas" \
	--request POST \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
	--json '{
		"kind": "openapi_v3",
		"name": "example_schema",
		"source": "<SOURCE>",
		"validation_enabled": false
	}'
```

```json
{
	"result": {
		"schema_id": "af632e95-c986-4738-a67d-2ac09995017a",
		"name": "example_schema",
		"kind": "openapi_v3",
		"source": "<SOURCE>",
		"validation_enabled": false,
		"created_at": "2023-04-03T15:10:08.902309Z"
	},
	"success": true,
	"errors": [],
	"messages": []
}
```

### Add schema operations

Schemas contain hosts, paths, and methods that define operations. An operation represents an endpoint by HTTP method, hostname pattern, and path pattern.

Schema Validation evaluates requests only for saved operations in Web Assets. Retrieve operations from the schema with `GET`.

*cURL commandbash*

```bash
curl --request GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas/$SCHEMA_ID/operations?operation_status=new&page=1&per_page=50" \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

```json
{
	"result": [
		{
			"method": "GET",
			"host": "example.com",
			"endpoint": "/pets"
		}
	],
	"success": true,
	"errors": [],
	"messages": [],
	"result_info": {
		"page": 1,
		"per_page": 50,
		"count": 1,
		"total_count": 1
	}
}
```

Use `operation_status=new` to return operations that are not saved. Use `feature=schema_info` to include Schema Validation configuration for existing operations.

Results are paginated. Request each page to retrieve all schema operations.

Add schema operations to Web Assets with `POST`.

*cURL commandbash*

```bash
curl --request POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/api_gateway/operations" \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
	--header "Content-Type: application/json" \
	--data '[
		{
			"method": "GET",
			"host": "example.com",
			"endpoint": "/pets"
		}
	]'
```

```json
{
	"result": [
		{
			"operation_id": "6c734fcd-455d-4040-9eaa-dbb3830526ae",
			"method": "GET",
			"host": "example.com",
			"endpoint": "/pets",
			"last_updated": "2023-04-04T16:07:37.575971Z"
		}
	],
	"success": true,
	"errors": [],
	"messages": []
}
```

The endpoint may limit the number of operations you can add in a single batch. If necessary, add operations in multiple requests.

### Activate the schema

After you save the operations, use `PATCH` to activate the schema.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>Account API Gateway</code>
- <code>Domain API Gateway</code>

</details>

*Set schema validation statebash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas/$SCHEMA_ID" \
	--request PATCH \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
	--json '{
		"validation_enabled": true
	}'
```

```json
{
	"result": {
		"schema_id": "af632e95-c986-4738-a67d-2ac09995017a",
		"name": "example_schema",
		"kind": "openapi_v3",
		"source": "",
		"validation_enabled": true,
		"created_at": "2023-04-03T15:10:08.902309Z"
	},
	"success": true,
	"errors": [],
	"messages": []
}
```

Activation makes uploaded profile evaluation available for configured operations.

### List all schemas

List uploaded schemas on a zone with `GET`. Results use the same `page` and `per_page` pagination parameters.

Use the optional `validation_enabled` query parameter to filter schemas by validation state.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>Account API Gateway</code>
- <code>Account API Gateway Read</code>
- <code>Domain API Gateway</code>
- <code>Domain API Gateway Read</code>

</details>

*List all uploaded schemasbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas" \
	--request GET \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

```json
{
	"result": [
		{
			"schema_id": "af632e95-c986-4738-a67d-2ac09995017a",
			"name": "example_schema",
			"kind": "openapi_v3",
			"source": "<SOURCE>",
			"validation_enabled": true,
			"created_at": "2023-04-03T15:10:08.902309Z"
		}
	],
	"success": true,
	"errors": [],
	"messages": [],
	"result_info": {
		"page": 1,
		"per_page": 20,
		"count": 1,
		"total_count": 1
	}
}
```

Note

Use `omit_source=true` to exclude each schema source from the response.

### Delete a schema

You can delete a schema using `DELETE`.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>Account API Gateway</code>
- <code>Domain API Gateway</code>

</details>

*Delete a schemabash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/schema_validation/schemas/$SCHEMA_ID" \
	--request DELETE \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

```json
{
	"result": null,
	"success": true,
	"errors": [],
	"messages": []
}
```

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/schema-validation/api/#page","headline":"API configuration","description":"Manage uploaded OpenAPI schemas with the Cloudflare API.","url":"https://developers.cloudflare.com/api-shield/security/schema-validation/api/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/schema-validation/api/og.png?v=66c08eadff5f7d12","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Track the order of API requests over time to discover user journeys and sequences.
title: Sequence Analytics
image: https://developers.cloudflare.com/api-shield/security/sequence-analytics/og.png?v=32323ccfad681d76
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Sequence Analytics

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/sequence-analytics/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Sequence Analytics tracks the order of API endpoint requests over time, allowing you to discover how users interact with your API. Sequence Analytics groups and highlights important user journeys (sequences) across your API. You can enforce preferred sequences using [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/).

## Process

### Sequence building

A sequence is a time-ordered list of HTTP API requests made by a specific visitor as they browse a website, use a mobile app, or interact with a B2B partner via API.

For example, a portion of a sequence made during a bank funds transfer could look like:

| Order | Method | Path | Description |
| --- | --- | --- | --- |
| 1 | `GET` | `/api/v1/users/{user_id}/accounts` | `user_id` is the active user. |
| 2 | `GET` | `/api/v1/accounts/{account_id}/balance` | `account_id` is one of the user’s accounts. |
| 3 | `GET` | `/api/v1/accounts/{account_id}/balance` | `account_id` is a different account belonging to the user. |
| 4 | `POST` | `/api/v1/transferFunds` | This contains a request body detailing an account to transfer funds from, an account to transfer funds to, and an amount of money to transfer. |

API Shield uses your configured session identifier and operations in the `full` or `candidate` state to build a set of ordered API operations (HTTP host, method, and path) requested per session. API Shield may surface sequences in various lengths depending on how it scores the sequences.

### Sequence scoring

API Shield scores sequences by a metric called precedence score. Sequence Analytics displays sequences by the highest precedence score. High-scoring sequences contain API requests which are likely to occur together in order.

Using the example above, a high score means that the last operation in the sequence `POST /api/v1/transferFunds` is highly likely to be preceded by the other operations in sequence `GET /api/v1/users/{user_id}/accounts` followed by `GET /api/v1/accounts/{account_id}/balance`. The scores are probabilities, which API Shield estimates using data from the last 24 hours.

### Secure your API

To proactively secure your API, you should inspect your highest-scoring sequences. For each high-scoring sequence, you should confirm with your development team if the final operation in the sequence must legitimately always be preceded by the other operations in the sequence.

Using the above example, if `POST /api/v1/transferFunds` must legitimately always be preceded by `GET /api/v1/users/{user_id}/accounts` and `GET /api/v1/accounts/{account_id}/balance`, you should create an **Allow** rule in sequence mitigation on the final operation of the sequence.

You should also consider applying other API Shield protections to these endpoints ([rate limiting suggestions](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), and [mTLS](https://developers.cloudflare.com/api-shield/security/mtls/)).

For more information, refer to the [blog post ↗︎](https://blog.cloudflare.com/api-sequence-analytics).

### Repeated sequences

To facilitate exploration, Sequence Analytics collapses successive requests to the same operation into one when no other operation occurs between them.

## Availability

Sequence Analytics is available for all API Shield customers. Pro, Business, and Enterprise customers who have not purchased API Shield can get started by [enabling the API Shield trial ↗︎](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or contacting your account manager.

## Limitations

Sequence Analytics currently requires a session identifier and operations that API Shield can match at the edge. Ensure that you have [set up your session identifier(s)](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers) and reviewed your operations in the `full` and `candidate` states in [Web Assets](https://developers.cloudflare.com/security/web-assets/manage-operations/#operation-states).

Sequences are currently limited to nine operations in length.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/sequence-analytics/#page","headline":"Sequence Analytics","description":"Track the order of API requests over time to discover user journeys and sequences.","url":"https://developers.cloudflare.com/api-shield/security/sequence-analytics/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/sequence-analytics/og.png?v=32323ccfad681d76","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Enforce expected API request patterns to detect and block malicious sequences.
title: Sequence mitigation
image: https://developers.cloudflare.com/api-shield/security/sequence-mitigation/og.png?v=7b13f42fd0529a94
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Sequence mitigation

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Sequence mitigation allows you to enforce request patterns for authenticated clients communicating with your API.

You can use sequence rules to establish a set of known behavior for API clients or detect and mitigate malicious behavior.

For example, you may expect that API requests made during a bank funds transfer could conform to the following order in time:

| Order | Method | Path | Description |
| --- | --- | --- | --- |
| 1 | `GET` | `/api/v1/users/{user_id}/accounts` | `user_id` is the active user. |
| 2 | `GET` | `/api/v1/accounts/{account_id}/balance` | `account_id` is one of the user’s accounts. |
| 3 | `GET` | `/api/v1/accounts/{account_id}/balance` | `account_id` is a different account belonging to the user. |
| 4 | `POST` | `/api/v1/transferFunds` | This contains a request body detailing an account to transfer funds from, an account to transfer funds to, and an amount of money to transfer. |

You may want to enforce that an API user requests `GET /api/v1/users/{user_id}/accounts` before `GET /api/v1/accounts/{account_id}/balance` and that you request `GET /api/v1/accounts/{account_id}/balance` before `POST /api/v1/transferFunds`.

Using sequence mitigation, you can enforce that request pattern with two new sequence mitigation rules.

Note

You can create sequence mitigation rules for a sequence even if the sequence is not listed in [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/).

## Process

You can [create a sequence rule](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/) to enforce behavior on your API over time using one of two approaches.

A positive security model blocks users who make API requests outside of your expected patterns. A negative security model blocks users who perform a known malicious sequence of API calls.

Sequence rules built via the Cloudflare dashboard using API Shield rules utilize a lookback window to match endpoints in the sequence. The rule will match as long as both endpoints are found within [10 requests](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/#request-limitations) (to endpoints within Endpoint Management) of each other and made within [10 minutes](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/#time-limitations) of each other.

Note

Contact Cloudflare Support if the default lookback window is not sufficient for you.

If you want to add multiple endpoints, ignore the lookback window, and configure time-based constraints, refer to [Sequence mitigation custom rules](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/).

In the bank funds transfer example, enforcing that a user requests `GET /api/v1/accounts/{account_id}/balance` before `POST /api/v1/transferFunds` is considered a positive security model, since a user may only perform a funds transfer after listing an account balance.

A negative security model may be useful if you see abusive behavior that is outside the norm of your application and you need to stop the requests while researching the correct positive security model to implement.

For example, if there was an authorization bug that allowed users to iterate through other users' profiles that contain account numbers via `GET /api/v1/users/{var1}/profile` and then a user tries to make fraudulent funds transfers, you could create a rule to block or log the sequence `GET /api/v1/users/{var1}/profile` to `POST /api/v1/transferFunds`.

## Limitations

### Endpoint Management

To track requests to API endpoints, they must be added to [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/). Add your endpoints to endpoint management via [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), or [manually](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#add-endpoints-manually) through the Cloudflare dashboard.

### Session Identifiers

API Shield uses your configured session identifier to track sessions. You must configure a session identifier that is unique per end user of your API in order for sequence mitigation to function as expected.

### Request limitations

By default, API Shield stores the current and previous nine requested endpoints by each individual API user identified through the session identifier. Contact Cloudflare Support if the default lookback window is not sufficient for you.

Sequence mitigation further de-duplicates requests to the same endpoint while building the sequence.

To illustrate, in the original [sequence example](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) listed above, sequence mitigation would store the following sequence:

1. `GET /api/v1/users/{user_id}/accounts`
2. `GET /api/v1/accounts/{account_id}/balance`
3. `POST /api/v1/transferFunds`

Sequence mitigation de-duplicated the two requests to `GET /api/v1/accounts/{account_id}/balance` and stored them as a single request.

### Time limitations

Sequence mitigation rules have a lookback period of 10 minutes. Any two requests using the same session identifier extend the sequence if they happen no further than 10 minutes apart. A request that happens more than 10 minutes after the previous one starts a new sequence.

For example, if you create a rule requiring one endpoint to be requested before another, and more than 10 minutes elapses between the two requests, the rule will not match.

## Availability

Sequence mitigation is currently in a closed beta and is only available for Enterprise customers. If you would like to be included in the beta, contact your account team.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/#page","headline":"Sequence mitigation","description":"Enforce expected API request patterns to detect and block malicious sequences.","url":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/og.png?v=7b13f42fd0529a94","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Build and configure sequence mitigation rules using the Cloudflare API.
title: Configure sequence mitigation via the API
image: https://developers.cloudflare.com/api-shield/security/sequence-mitigation/api/og.png?v=0ee1fd9dfb8f0f70
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configure sequence mitigation via the API

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/api/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

To configure sequence mitigation via the API, choose a sequence, rule kind, and action. The following example shows a rule returned by the API. In responses, `position` is a one-indexed integer:

*Example response rule objectjson*

```json
{
	"id": "d4909253-390f-4956-89fd-92a5b0cd86d8",
	"title": "<RULE_TITLE>",
	"kind": "allow",
	"action": "block",
	"sequence": [
		"0d9bf70c-92e1-4bb3-9411-34a3bcc59003",
		"b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"
	],
	"position": 1,
	"last_updated": "2023-07-24T12:06:51.796286Z",
	"created_at": "2023-07-24T12:06:51.796286Z"
}
```

This rule enforces that a request to endpoint `0d9bf70c-92e1-4bb3-9411-34a3bcc59003` must come before a request to endpoint `b704ab4d-5be0-46e0-9875-b2b3d1ab42f9`.

Otherwise, the request to endpoint `b704ab4d-5be0-46e0-9875-b2b3d1ab42f9` is blocked.

### Fields

| Field name | Description | Possible Values | Example |
| --- | --- | --- | --- |
| `id` | An opaque identifier that identifies a rule. | A UUID | `"d4909253-390f-4956-89fd-92a5b0cd86d8"` |
| `title` | A string that helps to identify the rule. | A value between 1 and 50 characters | `"Allow checkout sequence"` |
| `kind` | Defines the semantics of this rule. Block rules have a negative security model and allow to explicitly deny a sequence. Allow rules have a positive security model and deny everything but the configured sequence. | `block`, `allow` | `"block"` |
| `action` | What firewall action should we do when the rule matches. | `block`,`log` | `"log"` |
| `sequence` | Denotes the operations (from Endpoint Management) that make up the sequence for this rule. We currently only support sequences of length two. Both operations must use the same hostname. The first operation is the starting endpoint, and the second operation is the ending endpoint. | An array with two valid operation IDs from Endpoint Management | `["0d9bf70c-92e1-4bb3-9411-34a3bcc59003", "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"]` |
| `position` | Denotes the one-indexed position of this rule among all sequence rules. Rules are evaluated from top to bottom, so rules with lower position values are evaluated first. Responses return an integer. `POST` and `PATCH` requests set the position with `{"index": N}`. | A positive integer | `1` |
| `last_updated` | When this rule was last changed. | A date string | `2023-05-02T12:06:51.796286Z` |
| `created_at` | When this rule was created. | A date string | `2023-05-02T12:06:51.796286Z` |

You can find an endpoint's operation ID by exporting the schema in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/#export-a-schema) or via the [API](https://developers.cloudflare.com/api/resources/api_gateway/subresources/operations/methods/list/).

### List sequence rules

Use the `GET` command to list rules.

*cURL commandbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules"
```

### Add a single sequence rule

Use the `POST` command to create a single rule.

This adds a single rule to all existing rules. If you omit `position`, the API appends the rule. To insert it at a specific position, set the one-indexed request field to `{"index": N}`. Existing rules at and after that position move back.

The response will reflect the rule that has been written with its ID. In case something is not right with the rule, an appropriate error message with a `json` path pointing towards the issue will be provided.

*Example using cURLbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules/rules" \
--header "Content-Type: application/json" \
--data '{
  "title": "string",
  "kind": "block",
  "action": "block",
  "sequence": [
    "0d9bf70c-92e1-4bb3-9411-34a3bcc59003",
    "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"
  ],
  "position": {
    "index": 1
  }
}'
```

### Add multiple sequence rules

Use the `PUT` command to set up new rules in bulk.

This will overwrite any existing rules and replace them with the rules specified in the body. Setting an empty array for the rules removes all rules.

The order of objects in the `rules` array sets their order, starting at position `1`. Do not include `position` in individual bulk rule objects.

The response will reflect the rules that have been written with their IDs in case something is not right with the rules, an appropriate error message with a `json` path pointing towards the issue will be provided.

*Example using cURLbash*

```bash
curl --request PUT "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules" \
--header "Content-Type: application/json" \
--data '{
  "rules": [
    {
      "title": "<RULE_TITLE>",
      "kind": "block",
      "action": "block",
      "sequence": [
        "0d9bf70c-92e1-4bb3-9411-34a3bcc59003",
        "b704ab4d-5be0-46e0-9875-b2b3d1ab42f9"
      ]
    }
  ]
}'
```

### Delete a rule

Use the `DELETE` command with its rule ID to delete a rule.

*cURL commandbash*

```bash
curl --request DELETE "https://api.cloudflare.com/client/v4/zones/{zone_id}/api_gateway/seqrules/rules/d4909253-390f-4956-89fd-92a5b0cd86d8"
```

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/api/#page","headline":"Configure sequence mitigation via the API","description":"Build and configure sequence mitigation rules using the Cloudflare API.","url":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/api/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/api/og.png?v=0ee1fd9dfb8f0f70","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Write custom rules that match valid or invalid API request sequences.
title: Sequence mitigation custom rules
image: https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/og.png?v=f445226227fcd9a2
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Sequence mitigation custom rules

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

API Shield sequence custom rules use the configured API Shield session identifier to track the order of requests a user has made and the time between requests, and makes them available via [Cloudflare Rules](https://developers.cloudflare.com/rules). This allows you to write rules that match valid or invalid sequences.

These rules are similar to [cookie sequence rules](https://developers.cloudflare.com/bots/additional-configurations/sequence-rules/) but have a different set of prerequisites:

- They require [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers) to be set in API Shield.
- Because they require session identifiers, they can only be used on traffic that can be clearly attributed to individual users through session identifiers (authenticated traffic).
- The sequence has a 10-minute inactivity window. Each tracked request refreshes this window.
- You must set up at least one [API sequence rule](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/) to activate the sequence system.

Rules built using these custom rules are similar to the sequence rules that can be configured [via the API or the Cloudflare dashboard](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) as they make use of the same underlying technology. However, these custom rules allow for greater flexibility by using free-form logic on top of the recorded sequence and providing access to the full response options that rulesets offers.

## Availability

Note

Sequence mitigation is currently in a closed beta and is only available for Enterprise customers. If you would like to be included in the beta, contact your account team.

These sequence fields are available in:

- [Custom rules](https://developers.cloudflare.com/waf/custom-rules/) ( `http_request_firewall_custom` phase)
- [Rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/) ( `http_request_ratelimit`)
- [Bulk Redirects](https://developers.cloudflare.com/workers/examples/bulk-redirects/) ( `http_request_redirect`)
- [Request Header Transform Rules](https://developers.cloudflare.com/rules/transform/response-header-modification/) ( `http_request_late_transform`)

| Field name | Description | Example value |
| --- | --- | --- |
| `cf.sequence.current_op`<br>`String` | This field contains the ID of the operation that matches the current request. If the current request does not match any operations defined in Endpoint Management, it will be an empty string. | `c821cc00` |
| `cf.sequence.previous_ops`<br>`Array<String>` | This field contains an array of the prior operation IDs in the sequence, ordered from most to least recent. It does not include the current request. <br><br> If an operation is repeated, it will appear multiple times in the sequence. | `["f54dac32", "c821cc00", "a37dc89b"]` |
| `cf.sequence.msec_since_op`<br>`Map<Number>` | This field contains a map where the keys are operation IDs and the values are the number of milliseconds since that operation has most recently occurred. <br><br> This does not include the current request or operation as it only factors in previous operations in the sequence. | `{"f54dac32": 1000, "c821cc00": 2000}` |

## Build a sequence custom rule

1. In the Cloudflare dashboard, go to the **Security rules** page. [Go to **Security rules** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. To create a new empty rule, select **Create rule** > **Custom rules**.
3. Enter a descriptive name for the rule in **Rule name**.
4. Under **When incoming requests match**, use the **Field** drop-down list to filter by **Sequences** and select from:
   - Current Operation
   - Previous Operations
   - Elapsed time
5. Under **Value**, select the edit icon to use Builder and build a sequence on the side panel.
6. Under **Select a hostname for this sequence**, choose all or a specific hostname from the dropdown list. Optionally, you can use the search bar to search for a specific hostname.
7. From the **Methods** dropdown list, choose all methods or a specific request method.
8. Select the checkbox for each endpoint in the order that you want them to appear in the sequence.
9. Set the time to complete.
10. Select **Save**.
11. Under **Then take action**, select the rule action in the **Choose action** dropdown. For example, selecting *Block* tells Cloudflare to refuse requests that match the conditions you specified.
12. (Optional) If you selected the *Block* action, you can configure a custom response.
13. Under **Place at**, select the order of when the rule will fire.
14. To save and deploy your rule, select **Deploy**. If you are not ready to deploy your rule, select **Save as Draft**.

Note

The fields in the custom rule are populated as a grouped sequence based on the values that you entered on Builder.

### Example rules

Each saved endpoint will have an endpoint ID visible in its details page in Endpoint Management in the form of a UUID. The references below (`aaaaaaaa`, `bbbbbbbb`, and `cccccccc`) are the first eight characters of the endpoint ID.

The visitor must wait more than 2 seconds after requesting endpoint `aaaaaaaa` before requesting endpoint `bbbbbbbb`:

```txt
cf.sequence.current_op eq "bbbbbbbb" and
cf.sequence.msec_since_op["aaaaaaaa"] ge 2000
```

The visitor must request endpoints `aaaaaaaa`, then `bbbbbbbb`, then `cccccccc` in that exact order:

```txt
cf.sequence.current_op eq "cccccccc" and
cf.sequence.previous_ops[0] == "bbbbbbbb" and
cf.sequence.previous_ops[1] == "aaaaaaaa"
```

By default, sequence fields include the current operation and the previous nine operations. Contact Cloudflare Support if you need a different lookback window.

The visitor must request endpoint `aaaaaaaa` before endpoint `bbbbbbbb`, but endpoint `aaaaaaaa` can be anywhere in the previous nine operations:

```txt
cf.sequence.current_op eq "bbbbbbbb" and
any(cf.sequence.previous_ops[*] == "aaaaaaaa")
```

The visitor must request either endpoint `aaaaaaaa` before endpoint `bbbbbbbb`, or endpoint `cccccccc` before endpoint `bbbbbbbb`:

```txt
(cf.sequence.current_op eq "bbbbbbbb" and
any(cf.sequence.previous_ops[*] == "aaaaaaaa")) or
(cf.sequence.current_op eq "bbbbbbbb" and
any(cf.sequence.previous_ops[*] == "cccccccc"))
```

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/#page","headline":"Sequence mitigation custom rules","description":"Write custom rules that match valid or invalid API request sequences.","url":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/og.png?v=f445226227fcd9a2","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Create and manage sequence rules in the dashboard or via WAF custom rules.
title: Manage sequence rules
image: https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/og.png?v=980cb29ac82a9aa9
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Manage sequence rules

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Cloudflare recommends creating sequence rules using WAF custom rules. Refer to the [sequence custom rules documentation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/custom-rules/) for more information.

Note

Sequence mitigation is currently in a closed beta and is only available for Enterprise customers. If you would like to be included in the beta, contact your account team.

## Create a sequence rule

The starting and ending endpoints must use the same hostname.

1. In the Cloudflare dashboard, go to the **Security rules** page. [Go to **Security rules** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/security-rules)
2. Select **Create rule** and choose **API sequence rules**.
3. Name your rule.
4. Select a starting endpoint. This is the endpoint that you expect users to hit first in their request flow when using your API.
   - Choose a hostname to display the list of endpoints for that hostname.
   - Choose an endpoint.
   - Select **Set as starting endpoint**.
5. Select a final endpoint. This is the endpoint you are targeting for protection.
   - Choose the same hostname as the starting endpoint to display its endpoints.
   - Choose an endpoint.
   - Select **Set as ending endpoint**.
6. Choose an action that corresponds to the security model type:
   - **Allow**: This will create a positive security model by defining approved sequences on your API.
   - **Log** / **Block**: This will test or enforce a negative security model defining known bad sequences on your API.

   Note

   If you chose **Allow**, select whether to log or block the request to the final endpoint when users do not first request the starting endpoint in the sequence.
7. Select **Create rule**.

## Edit a sequence rule

You also have the option to edit an existing rule by selecting it on the rule list. You can rename your rule, adjust the starting and ending endpoint order, modify the endpoint, and change the action of the rule.

## Reprioritize a sequence rule

You can change the priority order of your rules by selecting and dragging the rules on the list.

You can also explicitly set a priority order by selecting the three dots on your rule and choosing **Move to…** where you can set the new priority in the resulting modal window.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/#page","headline":"Manage sequence rules","description":"Create and manage sequence rules in the dashboard or via WAF custom rules.","url":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/sequence-mitigation/manage-sequence-rules/og.png?v=980cb29ac82a9aa9","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Set up adaptive, per-session rate limiting for API endpoints with Volumetric Abuse Detection.
title: Volumetric Abuse Detection
image: https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/og.png?v=894010f6b76bafbd
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Volumetric Abuse Detection

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Cloudflare Volumetric Abuse Detection generates adaptive, per-session rate limit recommendations for individual operations as traffic patterns change.

Cloudflare looks for endpoint abuse based on user traffic to individual endpoints.

For example, your API might see different levels of traffic to a `/reset-password` endpoint than a `/login` endpoint. Additionally, your `/login` endpoint might see higher than average traffic after a successful marketing campaign.

These two scenarios speak to the limitations of traditional rate limiting. Not only does traffic vary between endpoints, but it also can vary over time for the same endpoint. Volumetric Abuse Detection solves these problems using unsupervised learning (analyzing traffic patterns without predefined rules) to develop separate baselines for each endpoint and adjust to changes in user behavior over time.

Volumetric Abuse Detection rate limits are generated on a per-session basis rather than per IP address. This reduces false positives when traffic to your API increases, because rate limits track individual sessions rather than shared IP addresses.

Volumetric Abuse Detection rate limits are a way to prevent blatant volumetric abuse while minimizing false positives. If you are trying to prevent abusive bot traffic altogether, refer to Cloudflare's [Bot solutions](https://developers.cloudflare.com/bots/).

## Process

Volumetric Abuse Detection groups requests into 10-minute periods for each session. It uses the distribution of these request volumes to recommend one per-session threshold for each eligible operation.

To access the operations list, go to **Security** > **Web Assets** > **Operations**.

Recommendations will continue to update if your traffic pattern changes.

### Requirements

Volumetric Abuse Detection requires sufficient eligible traffic during the seven-day analysis window to produce a reliable recommendation. If a recommendation is unavailable for an operation, it might not have enough eligible traffic.

A [session identifier](https://developers.cloudflare.com/api-shield/get-started/#to-set-up-session-identifiers), such as an authorization token available as a request header or cookie, must be configured so Cloudflare can perform per-session analysis.

After adding or changing a session identifier, allow at least 24 hours for recommendations to appear. Recommendations may take longer or remain unavailable if Cloudflare cannot collect enough eligible traffic or calculate a threshold.

### Rate limiting recommendation calculation

Select an operation row in the operations list to view its rate limit recommendation. The detail view shows the suggested threshold as the overall recommendation, percentile-based values (p50, p90, p99), and a confidence classification calculated by the dashboard.

Percentile values

Percentile values describe the distribution of request counts across observed per-session, 10-minute buckets. For example, a p90 value of `83` means that approximately 90% of these buckets contained 83 or fewer requests.

Cloudflare calculates each recommendation from requests in the previous seven days. The recommendation may not change if your traffic profile remains consistent.

Cloudflare recommends using the overall rate limit recommendation rather than a single percentile value. The overall recommendation accounts for variation across all your API sessions. Choosing a single percentile value may cause false positives due to a high number of outliers.

In the operations list, you can review the dashboard confidence classification for each recommendation.

Implementing low confidence rate limits can still be helpful to prevent API abuse. If the confidence level is low, start your rate limit rule in `log` mode and observe violations for false positives before switching to `block`.

### Create rate limits

Refer to the [Rules documentation](https://developers.cloudflare.com/waf/rate-limiting-rules/create-zone-dashboard/) for more information on how to create an Advanced Rate Limiting rule.

## API

[Rate limit recommendations are available via the API](https://developers.cloudflare.com/api/resources/api_gateway/subresources/operations/methods/get/) if you would like to dynamically update rate limits over time.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

- <code>Account API Gateway</code>
- <code>Account API Gateway Read</code>
- <code>Domain API Gateway</code>
- <code>Domain API Gateway Read</code>

</details>

*Get a web or API operationbash*

```bash
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/api_gateway/operations/$OPERATION_ID" \
	--request GET \
	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

## Special cases

### Rate limit by JWT claim

Rate Limiting can use string claims from a valid JSON Web Token (JWT) as rate-limit characteristics. This includes registered claims, such as `sub`, and custom claims.

For nested claims, pass each object key separately to [`lookup_json_string()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#lookup_json_string). For example, use `"user", "email"` to access `user.email`.

Only valid JWTs populate JWT claim fields. If a rule also matches requests without the selected claim, those requests use a separate missing-value counter. Refer to [Missing field versus empty value](https://developers.cloudflare.com/waf/rate-limiting-rules/parameters/#missing-field-versus-empty-value).

For per-user limits, select a claim that uniquely identifies the user, such as `sub` when it is unique within your application. Requests with the same characteristic value share a rate-limit counter.

### Rate limit by user tier

To apply different per-user limits by tier, create one rate limiting rule for each tier. Match the tier claim in the rule expression and use a separate user identifier claim as the rate-limit characteristic.

For example, a free-tier rule can use:

*Example rule expressiontxt*

```txt
lookup_json_string(http.request.jwt.claims["<JWT_TOKEN_CONFIGURATION_ID>"][0], "tier") eq "free"
```

Use `sub` as the rate-limit characteristic and set the limit to five requests per minute. Create another rule that matches `"tier" eq "premium"` and applies the appropriate premium-tier limit.

## Limitations

A configured session identifier alone does not guarantee a recommendation. Cloudflare must also have sufficient eligible traffic and successfully calculate a threshold. To enable session-based rate limits, [subscribe to Advanced Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/#availability).

## Availability

Volumetric Abuse Detection is only available for Enterprise customers. If you are an Enterprise customer interested in this product, contact your account team.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/#page","headline":"Volumetric Abuse Detection","description":"Set up adaptive, per-session rate limiting for API endpoints with Volumetric Abuse Detection.","url":"https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/og.png?v=894010f6b76bafbd","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Test API endpoints for BOLA and other vulnerabilities using the Cloudflare API.
title: Configure Vulnerability Scanner via the API
image: https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/og.png?v=76da4d5c278845e9
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Configure Vulnerability Scanner via the API

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Use Cloudflare Vulnerability Scanner to test your API endpoints for vulnerabilities such as Broken Object Level Authorization (BOLA). This guide explains how to run your first vulnerability scan using the Cloudflare API.

## Prerequisites

You must have:

- At least one zone in the account.
- An OpenAPI schema describing the API you want to scan.
- API credentials for your target. The scanner needs to authenticate as different users to test for BOLA vulnerabilities.

---

## Process

### Create an API token

All API requests use the base URL `https://api.cloudflare.com/client/v4/` and authenticate with a `Bearer` token in the `Authorization` header.

[Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) in the Cloudflare dashboard with the following [permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/) scoped to the target account: **Account** > **API Gateway** > **Edit**

Save your API token and Account Tag from your account's **Overview** page in the Cloudflare dashboard as environment variables to use in the following commands.

```bash
export CLOUDFLARE_API_TOKEN="<YOUR_API_TOKEN>"
export ACCOUNT_ID="<YOUR_ACCOUNT_ID>"
```

### Create a target environment

A target environment defines what the scanner should scan. Currently, the only supported target type is zone.

Find your Zone Tag on the zone's **Overview** page in the Cloudflare dashboard and export it.

```bash
export ZONE_TAG="<YOUR_ZONE_TAG>"
```

Use the following `POST` request to create the target environment.

*cURL commandbash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/target_environments" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Production API",
    "description": "Main production zone for API scanning",
    "target": {
      "type": "zone",
      "zone_tag": "'"${ZONE_TAG}"'"
    }
  }'
```

Save the target environment ID from the response into a variable `TARGET_ENV_ID`.

(Optional) You can verify your target environment by making a `GET` request to the following URL.

```txt
https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/target_environments/${TARGET_ENV_ID}
```

### Create credential sets

Currently, the scanner supports a BOLA scan. This requires two sets of credentials:

- Owner: A legitimate user who owns the resources being tested.
- Attacker: A different legitimate user who should not have access to the owner's resources.

The scanner authenticates as both users and checks whether the attacker can access the owner's resources. Each set of credentials is organized into a credential set containing one or more credentials.

Use the following `POST` requests to create an Owner credential set and an Attacker credential set.

*Owner credential setbash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{ "name": "Owner Credentials" }'

# Export the ID from the response
export OWNER_CRED_SET_ID="<OWNER_CRED_SET_ID>"
```

*Attacker credential setbash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{ "name": "Attacker Credentials" }'

# Export the ID from the response
export ATTACKER_CRED_SET_ID="<ATTACKER_CRED_SET_ID>"
```

### Add credentials to each credential set

A credential describes a single authentication token or session value that the scanner attaches to its requests.

Note

The value field is `write-only` and is never returned by the API.

Use the following `POST` requests to add the owner and attacker's credentials to each set.

*Owner's credential (Header)bash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/${OWNER_CRED_SET_ID}/credentials" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Owner Bearer Token",
    "location": "header",
    "location_name": "authorization",
    "value": "Bearer eyJhbGciOiJSUzI1NiIs...owner-token"
  }'
```

*Attacker's credential (Cookie)bash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/${ATTACKER_CRED_SET_ID}/credentials" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "Attacker Session Cookie",
    "location": "cookie",
    "location_name": "session_id",
    "value": "attacker-session-token-value"
  }'
```

(Optional) You can list all credentials in a set using a `GET` request to the following URL.

```txt
https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/credential_sets/<CRED_SET_ID>/credentials
```

### Start a scan

With your target environment and two credential sets ready, you can start a BOLA scan.

Ensure your OpenAPI schema is formatted as a string. For example, using `jq`.

```bash
OPEN_API_SCHEMA=$(jq -c . < openapi.json)
```

Use the following `POST` request to initiate the scan.

*cURL commandbash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  --header "Content-Type: application/json" \
  --data "$(jq -n \
    --arg te_id "$TARGET_ENV_ID" \
    --arg schema "$OPEN_API_SCHEMA" \
    --arg owner "$OWNER_CRED_SET_ID" \
    --arg attacker "$ATTACKER_CRED_SET_ID" \
    '{
      target_environment_id: $te_id,
      scan_type: "bola",
      open_api: $schema,
      credential_sets: { owner: $owner, attacker: $attacker }
    }')"
```

Save the scan ID from the response.

```bash
export SCAN_ID="<SCAN_ID>"
```

You can check the status of your scan using a `GET` request.

*cURL commandbash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"
```

### Retrieve the scan report

Once a scan has status `completed`, a report is available containing detailed findings for the vulnerabilities tested.

*cURL commandbash*

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}"
```

Note

When the scan has not yet completed, the API returns the result as `null`.

You may find it easier to summarize the report results with `jq`.

```bash
curl "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq '
    .result.report.report.tests[] |
    {
      test_verdict: .verdict,
      steps: [
        .steps
        | to_entries[]
        | {
            step: (.key + 1),
            method: .value.request.method,
            url: .value.request.url,
            role: .value.request.credential_set.role,
            response_status: .value.response.status,
            assertions: [
              .value.assertions[]
              | {
                  description: .description,
                  expected_status_min: .kind.parameters.min,
                  expected_status_max: .kind.parameters.max,
                  observed_status: .observed,
                  outcome: .outcome
                }
            ],
            errors: (.value.errors // [])
          }
      ]
    }
  '
```

Adding the `jq` command summarizes each response and its assertions. In step 3 of the following example, the scanner records the attacker's `DELETE` request as completed with a `204` response. The assertion expecting a `4xx` response fails, resulting in a `warning` verdict.

```json
{
	"test_verdict": "warning",
	"steps": [
		{
			"step": 1,
			"method": "POST",
			"url": "https://api.example.com/v1/orders",
			"role": "owner",
			"response_status": 201,
			"assertions": [
				{
					"description": "Owner must successfully create resource.",
					"expected_status_min": 200,
					"expected_status_max": 299,
					"observed_status": 201,
					"outcome": "ok"
				}
			],
			"errors": []
		},
		{
			"step": 2,
			"method": "GET",
			"url": "https://api.example.com/v1/orders",
			"role": "attacker",
			"response_status": 403,
			"assertions": [
				{
					"description": "Attacker should not be able to retrieve resource.",
					"expected_status_min": 400,
					"expected_status_max": 499,
					"observed_status": 403,
					"outcome": "ok"
				}
			],
			"errors": []
		},
		{
			"step": 3,
			"method": "DELETE",
			"url": "https://api.example.com/v1/orders/bdc64e8a-deec-4374-92c0-4fe91d1650bb",
			"role": "attacker",
			"response_status": 204,
			"assertions": [
				{
					"description": "Attacker should not be able to delete resource.",
					"expected_status_min": 400,
					"expected_status_max": 499,
					"observed_status": 204,
					"outcome": "fail"
				}
			],
			"errors": []
		}
	]
}
```

#### Example polling pattern

A common pattern is to poll the scan status until it completes, then fetch the report.

*Examplebash*

```bash
while true; do
  STATUS=$(curl --silent \
    "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}" \
    --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq -r '.result.status // empty')

  echo "Scan status: ${STATUS:-unknown}"

  case "$STATUS" in
    completed) echo "Scan finished. Fetching report..."; break ;;
    failed)    echo "Scan failed." >&2; exit 1 ;;
    *)         sleep 10 ;;
  esac
done

curl --silent \
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/vuln_scanner/scans/${SCAN_ID}/report" \
  --header "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" | jq .
```

---

## Limitations

During the open beta, you can split a large OpenAPI schema into smaller files organized by use case. For example, if your application supports account modification, social sharing, and personal favoriting, you can create a separate OpenAPI file for each use case.

---

## Availability

The vulnerability scanner is currently only available for Enterprise API Shield customers. Cloudflare will add more scan types in the future and increase the availability of the scanner at that time.

---

## Reference

### Credential locations

When creating credentials, the `location` field determines where the scanner attaches the credential during requests.

| Location | `location_name` | Example use case |
| --- | --- | --- |
| header | An HTTP header name | `Authorization` header with a `Bearer` token. |
| cookie | A cookie name | `session_id` cookie with a session token. |

A credential set can contain multiple credentials. For example, an API that requires both a `Bearer` token in the `Authorization` header and a `CSRF` token in the `X-CSRF-Token` header would have two separate credentials configured in its set.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/#page","headline":"Configure Vulnerability Scanner via the API","description":"Test API endpoints for BOLA and other vulnerabilities using the Cloudflare API.","url":"https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/og.png?v=76da4d5c278845e9","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Use Cloudflare as your API gateway for security, management, and routing.
title: API Gateway
image: https://developers.cloudflare.com/api-shield/api-gateway/og.png?v=86ed18ad42126e99
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# API Gateway

Last updated May 6, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/api-gateway/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Cloudflare API Shield provides API security, management tools, and integration with the Cloudflare Developer Platform for building new APIs.

- **Security**: Protect APIs with JWT validation, mutual TLS (mTLS) authentication, schema validation, and defenses against the [OWASP Top 10 API Security risks ↗︎](https://owasp.org/www-project-api-security/).
- **Management and monitoring**: Use endpoint management, analytics, and routing tools to streamline API operations. Monitor risks with Posture Management and gain visibility through Security Analytics.
- **Development**: Build and deploy APIs using the Cloudflare Developer Platform with its serverless infrastructure and developer tools.

## Cloudflare as your API Gateway

### API security features

- **Protection Against OWASP Top 10 API Security risks**: Mitigate common API vulnerabilities, including injection attacks and improper asset management.

### Management and Monitoring tools

- **[Endpoint management](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/)**: Gain visibility into your API endpoints, including discovery of shadow APIs and monitoring of active endpoints.
- **[Analytics and logging](https://developers.cloudflare.com/api-shield/security/sequence-analytics/)**: Access detailed analytics and logs to monitor API usage, performance, and security events.
- **[API Routing](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/)**: Optimize API performance and reliability with secure routing.
- **[Posture Management](https://developers.cloudflare.com/api-shield/security/authentication-posture/)**: Monitor API Authentication status and receive alerts for common API risks.

### Build APIs with Cloudflare’s Developer Platform

The [Cloudflare Developer Platform ↗︎](https://www.cloudflare.com/developer-platform/) offers a serverless execution environment, allowing you to build and deploy new APIs without the need to manage infrastructure. Its benefits include:

- **Global scalability**: Deploy APIs across Cloudflare's global network for low latency and high availability.
- **Integrated services**: Use storage, databases, and AI tools alongside your APIs.
- **Developer tools**: Build with frameworks and tools that support the API development workflow.

## Get started

To begin using Cloudflare API Shield, refer to our [Get started](https://developers.cloudflare.com/api-shield/get-started/) guide.

For detailed instructions and additional resources, refer to the [API Shield documentation](https://developers.cloudflare.com/api-shield/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/api-gateway/#page","headline":"API Gateway","description":"Use Cloudflare as your API gateway for security, management, and routing.","url":"https://developers.cloudflare.com/api-shield/api-gateway/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/api-gateway/og.png?v=86ed18ad42126e99","dateModified":"2026-05-06","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Definitions for terms used across API Shield documentation.
title: Glossary
image: https://developers.cloudflare.com/api-shield/glossary/og.png?v=c2b1d9918065d5bb
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Glossary

Last updated Apr 15, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/glossary/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Review the definitions for terms used across Cloudflare's API Shield documentation.

| Term | Definition |
| --- | --- |
| API call | Also known as an API request. An API call is a message sent to a server asking an API to provide a service or information. |
| API endpoint | The API endpoint is the location where API calls or requests are fulfilled. API Shield defines endpoints as a host, method, and path tuple. |
| API schema | The API schema defines which API requests are valid based on several request properties like target endpoint, path or query variable format, and HTTP method. |
| session identifier | A session identifier is a configured value that API Shield uses to associate requests with a session or client. |
| source endpoint | The source endpoint is the endpoint managed by API Shield in Endpoint Management by its routing feature. |
| target endpoint | The target endpoint is the ultimate destination that a request is sent to by API Shield's routing feature. |

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/glossary/#page","headline":"Glossary","description":"Definitions for terms used across API Shield documentation.","url":"https://developers.cloudflare.com/api-shield/glossary/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/glossary/og.png?v=c2b1d9918065d5bb","dateModified":"2026-04-15","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Track the latest updates and changes to API Shield features.
title: Changelog
image: https://developers.cloudflare.com/api-shield/changelog/og.png?v=2e89db0c051e0f95
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Changelog

Last updated Apr 15, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/changelog/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

[Subscribe to RSS](https://developers.cloudflare.com/changelog/rss/api-shield.xml)

## 2026-08-27

  
**Increased limits for JWT validation configurations**  

API Shield [JSON Web Token validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) now supports 32 token configurations per zone by default. Each token configuration can contain up to 16 keys.

These increased limits support more JWT configurations and provide additional capacity for key rotation.

Refer to [Configure JWT validation via the API](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/) for configuration details.

## 2026-08-25

  
**Symmetric key support for JWT validation**  

API Shield [JSON Web Token validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) now supports symmetric keys that use the `HS256`, `HS384`, and `HS512` algorithms. You can configure HMAC verification keys in the Cloudflare dashboard or with the Cloudflare API.

Cloudflare never stores symmetric credentials in plaintext. API responses do not include the credential.

Refer to [Configure JWT validation via the API](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#credentials) for supported key formats and credential requirements.

## 2026-03-23

  
**Web Assets fields now available in GraphQL Analytics API**  

Two new fields are now available in the `httpRequestsAdaptive` and `httpRequestsAdaptiveGroups` [GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api/) datasets:

- `webAssetsOperationId` — the ID of the [saved endpoint](https://developers.cloudflare.com/api-shield/management-and-monitoring/) that matched the incoming request.
- `webAssetsLabelsManaged` — the [managed labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#managed-labels) mapped to the matched operation at the time of the request (for example, `cf-llm`, `cf-log-in`). At most 10 labels are returned per request.

Both fields are empty when no operation matched. `webAssetsLabelsManaged` is also empty when no managed labels are assigned to the matched operation.

These fields allow you to determine, per request, which Web Assets operation was matched and which managed labels were active. This is useful for troubleshooting downstream security detection verdicts — for example, understanding why [AI Security for Apps](https://developers.cloudflare.com/waf/detections/ai-security-for-apps/) did or did not flag a request.

Refer to [Endpoint labeling service](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#analytics) for GraphQL query examples.

## 2026-03-09

  
**New Vulnerability Scanner for API Shield**  

Introducing Cloudflare's Web and API Vulnerability Scanner (Open Beta)

Cloudflare is launching the [Open Beta of the **Web and API Vulnerability Scanner** ↗︎](https://blog.cloudflare.com/vulnerability-scanner) for all [API Shield](https://developers.cloudflare.com/api-shield/) customers. This new, stateful Dynamic Application Security Testing (DAST) platform helps teams proactively find logic flaws in their APIs.

The initial release focuses on detecting Broken Object Level Authorization (BOLA) vulnerabilities by building API call graphs to simulate attacker and owner contexts, then testing these contexts by sending real HTTP requests to your APIs.

The scanner is now available via the Cloudflare API. To scan, set up your target environment, owner and attacker credentials, and upload your OpenAPI file with response schemas. The scanner will be available in the Cloudflare dashboard in a future release.

**Access**: This feature is only available to API Shield subscribers via the Cloudflare API. We hope you will use the API for programmatic integration into your CI/CD pipelines and security dashboards.

**Documentation**: Refer to the [developer documentation](https://developers.cloudflare.com/api-shield/security/vulnerability-scanner/) to start scanning your endpoints today.

## 2025-11-25

  
**New Zombie API detection for API Shield**  

API Shield now automatically detects zombie endpoints — saved endpoints that have not received traffic for an extended period. When detected, the `cf-risk-zombie` [risk label](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#risk-labels) is applied.

The scan runs daily alongside existing risk scans. Endpoints are labeled after 32 days without traffic.

Zombie endpoints may indicate deprecated or forgotten API surface area that could pose a security risk. Review these endpoints and consider removing them from Endpoint Management if they are no longer in use. Also consider using a [fallthrough rule](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-adding-a-fallthrough-rule) to prevent communication with endpoints removed from Endpoint Management.

## 2025-11-12

  
**New BOLA Vulnerability Detection for API Shield**  

Now, API Shield automatically searches for and highlights **Broken Object Level Authorization (BOLA) attacks** on managed API endpoints. API Shield will highlight both BOLA enumeration attacks and BOLA pollution attacks, telling you what was attacked, by who, and for how long.

You can find these attacks three different ways: Security Overview, Endpoint details, or Security Analytics. If these attacks are not found on your managed API endpoints, there will not be an overview card or security analytics suspicious activity card.

On the Security Overview card, select the suggestion > **View details** to review the top attacked API endpoints, endpoint details, and the attack summary: ![BOLA attack Overview card](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=1546,height=816,format=webp/_astro/bola-overview-card.hwcSeAkb.png) ![BOLA attack Overview drawer](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=1246,height=1078,format=webp/_astro/bola-overview-drawer.DD2c0bxS.png)

From the endpoint details, you can select **View attack** to find details about the BOLA attacker’s sessions.

![BOLA attack endpoint details](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=2050,height=630,format=webp/_astro/bola-endpoint-attack.UQP3MDkp.png)

From here, select **View in Analytics** to observe attacker traffic over time for the last seven days.

![BOLA attack analytics drawer](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=1156,height=1176,format=webp/_astro/bola-analytics-drawer.DXzC6EJU.png)

Your search will filter to traffic on that endpoint in the last seven days, along with the malicious session IDs found in the attack. Session IDs are hashed for privacy and will not be found in your origin logs. Refer to IP and JA4 fingerprint to cross-reference behavior at the origin.

At any time, you can also start your investigation into attack traffic from Security Analytics by selecting the suspicious activity card.

![Suspicious Activity card](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=1252,height=722,format=webp/_astro/bola-suspicious-card._B3GB3s4.png)

We urge you to take all of this client information to your developer team to research the attacker behavior and ensure any broken authorization policies in your API are fixed at the source in your application, preventing further abuse.

In addition, this release marks the end of the beta period for these scans. All Enterprise customers with API Shield subscriptions will see these new attacks if found on their zone.

## 2025-03-18

  
**New API Posture Management for API Shield**  

Now, API Shield **automatically** labels your API inventory with API-specific risks so that you can track and manage risks to your APIs.

View these risks in [Endpoint Management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) by label:

![A list of endpoint management labels](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=2172,height=936,format=webp/_astro/endpoint-management-label.BDmf8Ai1.png)

...or in [Security Center Insights](https://developers.cloudflare.com/security/security-insights/):

![An example security center insight](https://developers.cloudflare.com/cdn-cgi/image/onerror=redirect,width=2250,height=1316,format=webp/_astro/posture-management-insight.7vB7mzGI.png)

API Shield will scan for risks on your API inventory daily. Here are the new risks we're scanning for and automatically labelling:

- **cf-risk-sensitive**: applied if the customer is subscribed to the [sensitive data detection ruleset](https://developers.cloudflare.com/waf/managed-rules/reference/sensitive-data-detection/) and the WAF detects sensitive data returned on an endpoint in the last seven days.
- **cf-risk-missing-auth**: applied if the customer has configured a session ID and no successful requests to the endpoint contain the session ID.
- **cf-risk-mixed-auth**: applied if the customer has configured a session ID and some successful requests to the endpoint contain the session ID while some lack the session ID.
- **cf-risk-missing-schema**: added when a learned schema is available for an endpoint that has no active schema.
- **cf-risk-error-anomaly**: added when an endpoint experiences a recent increase in response errors over the last 24 hours.
- **cf-risk-latency-anomaly**: added when an endpoint experiences a recent increase in response latency over the last 24 hours.
- **cf-risk-size-anomaly**: added when an endpoint experiences a spike in response body size over the last 24 hours.

In addition, API Shield has two new 'beta' scans for **Broken Object Level Authorization (BOLA) attacks**. If you're in the beta, you will see the following two labels when API Shield suspects an endpoint is suffering from a BOLA vulnerability:

- **cf-risk-bola-enumeration**: added when an endpoint experiences successful responses with drastic differences in the number of unique elements requested by different user sessions.
- **cf-risk-bola-pollution**: added when an endpoint experiences successful responses where parameters are found in multiple places in the request.

We are currently accepting more customers into our beta. Contact your account team if you are interested in BOLA attack detection for your API.

Refer to the [blog post ↗︎](https://blog.cloudflare.com/cloudflare-security-posture-management/) for more information about Cloudflare's expanded posture management capabilities.

## 2025-02-17

**New automatically applied risk labels**

API Shield now automatically labels endpoints with risks due to missing schemas and performance anomalies (spikes in error rates, latency, and body response sizes).

## 2025-01-16

**API Authentication Posture**

Customers will see per-endpoint authentication details inside [Endpoints](https://developers.cloudflare.com/api-shield/management-and-monitoring/) for zones with configured session identifiers.

## 2024-12-19

**Automatically applied endpoint risk labels**

API Shield now automatically labels endpoints with risks due to authentication status and sensitive data detection.

## 2024-11-04

**Endpoint labels**

Customers can now organize their endpoints by use case and custom labels using the [Endpoint labeling service](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/) for easy reference and future machine learning (ML) model training.

## 2024-10-18

**API Shield fields in Custom Rules**

Customers can now use API Shield product feature fields in [custom rules](https://developers.cloudflare.com/waf/custom-rules/), referencing features such as [JWT validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/), [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers), and [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).

## 2024-09-25

**Fallthrough rule for Schema validation 2.0**

Customers can now enable the [Fallthrough Action](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-adding-a-fallthrough-rule) for Schema validation 2.0 to block or log requests that do not match the endpoints listed in schemas protected by Schema validation 2.0.

## 2024-08-28

**Increased capacity for Endpoint management and Schema validation**

Endpoint management and Schema validation now support up to 10,000 saved and validated API endpoints.

## 2024-07-08

**API Discovery's hostname variables**

Customers can now see when [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/) groups similar subdomains with the same methods and paths, making it easy to discover and manage APIs that share many vanity domains or subdomains.

## 2024-07-02

**Route API requests using API Routing**

Customers can now route requests to different back-end services through [API Routing](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/), creating a unified front for their APIs distributed across otherwise disparate systems.

## 2024-05-13

**Use JWT claims in Advanced Rate Limiting, Transform Rules, and as session IDs**

Customers can now use the fields inside [JSON Web Tokens (known as claims)](https://developers.cloudflare.com/api-shield/security/jwt-validation/transform-rules/#enhance-transform-rules-with-jwt-claims) as [session identifiers in API Shield](https://developers.cloudflare.com/api-shield/get-started/#session-identifiers), to count values in [Advanced Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/), and to send on useful information in [Transform Rules](https://developers.cloudflare.com/rules/transform/).

## 2024-04-30

**Build sequence mitigation rules via the Cloudflare dashboard**

Customers can now build [Sequence mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/) rules with a new user interface inside the API Shield section of the [Cloudflare dashboard ↗︎](https://dash.cloudflare.com/).

## 2024-02-23

**Endpoint management supports hostname variables**

Customers can now save endpoints in [Endpoint management](https://developers.cloudflare.com/api-shield/management-and-monitoring/) that contain variables in the hostname. Hostname variables are supported across all product features.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"BlogPosting","@id":"https://developers.cloudflare.com/api-shield/changelog/#page","headline":"Changelog","description":"Track the latest updates and changes to API Shield features.","url":"https://developers.cloudflare.com/api-shield/changelog/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/changelog/og.png?v=2e89db0c051e0f95","dateModified":"2026-04-15","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Route API requests to different back-end services using API Shield Routing.
title: API Routing
image: https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/og.png?v=2b93b8249ae8d0f5
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# API Routing

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

API Shield Routing allows you to expose a single external API that routes requests to different back-end services, even when those services use different paths or hostnames than your zone.

Note

The term **Source Endpoint** refers to the endpoint managed by API Shield in Endpoint Management. The term **Target Endpoint** refers to the ultimate destination the request is sent to by the Routing feature.

## Process

You must add Source Endpoints to Endpoint Management through established methods, including [uploading a schema](https://developers.cloudflare.com/api-shield/security/schema-validation/#add-validation-by-uploading-a-schema), via [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), or by [adding manually](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#add-endpoints-manually), before creating a route.

To create a route, you will need the operation ID of the Source Endpoint. To find the operation ID in the dashboard:

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. In the **Operations** tab, filter the operations to find your **Source Endpoint**.
3. Expand the row for your Source Endpoint and note the **operation ID** field.
4. Select the copy icon to copy the operation ID to your clipboard.

Once your Source Endpoints are added to Endpoint Management, use the following steps to create and verify routes on any given operation ID:

### Create a route

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. In the operations list, select an existing endpoint and expand its details.
3. Under **Routing**, select **Create route**.
4. Enter the target URL or IP address to route your endpoint to.
5. Select **Deploy route**.

Note

You can reorder path variables if they are present. For example, you can route `/api/{var1}/users/{var2}` to `/{var2}/users/{var1}`. Segments of the path that are not variables may be added or omitted entirely.

You can also edit or delete a route by selecting **Edit route** on an existing route.

### Verify a route

After sending a request to your Source Endpoint, you should see the contents of the back-end service as if you called the Target Endpoint directly.

If API Shield returns unexpected results, check your Source Endpoint host, method, and path and [verify the Route](https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/#verify-a-route) to ensure the Target Endpoint value is correct.

## Availability

API Shield Routing is currently in an open beta and is only available for Enterprise customers subscribed to API Shield. Enterprise customers who have not purchased API Shield can preview [API Shield as a non-contract service ↗︎](https://dash.cloudflare.com/?to=/:account/:zone/security/api-shield) in the Cloudflare dashboard or by contacting your account team.

## Limitations

The Target Endpoint cannot be routed to a Worker if the route is to the same zone.

You cannot change the method of a request. For example, a `GET` Source Endpoint will always send a `GET` request to the Target Endpoint.

You must use all of the variables in the Target Endpoint that appear in the Source Endpoint. For example, routing `/api/{var1}/users/{var2}` to `/api/users/{var2}` is not allowed and will result in an error since `{var1}` is present in the Source Endpoint but not in the Target Endpoint.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/#page","headline":"API Routing","description":"Route API requests to different back-end services using API Shield Routing.","url":"https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/management-and-monitoring/api-routing/og.png?v=2b93b8249ae8d0f5","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Create interactive API documentation portals from saved endpoints or schemas.
title: Build developer portals
image: https://developers.cloudflare.com/api-shield/management-and-monitoring/developer-portal/og.png?v=7ea2dd055dfcc6a3
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Build developer portals

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/management-and-monitoring/developer-portal/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Once your endpoints are saved, API Shield doubles as an API catalog. API Shield can build an interactive documentation portal with the knowledge it has of your APIs, or you can upload a new OpenAPI schema file to build a documentation portal ad-hoc.

To create a developer portal:

1. In the Cloudflare dashboard, go to the **Security Settings** page. [Go to **Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Create a developer portal**, select **Create site**.
4. Upload an OpenAPI v3.0 schema file or choose to select an existing schema from API Shield.

   Note

   If you do not have a schema to upload or to select from a pre-existing schema, export your Endpoint Management schema. For best results, include the learned parameters.

   Only API schemas uploaded to Schema validation 2.0 are available when selecting existing schemas.
5. Select **Download project files** to save a local copy of the files that will be uploaded to Cloudflare Pages. Downloading the project files can be helpful if you wish to modify the project in any way and then upload the new version manually to Pages.
6. Select **Create pages project** to continue to Cloudflare Pages. Pages creates the project and imports your API schema with the supporting static content. This step does not deploy the site.
7. In Pages, select **Deploy site** to deploy the portal.

### Custom domains

To create a vanity domain instead of using the pages.dev domain, refer to the [Pages custom domain documentation](https://developers.cloudflare.com/pages/configuration/custom-domains/).

## Availability

Building developer portals is available to all API Shield subscribers. This feature uses Cloudflare Pages to host the resulting portal. Refer to [Pages](https://developers.cloudflare.com/pages/) for any limitations of your current subscription plan.

## Limitations

This feature currently uses the open source [Redoc ↗︎](https://github.com/Redocly/redoc) project from [Redocly ↗︎](https://redocly.com/). For custom theme and branding options, visit the [Redoc GitHub repository ↗︎](https://github.com/Redocly/redoc).

To modify the resulting page, download the project files before creating the Pages project. You can create a new Pages project with the modified files you have made to meet your branding guidelines.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/management-and-monitoring/developer-portal/#page","headline":"Build developer portals","description":"Create interactive API documentation portals from saved endpoints or schemas.","url":"https://developers.cloudflare.com/api-shield/management-and-monitoring/developer-portal/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/management-and-monitoring/developer-portal/og.png?v=7ea2dd055dfcc6a3","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Organize API endpoints and address vulnerabilities with managed and custom labels.
title: Endpoint labeling service
image: https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/og.png?v=2a70dbad887ad007
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Endpoint labeling service

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

API Shield's labeling service helps you organize your endpoints and address vulnerabilities in your API. The labeling service includes managed and user-defined labels.

Managed labels help you organize endpoints by use case. Cloudflare automatically applies selected managed labels based on observed endpoint use cases and risks that may need attention.

You can also create user-defined labels and add them to individual or multiple endpoints. User-defined labels are useful for organizing your endpoints by owner, version, or type.

You can filter your endpoints based on the labels.

## Categories

### Managed labels

Use managed labels to identify endpoints by use case. Cloudflare automatically applies selected managed labels, and you can also apply managed labels manually.

`cf-api-endpoint`: Add this label to endpoints that serve machine-readable data or facilitate programmatic interaction.

`cf-log-in`: Add this label to endpoints that accept user credentials. You may have multiple endpoints if you accept username, password, and multi-factor authentication (MFA) across multiple endpoints or requests.

`cf-sign-up`: Add this label to endpoints that are the final step in creating user accounts for your site or application.

`cf-content`: Add this label to endpoints that provide unique content, such as product details, user reviews, pricing, or other unique information.

`cf-purchase`: Add this label to endpoints that are the final step in purchasing goods or services online.

`cf-password-reset`: Add this label to endpoints that participate in the user password reset process. This includes initial password reset requests and final password reset submissions.

`cf-add-cart`: Add this label to endpoints that add items to a user's shopping cart or verify item availability.

`cf-add-payment`: Add this label to endpoints that accept credit card or bank account details where fraudsters may iterate through account numbers to guess valid combinations of payment information.

`cf-check-value`: Add this label to endpoints that check the balance of rewards points, in-game currency, or other stored value products that can be earned, transferred, and redeemed for cash or physical goods.

`cf-add-post`: Add this label to endpoints that post messages in a communication forum, or product or merchant reviews.

`cf-account-update`: Add this label to endpoints that participate in user account or profile updates.

`cf-llm`: Services that are (partially) powered by Large Language Model (LLM).

`cf-mcp`: Add this label to endpoints that implement the [Model Context Protocol (MCP)](https://developers.cloudflare.com/agents/model-context-protocol/) for AI tool and data access.

`cf-rss-feed`: Add this label to endpoints that expect traffic from RSS clients.

`cf-web-page`: Add this label to endpoints that serve HTML pages.

`cf-contains-ads`: Add this label to endpoints that serve web pages containing advertisements.

Note

[Bot Fight Mode](https://developers.cloudflare.com/bots/get-started/bot-fight-mode/) will not block requests to endpoints labeled as `cf-rss-feed`.

[Super Bot Fight Mode rules](https://developers.cloudflare.com/bots/get-started/super-bot-fight-mode/#ruleset-engine) will not match or challenge requests labeled as `cf-rss-feed`.

### Risk labels

Cloudflare automatically scans your saved endpoints for risks approximately once a day. API Shield applies these labels when a scan finds security risks on your endpoints. A corresponding Security Center Insight is also raised when risks are found.

`cf-risk-missing-auth`: Automatically added when all successful requests lack a configured session identifier. Refer to [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/#process) for more information.

`cf-risk-mixed-auth`: Automatically added when some successful requests contain a configured session identifier and some successful requests lack one. Refer to [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/#process) for more information.

`cf-risk-sensitive`: Automatically added to endpoints when HTTP responses match the WAF's [Sensitive Data Detection](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#sensitive-data-detection) ruleset.

`cf-risk-errors-anomaly`: Automatically added when an endpoint experiences a recent increase in response errors over the last 24 hours.

`cf-risk-latency-anomaly`: Automatically added when an endpoint experiences a recent increase in response latency over the last 24 hours.

`cf-risk-size-anomaly`: Automatically added when an endpoint experiences a spike in response body size over the last 24 hours.

`cf-risk-bola-enumeration`: Automatically added when some sessions request unusually many distinct combinations of path parameter values for an endpoint compared with other sessions.

`cf-risk-bola-pollution`: Automatically added when Cloudflare detects an unusual pattern of requests that send different values for the same parameter in its schema-defined location and an unexpected request location. Only requests whose responses have status codes below `400` contribute.

`cf-risk-zombie`: Automatically added when a saved endpoint has not received traffic in 32 days.

Note

Cloudflare applies authentication labels based only on requests with successful response codes. Refer to the following table for more details.

#### Recommended action

How you address risks to your endpoints will depend on its label(s). The following steps provide you with general guidelines on how to take action on them.

1. Review risks to endpoints.

   View the endpoints labeled as risks and identify if they have been labeled for other risks.

   For example, endpoints labeled `cf-risk-sensitive` and `cf-risk-missing-auth` or `cf-risk-mixed-auth` may return sensitive data in successful responses that lack a configured session identifier. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)

   Go to the details pages for endpoints labeled as `cf-risk-missing-auth` or `cf-risk-mixed-auth`, and check for recent changes in configured session identifier presence in the last 24 hours and seven days.
2. Review traffic to these labeled endpoints in Security Analytics.

   Check for unexpected traffic sources and note any irregular traffic patterns.

   Filtering

   Filtering by risk label includes all traffic to all endpoints labeled with that risk, not only the traffic that prompted Cloudflare to apply the label. [Go to **Analytics** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/analytics)
3. Review your origin's authorization and authentication policies with your development team.

   Speak with your developers or application owners in your organization to understand whether or not all requests to these endpoints should be authenticated. Modify your application to consistently enforce the authentication requirement for all traffic accessing these endpoints.

   Refer to [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/) for more information.

---

## Analytics

### GraphQL Analytics API

You can query the matched operation and managed labels for individual requests using the [GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api/). The `webAssetsOperationId` and `webAssetsLabelsManaged` fields are available in the `httpRequestsAdaptive` and `httpRequestsAdaptiveGroups` datasets. Use [introspection](https://developers.cloudflare.com/analytics/graphql-api/features/discovery/introspection/) to explore the full schema and available filter operators.

`webAssetsLabelsManaged` returns at most 10 labels per request.

#### Example: query requests by managed label

The following query returns the count of requests per operation ID and managed label set, filtered to requests where the matched operation carries the `cf-log-in` managed label.

```graphql
query GetAdaptiveGroups($start: DateTime!, $end: DateTime!) {
	viewer {
		zones(filter: { zoneTag: $zoneTag }) {
			httpRequestsAdaptiveGroups(
				filter: {
					datetime_geq: $start
					datetime_leq: $end
					requestSource: "eyeball"
					webAssetsLabelsManaged_hasany: ["cf-log-in"]
				}
				limit: 25
				orderBy: [count_DESC]
			) {
				count
				dimensions {
					webAssetsOperationId
					webAssetsLabelsManaged
				}
			}
		}
	}
}
```

Replace `cf-log-in` with any [managed label](#managed-labels) or [risk label](#risk-labels). You can also omit the `webAssetsLabelsManaged_hasany` filter and use `webAssetsOperationId` as the sole dimension to group traffic by matched operation regardless of label.

### Logpush

You can export per-request Web Assets data to your storage or SIEM system of choice using [Logpush](https://developers.cloudflare.com/logs/logpush/). The `WebAssetsOperationID` and `WebAssetsLabelsManaged` fields are available in the [HTTP requests dataset](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http_requests/#webassetslabelsmanaged).

---

## Create a label

1. In the Cloudflare dashboard, go to the **Security Settings** page. [Go to **Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. Under **Endpoint labels**, select **Manage labels**.
4. Name the label and add an optional label description.
5. Apply the label to your selected endpoints.
6. Select **Create label**.

Alternatively, you can create a user-defined label via **Security** > **Web Assets**.

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Operations** tab.
3. Choose the endpoint that you want to label.
4. Select **Edit endpoint labels**.
5. Under **User**, select **Create user label**.
6. Enter the label name.
7. Select **Create**.

## Apply a label to an individual endpoint

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. In the **Operations** tab, choose the endpoint that you want to label.
3. Select **Edit endpoint labels**.
4. Add the label(s) that you want to use for the endpoint from the list of managed and user-defined labels.
5. Select **Save labels**.

## Bulk apply labels to multiple endpoints

1. In the Cloudflare dashboard, go to the **Security Settings** page. [Go to **Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Endpoint labels**, select **Manage labels**.
4. On the existing label that you want to apply to multiple endpoints, select **Bulk apply**.
5. Choose the endpoints that you want to label by selecting its checkbox.
6. Select **Apply label**.

## Availability

User-defined endpoint labels are available to all customers. Managed endpoint labels require an API Shield subscription.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/#page","headline":"Endpoint labeling service","description":"Organize API endpoints and address vulnerabilities with managed and custom labels.","url":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/og.png?v=2a70dbad887ad007","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["GraphQL"]}
```

---

---
description: Manage API operations through the Web Assets dashboard.
title: Endpoint Management
image: https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/og.png?v=c356a5f151d9e5fe
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Endpoint Management

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Available on all plans

Endpoint Management uses the [Web Assets](https://developers.cloudflare.com/security/web-assets/) dashboard. Go to **Web Assets** > **Operations** to manage API endpoints.

An operation is Cloudflare's term for an endpoint identified by HTTP method, hostname pattern, and path pattern. Web Assets continuously discovers operations, and you can add them manually.

Cloudflare discovered operations are only added to the inventory. To start profiling, select **Learn profile** for the intended operation.

Schema Profile availability

Customers with API Security already have access to Schema Profiles through Schema Learning and Schema Validation. Cloudflare is opening a closed beta to invited Enterprise customers without API Security. Interested customers can contact their account team to express interest. Closed beta access does not imply future plan availability or pricing.

Note

When an endpoint uses [Cloudflare Workers](https://developers.cloudflare.com/workers/), some metrics are not populated.

## Access

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Operations** tab.

### Review discovered operations

Web Assets continuously adds discovered operations to the inventory. Discovery does not start profile learning.

Candidate operations can provide context for matching, edge security detections, and [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/). You do not need to change every discovered operation.

### Add operations from Schema validation

1. From **Web Assets** > **Operations**, select **Add operation**.
2. Select **Upload schema**.
3. Upload a schema file.
4. Select **Add schema and endpoints**.

API Shield looks for duplicate operations with the same hostname, method, and path. Duplicate operations are not added.

### Add operations manually

1. From **Web Assets** > **Operations**, select **Add operation**.
2. Select **Manually add**.
3. Select the method and enter the hostname pattern and path pattern.
4. Select **Add operation**.

When adding an operation manually, you can specify variable fields in the path or hostname. Enclose variables in braces, such as `/api/user/{var1}/details` or `{hostVar1}.example.com`.

Cloudflare supports hostname variables in the following formats:

```txt
{hostVar1}.example.com

foo.{hostVar1}.example.com

{hostVar2}.{hostVar1}.example.com
```

Hostname variables must comprise the entire domain field and must not be used with other text in the field.

The following format is not supported:

```txt
foo-{hostVar1}.example.com
```

For more information on how Cloudflare uses variables in API Shield, refer to the examples from [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/).

### Edit operations

You can edit the identity of an operation.

1. From **Web Assets** > **Operations**, open the row actions for the operation.
2. Select **Edit operation**.
3. Update the HTTP method, hostname pattern, or path pattern.
4. Select **Save**.

Editing this operation will change its ID

Cloudflare computes operation IDs from the HTTP method, hostname, and path. Changing these values creates a different operation ID.

### Start profile learning

Start profiling only after reviewing the operation identity.

1. From **Web Assets** > **Operations**, open the operation overflow menu.
2. Select **Learn profile**.
3. After the profile becomes available, open the overflow menu again.
4. Select **View details** and review **Security overview**.

For learning requirements, analytics, and enforcement, refer to [Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/).

### Delete operations manually

You can delete endpoints one at a time or in bulk.

1. From **Web Assets** > **Operations**, select the operations that you want to delete.
2. Select **Delete operations**.

Caution

When you delete a full operation, Cloudflare stops tracking its associated performance and analytics data. Its previous historical metrics cannot be restored. If the operation returns to the `full` state, metric tracking restarts from that point.

## Operation analysis

For each operation in the `full` state, you can view:

- **Request count**: The total number of requests to the operation over time.
- **Rate limiting recommendation**: per 10 minutes. This is guided by the request count.
- **Latency**: The average origin response time in milliseconds (ms). This metric shows how long it takes from the moment a visitor makes a request to the moment the visitor gets a response back from the origin.
- **Error rate** vs. overall traffic: grouped by 4xx, 5xx, and their sum.
- **Response size**: The average size of the response (in bytes) returned to the request.
- **Labels**: The current [labels](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-labels/) assigned to the operation.
- **[Authentication status](https://developers.cloudflare.com/api-shield/security/authentication-posture/)**: The session identifiers observed on successful requests to this operation.
- **Sequences**: The number of [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/) sequences containing the operation.

Note

You can view detailed metrics from the last 24 hours or seven days.

## Using the Cloudflare API

You can manage saved operations through the Cloudflare API. For more information, refer to the [operations API documentation](https://developers.cloudflare.com/api/resources/api_gateway/subresources/operations/methods/list/).

## Sensitive Data Detection

Sensitive data comprises various personally identifiable information and financial data. Cloudflare created this ruleset to address common data loss threats, and the WAF can search for this data in HTTP response bodies from your origin.

API Shield alerts you to sensitive data in responses from full operations. Your zone must also have the [Sensitive Data Detection managed ruleset](https://developers.cloudflare.com/waf/managed-rules/reference/sensitive-data-detection/).

Sensitive Data Detection is available to Enterprise customers on our Advanced application security plan.

After you turn on Sensitive Data Detection, API Shield applies the `cf-risk-sensitive` label to operations whose responses matched the Sensitive Data Detection ruleset during the past week.

Open the operation details to review the detected sensitive data types. Select **Explore Events** to view matched events in Security Events.

After you turn on Sensitive Data Detection for your zone, you can [browse the Sensitive Data Detection ruleset ↗︎](https://dash.cloudflare.com/?to=/:account/:zone/security/data/ruleset/e22d83c647c64a3eae91b71b499d988e/rules). The link will not work if Sensitive Data Detection is not turned on.

## Limitations

Certain performance metrics, such as latency, are not supported when a request is handled by a Cloudflare service in a way that prevents it from being passed directly to your origin server.

This limitation is specifically observed when:

- A Cloudflare Worker is running on the URL path.
- Other products built on top of Workers, such as [Waiting Room](https://developers.cloudflare.com/waiting-room/), are active on the application.

In these scenarios, the system is unable to accurately measure the origin response time, and the metric will not be populated in the dashboard.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/#page","headline":"Endpoint Management","description":"Manage API operations through the Web Assets dashboard.","url":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/og.png?v=c356a5f151d9e5fe","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Learn Schema Profiles from qualifying operation traffic.
title: Schema learning
image: https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/og.png?v=3854a63bcbabd9ba
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Schema learning

Last updated Sep 29, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Note

Schema Learning is the learned source for a Schema Profile. For the shared detection and mitigation model, refer to [Application Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/).

Schema Learning observes qualifying traffic for selected operations. It learns expected request fields and constraints for a Schema Profile.

## Start profile learning

1. In the Cloudflare dashboard, go to **Web Assets** > **Operations**. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Open the operation overflow menu and select **Learn profile**.
3. After the profile becomes available, select **View details**.
4. Review the learned schema under **Security overview**.

Cloudflare runs an **always-on detection** after the learned profile becomes available. The detection does not mitigate requests by itself.

To investigate results, refer to [Analyze profile detections](https://developers.cloudflare.com/waf/detections/application-profiles/analyze-profile-detections/). To mitigate violations, refer to [Enforce profiles with Custom Rules](https://developers.cloudflare.com/waf/detections/application-profiles/enforce-profiles-with-custom-rules/).

## Meet learning requirements

Learning runs weekly using qualifying traffic from the previous seven days. Only requests that received a `2xx` response contribute.

The field-learning threshold requires 1,000 qualifying requests. The boundary-learning threshold requires 10,000 qualifying requests.

The first profile appears after the next weekly learning run. This can take up to seven days after meeting the relevant threshold.

For supported request components, constraints, and limitations, refer to [Schema Profiles](https://developers.cloudflare.com/waf/detections/application-profiles/schema-profiles/).

## Export a schema

Export availability depends on your plan. Each export creates a point-in-time OpenAPI file from the current learned profile. It does not change the profile or its detection.

1. In the Cloudflare dashboard, go to the **Web Assets** page. [Go to **Web assets** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/web-assets)
2. Go to the **Operations** tab.
3. Select **Export schema** and choose a hostname to export.
4. Select whether to include learned parameters and rate limit recommendations.
5. Select **Export schema** and choose a location to save the file.

Note

The schema is saved as a JSON file in OpenAPI `v3.0.0` format.

## Learned schema contents

Exported schemas include the listed hostname in the servers section. They also include operations by hostname, method, and path.

For operations that receive sufficient traffic, exported schemas also include:

- Detected path variables and formats
- Detected query parameters and formats
- Detected `POST`, `PUT`, and `PATCH` body variable names and formats for `application/json` content types

Exported schemas can optionally include API Shield rate limit recommendations.

For a fixed Schema Profile, upload the exported file through [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/#page","headline":"Schema learning","description":"Learn Schema Profiles from qualifying operation traffic.","url":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/management-and-monitoring/endpoint-management/schema-learning/og.png?v=3854a63bcbabd9ba","dateModified":"2026-09-29","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Configure session identifiers to track authenticated API traffic per user.
title: Session identifiers
image: https://developers.cloudflare.com/api-shield/management-and-monitoring/session-identifiers/og.png?v=cce4a254e2b80e7d
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Session identifiers

Last updated Apr 15, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/management-and-monitoring/session-identifiers/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

While not strictly required, it is recommended that you configure your session identifiers when getting started with API Shield. When Cloudflare inspects your API traffic for individual sessions, we can offer more tools for visibility, management, and control.

If you are unsure of the session identifiers that your API uses, consult with your development team.

Session identifiers should uniquely identify API clients. A common session identifier for API traffic is the `Authorization` header. When a [JSON Web Token (JWT)](https://developers.cloudflare.com/api-shield/security/jwt-validation/) is used by the API for client authentication, its value may change over time. You can use a claim value inside the JWT such as `sub` or `email` as a session identifier to uniquely identify the session over time.

If no session identifiers are configured and the `Authorization` header appears on more than 1% of eligible sampled client requests with `2xx` responses, Cloudflare automatically configures that header as the API Shield session identifier. Cloudflare does not overwrite an existing session identifier configuration.

Note

An API Shield subscription or eligible API Shield trial is required to configure session identifiers, including cookie-based identifiers. Configured identifiers can provide optional evidence for [API Discovery](https://developers.cloudflare.com/api-shield/security/api-discovery/), and are used by [Sequence Mitigation](https://developers.cloudflare.com/api-shield/security/sequence-mitigation/), [rate limiting recommendations](https://developers.cloudflare.com/api-shield/security/volumetric-abuse-detection/), [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/), and [Authentication Posture](https://developers.cloudflare.com/api-shield/security/authentication-posture/).

## To set up session identifiers

You can configure up to 10 session identifiers.

1. In the Cloudflare dashboard, go to the **Security Settings** page. [Go to **Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings)
2. Filter by **API abuse**.
3. On **Session identifiers**, select **Configure session identifiers**.
4. Select **Manage identifiers**.
5. Choose the type of session identifier (cookie, HTTP header, or JWT claim).

   Note

   The session identifier cookie must comply with RFC 6265. Otherwise, it will be rejected.

   If you are using a JWT claim, choose the [Token Configuration](https://developers.cloudflare.com/api-shield/security/jwt-validation/api/#token-configurations) that will verify the JWT, then specify the claim using a supported [RFC 9535 JSONPath ↗︎](https://www.rfc-editor.org/rfc/rfc9535.html) expression. Token Configurations are required to use JWT claims as session identifiers. Refer to [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) for more information.
6. Enter the name of the session identifier.
7. Select **Save**.

API Shield generates rate limiting recommendations for eligible saved operations. Recommendations require API Shield access, a configured session identifier that matches operation traffic, sufficient data, and completed processing. After these requirements are met, you can view per-operation and per-session recommendations and create rate limiting rules.

Discovery can use configured session identifiers as one signal when identifying API traffic. Session identifiers also support session traffic analysis in [Sequence Analytics](https://developers.cloudflare.com/api-shield/security/sequence-analytics/).

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/management-and-monitoring/session-identifiers/#page","headline":"Session identifiers","description":"Configure session identifiers to track authenticated API traffic per user.","url":"https://developers.cloudflare.com/api-shield/management-and-monitoring/session-identifiers/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/management-and-monitoring/session-identifiers/og.png?v=cce4a254e2b80e7d","dateModified":"2026-04-15","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Reference for the deprecated classic Schema validation feature in API Shield.
title: Classic Schema validation (deprecated)
image: https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/og.png?v=eafc4d0ec6990979
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Classic Schema validation (deprecated)

Last updated Sep 8, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Deprecation notice

Classic Schema validation has been deprecated.

Upload all new schemas to [Schema validation 2.0](https://developers.cloudflare.com/api-shield/security/schema-validation/).

Use the **API Shield** interface to configure [API Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/), which validates requests according to the API schema you provide.

Before you can configure Schema validation for an API, you must obtain an API Schema file matching our [specifications](https://developers.cloudflare.com/api-shield/security/schema-validation/#specifications).

If you are in the Schema validation 2.0, you can make changes to your settings but you cannot add any new Classic Schema validation schemas.

Note

This feature is only available for customers on an Enterprise plan. Contact your account team to get access.

## Create an API Shield with Schema validation

To configure Schema validation in the Cloudflare dashboard:

1. Log in to the [Cloudflare dashboard ↗︎](https://dash.cloudflare.com) and select your account and domain.
2. Select **Security** > **API Shield**.
3. Go to **Schema validation** and select **Add schema**.
4. Enter a descriptive name for your policy and optionally edit the expression to trigger Schema validation. For example, if your API is available at `http://api.example.com/v1`, include a check for the *Hostname* field — equal to `api.example.com` — and a check for the *URI Path* field using a regular expression — matching the regex `^/v1`.

Important

To validate the hostname, you must include the *Hostname* field explicitly in the rule, even if the hostname value is in the schema file. Any hostname value present in the schema file will be ignored.

5. Select **Next**.
6. Upload your schema file.
7. Select **Save** to validate the content of the schema file and deploy the Schema validation rule. If you get a validation error, ensure that you are using one of the [supported file formats](https://developers.cloudflare.com/api-shield/security/schema-validation/#specifications) and that each endpoint and method pair has a unique operation ID.

After deploying your API Shield rule, Cloudflare displays a summary of all API endpoints organized by their protection level and actions that will occur for non-compliant and unprotected requests.

1. In the **Endpoint action** dropdown, select an action for every request that targets a protected endpoint and fails Schema validation.
2. In the **Fallthrough action** dropdown, select an action for every request that targets an unprotected endpoint.
3. Optionally, you can save the endpoints to Endpoint Management at the same time the Schema is saved by selecting **Save new endpoints to [endpoint management](https://developers.cloudflare.com/api-shield/management-and-monitoring/)**. Endpoints will be saved regardless of whether the Schema is saved as a draft or published live.
4. Select **Done**.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/#page","headline":"Classic Schema validation (deprecated)","description":"Reference for the deprecated classic Schema validation feature in API Shield.","url":"https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/reference/classic-schema-validation/og.png?v=eafc4d0ec6990979","dateModified":"2026-09-08","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```

---

---
description: Configure API Shield operations and uploaded schemas.
title: Terraform
image: https://developers.cloudflare.com/api-shield/reference/terraform/og.png?v=098eee42e6f863b5
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/api-shield/llms.txt  
> Use this file to discover all available pages before exploring further.

# Terraform

Last updated Aug 19, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/api-shield/reference/terraform/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Get started with API Shield using Terraform from the examples below. For more information on how to use Terraform with Cloudflare, refer to the [Terraform documentation](https://developers.cloudflare.com/terraform/).

The following resources are available to configure through Terraform:

**Session identifiers**

- [`api_shield` ↗︎](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield) for configuring session identifiers in API Shield.

**Web Assets operations**

- [`api_shield_operation` ↗︎](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_operation) for configuring operations.

**Schema validation**

- [`cloudflare_schema_validation_schemas` ↗︎](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/schema_validation_schemas) for configuring a schema in [Schema validation](https://developers.cloudflare.com/api-shield/security/schema-validation/). ~~ [`api_shield_schema` ↗︎](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_shield_schema)~~ has been deprecated and will be removed in a future version of the terraform provider.

**JWT Validation**

- [`cloudflare_token_validation_config` ↗︎](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/token_validation_config) for setting up JWT validation with specific keying material and token locations.
- [`cloudflare_token_validation_rules` ↗︎](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/token_validation_rules) for setting up rules to action on the validation result.

## Manage API Shield session identifiers

Refer to the example configuration below to set up [session identifiers](https://developers.cloudflare.com/api-shield/get-started/#to-set-up-session-identifiers) on your zone.

*Example configurationtf*

```tf
resource "cloudflare_api_shield" "session_identifiers" {
  zone_id = var.zone_id
  auth_id_characteristics = [{
    name = "authorization"
    type = "header"
  }]
}
```

## Manage Web Assets operations

Manage operations by method, hostname, and path. Operations appear in the Web Assets inventory.

*Example configurationtf*

```tf
resource "cloudflare_api_shield_operation" "get_image" {
  zone_id  = var.zone_id
  method   = "GET"
  host     = "example.com"
  endpoint = "/api/images/{var1}"
}

resource "cloudflare_api_shield_operation" "post_image" {
  zone_id  = var.zone_id
  method   = "POST"
  host     = "example.com"
  endpoint = "/api/images/{var1}"
}
```

## Manage Schema validation

Note

Configure Web Assets operations before activating uploaded schema evaluation with Terraform.

The schema resource uploads an OpenAPI schema. Setting `validation_enabled` to `true` makes uploaded profile evaluation available.

*Example configurationtf*

```tf
# Upload an OpenAPI schema for Schema Validation
resource "cloudflare_schema_validation_schemas" "example_schema" {
  zone_id            = var.zone_id
  kind               = "openapi_v3"
  name               = "example-schema.yaml"
  # In this example, we assume that the `example-schema.yaml` includes `get_image` and `post_image` operations from above
  source             = file("./schemas/example-schema.yaml")
  validation_enabled = true
}
```

Activation does not configure mitigation. Use `cf.schema_validation.uploaded.violated` in [WAF Custom Rules](https://developers.cloudflare.com/waf/detections/application-profiles/enforce-profiles-with-custom-rules/).

## Validate JWTs

Refer to the example configuration below to perform [JWT Validation](https://developers.cloudflare.com/api-shield/security/jwt-validation/) on your zone.

*Example configurationtf*

```tf
# Setting up JWT validation with specific keying material and location of the token
resource "cloudflare_token_validation_config" "example_es256_config" {
  zone_id       = var.zone_id
  token_type    = "JWT"
  title         = "ES256 Example"
  description   = "An example configuration that validates ES256 JWTs with `b0078548-c9bc-46e5-a678-06fb72443427` key ID in the authorization header"
  token_sources = ["http.request.headers[\"authorization\"][0]"]
  credentials   = {
    keys = [
      {
        alg = "ES256"
        kid = "b0078548-c9bc-46e5-a678-06fb72443427"
        kty = "EC"
        crv = "P-256"
        x   = "yl_BZSxUG5II7kJCMxDfWImiU6zkcJcBYaTgzV3Jgnk"
        y   = "0qAzLQe_YGEdotb54qWq00k74QdiTOiWnuw_YzuIqr0"
      }
    ]
  }
}

# Setting up JWT rules for all configured endpoints on `example.com` except for `get_image`
resource "cloudflare_token_validation_rules" "example_com" {
 zone_id      = var.zone_id
 title        = "Validate JWTs on example.com"
 description  = "This actions JWT validation results for requests to example.com except for the get_image endpoint"
 action       = "block"
 enabled      = true
 # Require that the JWT described through the example_es256_config is valid.
 # Reference the ID of the generated token config, this constructs: is_jwt_valid("<id>")
 # If the expression is >not true<, Cloudflare will perform the configured action on the request
 expression   = format("(is_jwt_valid(%q))", cloudflare_token_validation_config.example_es256_config.id)
 selector     = {
    # all current and future operations matching this include selector will perform the described action when the expression fails to match
    include = [
      {
        host          = ["example.com"]
      }
    ]
    exclude = [
      {
        # reference the ID of the get_image operation to exclude it
        operation_ids = ["${cloudflare_api_shield_operation.get_image.id}"]
      }
    ]
 }
}

# With JWT validation, we can also refine session identifiers to use claims from the JWT
resource "cloudflare_api_shield" "session_identifiers" {
  zone_id = var.zone_id
  auth_id_characteristics = [{
    # select the JWT's `sub` claim as an extremely stable session identifier
    # this is "<token_config_id:json_path>" format
    name = "${cloudflare_token_validation_config.example_es256_config.id}:$.sub"
    type = "jwt"
  }]
}
```

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/api-shield/reference/terraform/#page","headline":"Terraform","description":"Configure API Shield operations and uploaded schemas.","url":"https://developers.cloudflare.com/api-shield/reference/terraform/","inLanguage":"en","image":"https://developers.cloudflare.com/api-shield/reference/terraform/og.png?v=098eee42e6f863b5","dateModified":"2026-08-19","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["Terraform"]}
```
