---
title: Cloudflare for Platforms
description: Build platforms on Cloudflare where your customers can deploy code with their own subdomains or custom domains.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare for Platforms

Build a platform where your customers can deploy code, each with their own subdomain or custom domain.

Cloudflare for Platforms is used by leading platforms big and small to:

* Build application development platforms tailored to specific domains, like ecommerce storefronts or mobile apps
* Power AI coding platforms that let anyone build and deploy software
* Customize product behavior by allowing any user to write a short code snippet
* Offer every customer their own isolated database
* Provide each customer with their own subdomain

---

## Deploy your own platform

Get a working platform running in minutes. Choose a template based on what you are building:

### Platform Starter Kit

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/worker-publisher-template)

An example of a platform where users can deploy code at scale. Each snippet becomes its own isolated Worker, served at `example.com/{app-name}`. Deploying this starter kit automatically configures Workers for Platforms with routing handled for you.

[ View demo ](https://worker-publisher-template.templates.workers.dev/) [ View on GitHub ](https://github.com/cloudflare/templates/tree/main/worker-publisher-template) 

### AI vibe coding platform

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/vibesdk)

Build an [AI vibe coding platform](https://developers.cloudflare.com/reference-architecture/diagrams/ai/ai-vibe-coding-platform/) where users describe what they want and AI generates and deploys working applications. Best for: AI-powered app builders, code generation tools, or internal platforms that empower teams to build applications & prototypes.

[VibeSDK ↗](https://github.com/cloudflare/vibesdk) handles AI code generation, code execution in secure sandboxes, live previews, and deployment at scale.

[ View demo ](https://build.cloudflare.dev/) [ View on GitHub ](https://github.com/cloudflare/vibesdk) 

---

## Features

* **Isolation and multitenancy** — Each of your customers runs code in their own Worker, a [secure and isolated sandbox](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/worker-isolation/).
* **Programmable routing, ingress, egress, and limits** — You write code that dispatches requests to your customers' code, and can control [ingress](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/), [egress](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/), and set [per-customer limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/).
* **Databases and storage** — You can provide [databases, object storage, and more](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) to your customers as APIs they can call directly, without API tokens, keys, or external dependencies.
* **Custom domains and subdomains** — You [call an API](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) to create custom subdomains or configure custom domains for each of your customers.

To learn how these components work together, refer to [How Workers for Platforms works](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}}]}
```

---

---
title: Workers for Platforms
description: Run untrusted code from your customers or AI in secure, isolated sandboxes on Cloudflare's global network.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Workers for Platforms

Build a multi-tenant platform that runs untrusted code in secure, isolated sandboxes.

Workers for Platforms lets you run untrusted code written by your customers, or by AI, in a secure hosted sandbox. Each customer runs code in their own Worker, a secure and isolated environment.

## When to use Workers for Platforms

Use Workers for Platforms when you need to:

* **Run untrusted code at scale** \- Execute code written by your customers or generated by AI in a secure sandbox, with the ability to deploy an unlimited number of applications.
* **Build multi-tenant platforms** \- Give each customer their own isolated compute environment with complete separation between tenants.
* **Extend Cloudflare's developer platform to your customers** \- Use [bindings](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) to give each customer access to KV stores, D1 databases, R2 storage, and more. Your customers get the same powerful tools, managed through your platform.
* **Give each application its own domain** \- Host applications under a subdomain of your domain (for example, `customer-name.myplatform.com`) or integrate with [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) to allow customers to use their own domains.

## Features

Workers for Platforms provides tools to manage and control your customers' code:

* **[Custom limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/)** \- Set per-customer limits on CPU time and subrequests.
* **[Observability](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/observability/)** \- Collect logs and metrics across all user Workers in your namespace. Export to third-party platforms like Datadog, Splunk, and Grafana.
* **[Tags](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/tags/)** \- Organize, search, and filter user Workers by custom tags like customer ID, plan type, or environment.

---

## Reference architectures

Explore reference architectures that use Workers for Platforms:

[Programmable PlatformsWorkers for Platforms provide secure, scalable, cost-effective infrastructure for programmable platforms with global reach.](https://developers.cloudflare.com/reference-architecture/diagrams/serverless/programmable-platforms/)[AI Vibe Coding PlatformCloudflare's low-latency, fully serverless compute platform, Workers offers powerful capabilities to enable A/B testing using a server-side implementation.](https://developers.cloudflare.com/reference-architecture/diagrams/ai/ai-vibe-coding-platform/)

---

## Get started

[Get started](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/get-started/) 

Set up a dispatch namespace, dynamic dispatch Worker, and user Worker.

[How Workers for Platforms works](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/) 

Understand the architecture: dispatch namespaces, dynamic dispatch Workers, user Workers, and outbound Workers.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}}]}
```

---

---
title: Bindings
description: Attach KV, R2, D1, and other resource bindings to user Workers deployed through Workers for Platforms.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ Bindings ](https://developers.cloudflare.com/search/?tags=Bindings) 

# Bindings

When you deploy User Workers through Workers for Platforms, you can attach [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) to give them access to resources like [KV namespaces](https://developers.cloudflare.com/kv/), [D1 databases](https://developers.cloudflare.com/d1/), [R2 buckets](https://developers.cloudflare.com/r2/), and more. This enables your end customers to build more powerful applications without you having to build the infrastructure components yourself.

With bindings, each of your users can have their own:

* [KV namespace](https://developers.cloudflare.com/kv/) that they can use to store and retrieve data
* [R2 bucket](https://developers.cloudflare.com/r2/) that they can use to store files and assets
* [Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/) dataset that they can use to collect observability data
* [Durable Objects](https://developers.cloudflare.com/durable-objects/) class that they can use for stateful coordination

#### Resource isolation

Each User Worker can only access the bindings that are explicitly attached to it. For complete isolation, you can create and attach a unique resource (like a D1 database or KV namespace) to every User Worker.

![Resource Isolation Model](https://developers.cloudflare.com/_astro/programmable-platforms-5.B2yd7IjV_Z1IMWex.svg "Resource Isolation Model")

Resource Isolation Model

## Adding a KV Namespace to a User Worker

This example walks through how to create a [KV namespace](https://developers.cloudflare.com/kv/) and attach it to a User Worker. The same process can be used to attach to other [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/).

### 1\. Create a KV namespace

Create a KV namespace using the [Cloudflare API](https://developers.cloudflare.com/api/resources/kv/subresources/namespaces/methods/bulk%5Fupdate/).

### 2\. Attach the KV namespace to the User Worker

Use the [Upload User Worker API](https://developers.cloudflare.com/api/resources/workers%5Ffor%5Fplatforms/subresources/dispatch/subresources/namespaces/subresources/scripts/methods/update/) to attach the KV namespace binding to the Worker. You can do this when you're first uploading the Worker script or when updating an existing Worker.

Note

When using the API to upload scripts, bindings must be specified in the `metadata` object of your multipart upload request. You cannot upload the Wrangler configuration file as a module to configure the bindings. For more details about multipart uploads, see [Multipart upload metadata](https://developers.cloudflare.com/workers/configuration/multipart-upload-metadata/).

##### Example API request

Terminal window

```

curl -X PUT \

  "https://api.cloudflare.com/client/v4/accounts/<account-id>/workers/dispatch/namespaces/<your-namespace>/scripts/<script-name>" \

  -H "Content-Type: multipart/form-data" \

  -H "Authorization: Bearer <api-token>" \

  -F 'metadata={

    "main_module": "worker.js",

    "bindings": [

      {

        "type": "kv_namespace",

        "name": "USER_KV",

        "namespace_id": "<your-namespace-id>"

      }

    ]

  }' \

  -F 'worker.js=@/path/to/worker.js'


```

Now, the User Worker has can access the `USER_KV` binding through the `env` argument using `env.USER_DATA.get()`, `env.USER_DATA.put()`, and other KV methods.

Note: If you plan to add new bindings to the Worker, use the `keep_bindings` parameter to ensure existing bindings are preserved while adding new ones.

Terminal window

```

curl -X PUT \

  "https://api.cloudflare.com/client/v4/accounts/<account-id>/workers/dispatch/namespaces/<your-namespace>/scripts/<script-name>" \

  -H "Content-Type: multipart/form-data" \

  -H "Authorization: Bearer <api-token>" \

  -F 'metadata={

    "bindings": [

      {

        "type": "r2_bucket",

        "name": "STORAGE",

        "bucket_name": "<your-bucket-name>"

      }

    ],

    "keep_bindings": ["kv_namespace"]

  }'


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/","name":"Bindings"}}]}
```

---

---
title: Custom limits
description: Set per-customer CPU time and subrequest limits on user Workers in Workers for Platforms.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom limits

Custom limits allow you to programmatically enforce limits on your customers' Workers' resource usage. You can set limits for the maximum CPU time and number of subrequests per invocation. If a user Worker hits either of these limits, the user Worker will immediately throw an exception.

## Set Custom limits

Custom limits can be set in the dynamic dispatch Worker:

JavaScript

```

export default {

  async fetch(request, env) {

    try {

      // parse the URL, read the subdomain

      let workerName = new URL(request.url).host.split(".")[0];

      let userWorker = env.dispatcher.get(

        workerName,

        {},

        {

          // set limits

          limits: { cpuMs: 10, subRequests: 5 },

        },

      );

      return await userWorker.fetch(request);

    } catch (e) {

      if (e.message.startsWith("Worker not found")) {

        // we tried to get a worker that doesn't exist in our dispatch namespace

        return new Response("", { status: 404 });

      }

      return new Response(e.message, { status: 500 });

    }

  },

};


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/","name":"Custom limits"}}]}
```

---

---
title: Dynamic dispatch Worker
description: Create a dynamic dispatch Worker to route incoming requests to user Workers in your dispatch namespace.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Dynamic dispatch Worker

A [dynamic dispatch Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/#dynamic-dispatch-worker) is a specialized routing Worker that directs incoming requests to the appropriate user Workers in your dispatch namespace. Instead of using [Workers Routes](https://developers.cloudflare.com/workers/configuration/routing/routes/), dispatch Workers let you programmatically control request routing through code.

![Figure 1: Workers for Platforms: Main Flow](https://developers.cloudflare.com/_astro/programmable-platforms-1.BCCEhzLr_2d88FE.svg) 

Note

You can also create a dispatch Worker from the Cloudflare dashboard. Go to **Workers for Platforms**, select your namespace, and click **Create** \> **Dispatch Worker**. The dashboard provides templates for path-based and subdomain-based routing.

#### Why use a dynamic dispatch Worker?

* **Scale**: Route requests to millions of hostnames to different Workers, without defining [Workers Routes](https://developers.cloudflare.com/workers/configuration/routing/routes/) configuration for each one
* **Custom routing logic**: Write code to determine exactly how requests should be routed. For example:  
   * Store hostname-to-Worker mappings in [Workers KV](https://developers.cloudflare.com/kv/) and look them up dynamically  
   * Route requests based on subdomain, path, headers, or other request properties  
   * Use [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) attached to [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) for routing decisions
* **Add platform functionality**: Build additional features at the routing layer:  
   * Run authentication checks before requests reach user Workers  
   * Remove or add headers or metadata from incoming requests  
   * Attach useful context like user IDs or account information  
   * Transform requests or responses as needed

### Configure the dispatch namespace binding

To allow your dynamic dispatch Worker to dynamically route requests to Workers in a namespace, you need to configure a dispatch namespace [binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/). This binding enables your dynamic dispatch Worker to call any user Worker within that namespace using `env.dispatcher.get()`.

* [  wrangler.jsonc ](#tab-panel-4547)
* [  wrangler.toml ](#tab-panel-4548)

JSONC

```

{

  "dispatch_namespaces": [

    {

      "binding": "DISPATCHER",

      "namespace": "my-dispatch-namespace"

    }

  ]

}


```

TOML

```

[[dispatch_namespaces]]

binding = "DISPATCHER"

namespace = "my-dispatch-namespace"


```

Once the binding is configured, your dynamic dispatch Worker can route requests to any Worker in the namespace. Below are common routing patterns you can implement in your dispatcher.

### Routing examples

![Figure 2: Workers for Platforms: Main Flow](https://developers.cloudflare.com/_astro/programmable-platforms-2.DGAT6ZDR_Z19nioR.svg) 

#### KV-Based Routing

Store the routing mappings in [Workers KV](https://developers.cloudflare.com/kv/). This allows you to modify your routing logic without requiring you to change or redeploy the dynamic dispatch Worker.

JavaScript

```

export default {

  async fetch(request, env) {

    try {

      const url = new URL(request.url);


      // Use hostname, path, or any combination as the routing key

      const routingKey = url.hostname;


      // Lookup user Worker name from KV store

      const userWorkerName = await env.USER_ROUTING.get(routingKey);


      if (!userWorkerName) {

        return new Response("Route not configured", { status: 404 });

      }


      // Optional: Cache the KV lookup result

      const userWorker = env.DISPATCHER.get(userWorkerName);

      return await userWorker.fetch(request);

    } catch (e) {

      if (e.message.startsWith("Worker not found")) {

        return new Response("", { status: 404 });

      }

      return new Response(e.message, { status: 500 });

    }

  },

};


```

#### Subdomain-Based Routing

Route subdomains to the corresponding Worker. For example, `my-customer.example.com` will route to the Worker named `my-customer` in the dispatch namespace.

JavaScript

```

export default {

  async fetch(request, env) {

    try {

      // Extract user Worker name from subdomain

      // Example: customer1.example.com -> customer1

      const url = new URL(request.url);

      const userWorkerName = url.hostname.split(".")[0];


      // Get user Worker from dispatch namespace

      const userWorker = env.DISPATCHER.get(userWorkerName);

      return await userWorker.fetch(request);

    } catch (e) {

      if (e.message.startsWith("Worker not found")) {

        // User Worker doesn't exist in dispatch namespace

        return new Response("", { status: 404 });

      }

      // Could be any other exception from fetch() or from the dispatched Worker

      return new Response(e.message, { status: 500 });

    }

  },

};


```

#### Path-Based routing

Route URL paths to the corresponding Worker. For example, `example.com/customer-1` will route to the Worker named `customer-1` in the dispatch namespace.

JavaScript

```

export default {

  async fetch(request, env) {

    try {

      const url = new URL(request.url);

      const pathParts = url.pathname.split("/").filter(Boolean);


      if (pathParts.length === 0) {

        return new Response("Invalid path", { status: 400 });

      }


      // example.com/customer-1 -> routes to 'customer-1' worker

      const userWorkerName = pathParts[0];


      const userWorker = env.DISPATCHER.get(userWorkerName);

      return await userWorker.fetch(request);

    } catch (e) {

      if (e.message.startsWith("Worker not found")) {

        return new Response("", { status: 404 });

      }

      return new Response(e.message, { status: 500 });

    }

  },

};


```

### Enforce custom limits

Use [custom limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/) to control how much CPU time a given user Worker can use, or how many subrequests it can make. You can set different limits based on customer plan type or other criteria.

JavaScript

```

export default {

  async fetch(request, env) {

    try {

      const url = new URL(request.url);

      const userWorkerName = url.hostname.split(".")[0];


      // Look up customer plan from your database or KV

      const customerPlan = await env.CUSTOMERS.get(userWorkerName);


      // Set limits based on plan type

      const plans = {

        enterprise: { cpuMs: 50, subRequests: 50 },

        pro: { cpuMs: 20, subRequests: 20 },

        free: { cpuMs: 10, subRequests: 5 },

      };

      const limits = plans[customerPlan] || plans.free;


      const userWorker = env.DISPATCHER.get(userWorkerName, {}, { limits });

      return await userWorker.fetch(request);

    } catch (e) {

      if (e.message.startsWith("Worker not found")) {

        return new Response("", { status: 404 });

      }

      if (e.message.includes("CPU time limit")) {

        // Track limit violations with Analytics Engine

        env.ANALYTICS.writeDataPoint({

          indexes: [userWorkerName],

          blobs: ["cpu_limit_exceeded"],

        });

        return new Response("CPU limit exceeded", { status: 429 });

      }

      return new Response(e.message, { status: 500 });

    }

  },

};


```

For more details on available limits, refer to [Custom limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/).

To track limit violations and other metrics across user Workers, use [Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/). For detailed logging and debugging, configure a [Tail Worker](https://developers.cloudflare.com/workers/observability/logs/tail-workers/) to capture events from your dispatch Worker.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/","name":"Dynamic dispatch Worker"}}]}
```

---

---
title: Hostname routing
description: Learn how to route requests to the dispatch worker.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Hostname routing

You can use [dynamic dispatch](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/) Workers to route millions of vanity domains or subdomains to Workers without hitting traditional [route limits](https://developers.cloudflare.com/workers/platform/limits/#routes-and-domains). These hostnames can be subdomains under your managed domain (e.g. `customer1.saas.com`) or vanity domains controlled by your end customers (e.g. `mystore.com`), which can be managed through [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/).

## (Recommended) Wildcard route with a dispatch Worker

Configure a wildcard [Route](https://developers.cloudflare.com/workers/configuration/routing/routes/) (`*/*`) on your SaaS domain (the domain where you configure custom hostnames) to point to your dynamic dispatch Worker. This allows you to:

* **Support both subdomains and vanity domains**: Handle `customer1.myplatform.com` (subdomain) and `shop.customer.com` (custom hostname) with the same routing logic.
* **Avoid route limits**: Instead of creating individual routes for every domain, which can cause you to hit [Routes limits](https://developers.cloudflare.com/workers/platform/limits/#routes-and-domains), you can handle the routing logic in code and proxy millions of domains to individual Workers.
* **Programmatically control routing logic**: Write custom code to route requests based on hostname, [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/), path, or any other properties.

Note

This will route all traffic inbound to the domain to the dispatch Worker.

If you'd like to exclude certain hostnames from routing to the dispatch Worker, you can either:

* Add routes without a Worker specification to opt certain hostnames or paths from being executed by the dispatcher Worker (for example, for `saas.com`, `api.saas.com`, etc)
* Use a [dedicated domain](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) (for example, `customers.saas.com`) for custom hostname and dispatch worker management to keep the rest of the traffic for that domain separate.

### Setup

To set up hostname routing with a wildcard route:

1. **Configure custom hostnames**: Set up your domain and custom hostnames using [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/)
2. **Set the fallback origin**: Set up a [fallback origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin), this is where all custom hostnames will be routed to. If you’d like to route them to separate origins, you can use a [custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/). Requests will route through the Worker before reaching the origin. If the Worker is the origin then place a dummy DNS record for the fallback origin (e.g., `A 192.0.2.0`).
3. **Configure DNS**: Point DNS records (subdomains or custom hostname) via [CNAME record to the saas domain](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record). If your customers need to proxy their apex hostname (e.g. `example.com`) and cannot use CNAME records, check out [Apex Proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/).
4. **Create wildcard route**: Add a `*/*` route on your platform domain (e.g. saas.com) and associate it with your dispatch Worker.
5. **Implement dispatch logic**: Add logic to your dispatch Worker to route based on hostname, lookup mappings stored in [Workers KV](https://developers.cloudflare.com/kv/), or use [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) attached to custom hostnames.

Note

If you plan to route requests based on custom metadata, you'll need to create subdomains (e.g. `customer1.saas.com`) as custom hostnames. This is because DNS records do not support custom metadata.

#### Example dispatch Worker

JavaScript

```

export default {

  async fetch(request, env) {

    const hostname = new URL(request.url).hostname;


    // Get custom hostname metadata for routing decisions

    const hostnameData = await env.KV.get(`hostname:${hostname}`, {

      type: "json",

    });


    if (!hostnameData?.workerName) {

      return new Response("Hostname not configured", { status: 404 });

    }


    // Route to the appropriate user Worker

    const userWorker = env.DISPATCHER.get(hostnameData.workerName);

    return await userWorker.fetch(request);

  },

};


```

## Subdomain routing

If you're only looking to route subdomain records (e.g. `customer1.saas.com`), you can use a more specific route (`*.saas.com/*`) to route requests to your dispatch Worker.

### Setup

To set up subdomain routing:

1. Create an orange-clouded wildcard DNS record: `*.saas.com` that points to the origin. If the Worker is the origin then you can use a dummy DNS value (for example, `A 192.0.2.0`).
2. Set wildcard route: `*.saas.com/*` pointing to your dispatch Worker
3. Add logic to the dispatch Worker to route subdomain requests to the right Worker.

#### Example subdomain dispatch Worker

JavaScript

```

export default {

  async fetch(request, env) {

    const url = new URL(request.url);

    const subdomain = url.hostname.split(".")[0];


    // Route based on subdomain

    if (subdomain && subdomain !== "saas") {

      const userWorker = env.DISPATCHER.get(subdomain);

      return await userWorker.fetch(request);

    }


    return new Response("Invalid subdomain", { status: 400 });

  },

};


```

### O2O Behavior

When your customers are also using Cloudflare and point their custom domain to your SaaS domain via CNAME (for example, `mystore.com` → `saas.com`), Worker routing behavior depends on whether the customer's DNS record is proxied (orange cloud) or DNS-only (grey cloud). Learn more about [O2O setups](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/#with-o2o)

This can cause inconsistent behavior when using specific hostname routes:

* If you're routing based on the CNAME target (`saas.com`), the custom hostname's DNS record must be orange-clouded for the Worker to be invoked.
* If you're routing based on the custom hostname (`mystore.com`), the customer's record must be grey-clouded for the Worker to be invoked.

Since you may not have control over your customer's DNS proxy settings, we recommend using `*/*` wildcard route to ensure routing logic always works as expected, regardless of how DNS is configured.

#### Worker invocation across route configurations and proxy modes

The table below shows when Workers are invoked based on your route pattern and the customer's DNS proxy settings:

| Route Pattern         | Custom Hostname (Orange Cloud) | Custom Hostname (Grey Cloud) |
| --------------------- | ------------------------------ | ---------------------------- |
| \*/\* (Recommended)   | ✅                              | ✅                            |
| Target hostname route | ✅                              | ❌                            |
| Custom hostname route | ❌                              | ✅                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/hostname-routing/","name":"Hostname routing"}}]}
```

---

---
title: Observability
description: Collect logs, traces, and analytics across all user Workers in a Workers for Platforms dispatch namespace.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Observability

Workers for Platforms provides you with logs and analytics that can be used to share data with end users.

## Logs

Learn how to access logs with Workers for Platforms.

### Workers Trace Events Logpush

Workers Trace Events logpush is used to get raw Workers execution logs. Refer to [Logpush](https://developers.cloudflare.com/workers/observability/logs/logpush/) for more information.

Logpush can be enabled for an entire dispatch namespace or a single user Worker. To capture logs for all of the user Workers in a dispatch namespace:

1. Create a [Logpush job](https://developers.cloudflare.com/workers/observability/logs/logpush/#create-a-logpush-job).
2. Enable [logging](https://developers.cloudflare.com/workers/observability/logs/logpush/#enable-logging-on-your-worker) on your dispatch Worker.

Enabling logging on your dispatch Worker collects logs for both the dispatch Worker and for any user Workers in the dispatch namespace. Logs are automatically collected for all new Workers added to a dispatch namespace. To enable logging for an individual user Worker rather than an entire dispatch namespace, skip step 1 and complete step 2 on your user Worker.

All logs are forwarded to the Logpush job that you have setup for your account. Logpush filters can be used on the `Outcome` or `Script Name` field to include or exclude specific values or send logs to different destinations.

### Tail Workers

A [Tail Worker](https://developers.cloudflare.com/workers/observability/logs/tail-workers/) receives information about the execution of other Workers (known as producer Workers), such as HTTP statuses, data passed to `console.log()` or uncaught exceptions.

Use [Tail Workers](https://developers.cloudflare.com/workers/observability/logs/tail-workers/) instead of Logpush if you want granular control over formatting before logs are sent to their destination to receive [diagnostics channel events](https://developers.cloudflare.com/workers/runtime-apis/nodejs/diagnostics-channel), or if you want logs delivered in real-time.

Adding a Tail Worker to your dispatch Worker collects logs for both the dispatch Worker and for any user Workers in the dispatch namespace. Logs are automatically collected for all new Workers added to a dispatch namespace. To enable logging for an individual user Worker rather than an entire dispatch namespace, add the [Tail Worker configuration](https://developers.cloudflare.com/workers/observability/logs/tail-workers/#configure-tail-workers) directly to the user Worker.

## Analytics

There are two ways for you to review your Workers for Platforms analytics.

### Workers Analytics Engine

[Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/) can be used with Workers for Platforms to provide analytics to end users. It can be used to expose events relating to a Workers invocation or custom user-defined events. Platforms can write/query events by script tag to get aggregates over a user’s usage.

### GraphQL Analytics API

Use Cloudflare’s [GraphQL Analytics API](https://developers.cloudflare.com/analytics/graphql-api) to get metrics relating to your Dispatch Namespaces. Use the `dispatchNamespaceName` dimension in the `workersInvocationsAdaptive` node to query usage by namespace.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/observability/","name":"Observability"}}]}
```

---

---
title: Outbound Workers
description: Intercept and control outgoing fetch requests from user Workers using Outbound Workers in Workers for Platforms.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Outbound Workers

Outbound Workers sit between your customer's Workers and the public Internet. They give you visibility into all outgoing `fetch()` requests from user Workers.

![Outbound Workers diagram information](https://developers.cloudflare.com/_astro/outbound-worker-diagram.BSvN4KG0_YJsgi.webp) 

## General Use Cases

Outbound Workers can be used to:

* Log all subrequests to identify malicious domains or usage patterns.
* Create, allow, or block lists for hostnames requested by user Workers.
* Configure authentication to your APIs behind the scenes (without end developers needing to set credentials).

Note

When an Outbound Worker is enabled, your customer's Worker will no longer be able to use the [connect() API](https://developers.cloudflare.com/workers/runtime-apis/tcp-sockets/#connect)to create outbound TCP Sockets. This is to ensure all outbound communication goes through the Outbound Worker's `fetch` method.

## Use Outbound Workers

To use Outbound Workers:

1. Create a Worker intended to serve as your Outbound Worker.
2. Outbound Worker can be specified as an optional parameter in the [dispatch namespaces](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/) binding in a project's [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). Optionally, to pass data from your dynamic dispatch Worker to the Outbound Worker, the variable names can be specified under **parameters**.

Make sure that you have `wrangler@3.3.0` or later [installed](https://developers.cloudflare.com/workers/wrangler/install-and-update/).

* [  wrangler.jsonc ](#tab-panel-4549)
* [  wrangler.toml ](#tab-panel-4550)

JSONC

```

{

  "dispatch_namespaces": [

    {

      "binding": "dispatcher",

      "namespace": "<NAMESPACE_NAME>",

      "outbound": {

        "service": "<SERVICE_NAME>",

        "parameters": [

          "params_object"

        ]

      }

    }

  ]

}


```

TOML

```

[[dispatch_namespaces]]

binding = "dispatcher"

namespace = "<NAMESPACE_NAME>"


  [dispatch_namespaces.outbound]

  service = "<SERVICE_NAME>"

  parameters = [ "params_object" ]


```

1. Edit your dynamic dispatch Worker to call the Outbound Worker and declare variables to pass on `dispatcher.get()`.

JavaScript

```

export default {

  async fetch(request, env) {

    try {

      // parse the URL, read the subdomain

      let workerName = new URL(request.url).host.split(".")[0];


      let context_from_dispatcher = {

        customer_name: workerName,

        url: request.url,

      };


      let userWorker = env.dispatcher.get(

        workerName,

        {},

        {

          // outbound arguments. object name must match parameters in the binding

          outbound: {

            params_object: context_from_dispatcher,

          },

        },

      );

      return await userWorker.fetch(request);

    } catch (e) {

      if (e.message.startsWith("Worker not found")) {

        // we tried to get a worker that doesn't exist in our dispatch namespace

        return new Response("", { status: 404 });

      }

      return new Response(e.message, { status: 500 });

    }

  },

};


```

1. The Outbound Worker will now be invoked on any `fetch()` requests from a user Worker. The user Worker will trigger a [FetchEvent](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) on the Outbound Worker. The variables declared in the binding can be accessed in the Outbound Worker through `env.<VAR_NAME>`.

The following is an example of an Outbound Worker that logs the fetch request from user Worker and creates a JWT if the fetch request matches `api.example.com`.

JavaScript

```

export default {

  // this event is fired when the dispatched Workers make a subrequest

  async fetch(request, env, ctx) {

    // env contains the values we set in `dispatcher.get()`

    const customer_name = env.customer_name;

    const original_url = env.url;


    // log the request

    ctx.waitUntil(

      fetch("https://logs.example.com", {

        method: "POST",

        body: JSON.stringify({

          customer_name,

          original_url,

        }),

      }),

    );


    const url = new URL(original_url);

    if (url.host === "api.example.com") {

      // pre-auth requests to our API

      const jwt = make_jwt_for_customer(customer_name);


      let headers = new Headers(request.headers);

      headers.set("Authorization", `Bearer ${jwt}`);


      // clone the request to set new headers using existing body

      let new_request = new Request(request, { headers });


      return fetch(new_request);

    }


    return fetch(request);

  },

};


```

Note

Outbound Workers do not intercept fetch requests made from [Durable Objects](https://developers.cloudflare.com/durable-objects/) or [mTLS certificate bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/mtls/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/","name":"Outbound Workers"}}]}
```

---

---
title: Static assets
description: Host static assets on Cloudflare's global network and deliver faster load times worldwide with Workers for Platforms.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Static assets

Workers for Platforms lets you deploy front-end applications at scale. By hosting static assets on Cloudflare's global network, you can deliver faster load times worldwide and eliminate the need for external infrastructure. You can also combine these static assets with dynamic logic in Cloudflare Workers, providing a full-stack experience for your customers.

### What you can build

#### Static sites

Host and serve HTML, CSS, JavaScript, and media files directly from Cloudflare's network, ensuring fast loading times worldwide. This is ideal for blogs, landing pages, and documentation sites.

#### Full-stack applications

Combine asset hosting with Cloudflare Workers to power dynamic, interactive applications. Store and retrieve data using Cloudflare KV, D1, and R2 Storage, allowing you to serve both front-end assets and backend logic from a single Worker.

### Benefits

#### Global caching for faster performance

Cloudflare automatically caches static assets at data centers worldwide, reducing latency and improving load times by up to 2x for users everywhere.

#### Scalability without infrastructure management

Your applications scale automatically to handle high traffic without requiring you to provision or manage infrastructure. Cloudflare dynamically adjusts to demand in real time.

#### Unified deployment for static and dynamic content

Deploy front-end assets alongside server-side logic, all within Cloudflare Workers. This eliminates the need for a separate hosting provider and ensures a streamlined deployment process.

---

## Deploy static assets to User Workers

It is common that, as the Platform, you will be responsible for uploading static assets on behalf of your end users. This often looks like this:

1. Your user uploads files (HTML, CSS, images) through your interface.
2. Your platform interacts with the Workers for Platforms APIs to attach the static assets to the User Worker script.

Once you receive the static files from your users (for a new or updated site), complete the following steps to attach the files to the corresponding User Worker:

1. Create an Upload Session
2. Upload file contents
3. Deploy/Update the Worker

After these steps are completed, the User Worker's static assets will be live on the Cloudflare's global network.

### 1\. Create an Upload Session

Before sending any file data, you need to tell Cloudflare which files you intend to upload. That list of files is called a manifest. Each item in the manifest includes:

* A file path (for example, `"/index.html"` or `"/assets/logo.png"`)
* A hash (32-hex characters) representing the file contents
* The file size in bytes

Asset Isolation Considerations

Static assets uploaded to Workers for Platforms are associated with the namespace rather than with individual User Worker. If multiple User Workers exist under the same namespace, assets with identical hashes may be shared across them. **JWTs should therefore only be shared with trusted platform services and should never be distributed to end-users.**

If strict isolation of assets is required, we recommend either salting with a random value each time, or incorporating an end-user identifier (for example, account ID or Worker script ID) within the hashing process, to ensure uniqueness. For example, `hash = slice(sha256(accountID + fileContents), 32)`.

#### Example manifest (JSON)

```

{

  "/index.html": {

    "hash": "08f1dfda4574284ab3c21666d1ee8c7d4",

    "size": 1234

  },

  "/styles.css": {

    "hash": "36b8be012ee77df5f269b11b975611d3",

    "size": 5678

  }

}


```

To start the upload process, send a POST request to the Create Assets Upload Session [API endpoint](https://developers.cloudflare.com/api/resources/workers%5Ffor%5Fplatforms/subresources/dispatch/subresources/namespaces/subresources/scripts/subresources/asset%5Fupload/methods/create/).

Terminal window

```

POST /accounts/{account_id}/workers/dispatch/namespaces/{namespace}/scripts/{script_name}/assets-upload-session


```

Path Parameters:

* `namespace`: Name of the Workers for Platforms dispatch namespace
* `script_name`: Name of the User Worker

In the request body, include a JSON object listing each file path along with its hash and size. This helps Cloudflare identify which files you intend to upload and allows Cloudflare to check if any of them are already stored.

#### Sample request

Terminal window

```

curl -X POST \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME/assets-upload-session" \

  -H "Content-Type: application/json" \

  -H "Authorization: Bearer $API_TOKEN" \

  --data '{

    "manifest": {

      "/index.html": {

        "hash": "08f1dfda4574284ab3c21666d1ee8c7d4",

        "size": 1234

      },

      "/styles.css": {

        "hash": "36b8be012ee77df5f269b11b975611d3",

        "size": 5678

      }

    }

  }'


```

#### Generating the hash

You can compute a SHA-256 digest of the file contents, then truncate or otherwise represent it consistently as a 32-hex-character string. Make sure to do it the same way each time so Cloudflare can reliably match files across uploads.

#### API Response

If all the files are already stored on Cloudflare, the response will only return the JWT token. If new or updated files are needed, the response will return:

* `jwt`: An upload token (valid for 1 hour) which will be used in the API request to upload the file contents (Step 2).
* `buckets`: An array of file-hash groups indicating which files to upload together. Files that have been recently uploaded will not appear in buckets, since Cloudflare already has them.

Note

This step alone does not store files on Cloudflare. You must upload the actual file data in the next step.

### 2\. Upload File Contents

If the response to the Upload Session API returns `buckets`, that means you have new or changed files that need to be uploaded to Cloudflare.

Use the [Workers Assets Upload API](https://developers.cloudflare.com/api/resources/workers/subresources/assets/subresources/upload/) to transmit the raw file bytes in base64-encoded format for any missing or changed files. Once uploaded, Cloudflare will store these files so they can then be attached to a User Worker.

Warning

Asset uniqueness is determined by the provided hash and are associated globally to their namespace rather than with each specific User Worker. If an asset has already been uploaded for that namespace earlier, Cloudflare will automatically omit sending this asset hash back in the `buckets` response to save you from re-uploading the same thing twice. This means that an asset can be shared between multiple User Workers if it shares the same hash unless you **explicitly make the hash unique**. If you require full isolation between assets across User Workers, incorporate a unique identifier within your asset hashing process (either salting it with something entirely random each time, or by including the end-user account ID or their Worker name to retain per-customer re-use).

#### API Request Authentication

Unlike most Cloudflare API calls that use an account-wide API token in the Authorization header, uploading file contents requires using the short-lived JWT token returned in the `jwt` field of the `assets-upload-session` response.

Include it as a Bearer token in the header:

Terminal window

```

Authorization: Bearer <upload-session-token>


```

This token is valid for one hour and must be supplied for each upload request to the Workers Assets Upload API.

#### File fields (multipart/form-data)

You must send the files as multipart/form-data with base64-encoded content:

* Field name: The file hash (for example, `36b8be012ee77df5f269b11b975611d3`)
* Field value: A Base64-encoded string of the file's raw bytes

#### Example: Uploading multiple files within a single bucket

If your Upload Session response listed a single "bucket" containing two file hashes:

```

"buckets": [

  [

    "08f1dfda4574284ab3c21666d1ee8c7d4",

    "36b8be012ee77df5f269b11b975611d3"

  ]

]


```

You can upload both files in one request, each as a form-data field:

Terminal window

```

curl -X POST \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/assets/upload?base64=true" \

  -H "Authorization: Bearer <upload-session-token>" \

  -F "08f1dfda4574284ab3c21666d1ee8c7d4=<BASE64_OF_INDEX_HTML>" \

  -F "36b8be012ee77df5f269b11b975611d3=<BASE64_OF_STYLES_CSS>"


```

* `<upload-session-token>` is the token from step 1's assets-upload-session response
* `<BASE64_OF_INDEX_HTML>` is the Base64-encoded content of index.html
* `<BASE64_OF_STYLES_CSS>` is the Base64-encoded content of styles.css

If you have multiple buckets (for example, `[["hashA"], ["hashB"], ["hashC"]]`), you might need to repeat this process for each bucket, making one request per bucket group.

Once every file in the manifest has been uploaded, a status code of `201` will be returned, with the `jwt` field present. This JWT is a final "completion" token which can be used to create a deployment of a Worker with this set of assets. This completion token is valid for 1 hour.

```

{

  "success": true,

  "errors": [],

  "messages": [],

  "result": {

    "jwt": "<completion-token>"

  }

}


```

`<completion-token>` indicates that Cloudflare has successfully received and stored the file contents specified by your manifest. You will use this `<completion-token>` in Step 3 to finalize the attachment of these files to the Worker.

### 3\. Deploy the User Worker with static assets

Now that Cloudflare has all the files it needs (from the previous upload steps), you must attach them to the User Worker by making a PUT request to the [Upload User Worker API](https://developers.cloudflare.com/api/resources/workers%5Ffor%5Fplatforms/subresources/dispatch/subresources/namespaces/subresources/scripts/methods/update/). This final step links the static assets to the User Worker using the completion token you received after uploading file contents.

You can also specify any optional settings under the `assets.config` field to customize how your files are served (for example, to handle trailing slashes in HTML paths).

#### API request example

Terminal window

```

curl -X PUT \

  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \

  -H "Content-Type: multipart/form-data" \

  -H "Authorization: Bearer $API_TOKEN" \

  -F 'metadata={

    "main_module": "index.js",

    "assets": {

      "jwt": "<completion-token>",

      "config": {

        "html_handling": "auto-trailing-slash"

      }

    },

    "compatibility_date": "2025-01-24"

  };type=application/json' \

  -F 'index.js=@/path/to/index.js;type=application/javascript'


```

* The `"jwt": "<completion-token>"` links the newly uploaded files to the Worker
* Including "html\_handling" (or other fields under "config") is optional and can customize how static files are served
* If the user's Worker code has not changed, you can omit the code file or re-upload the same index.js

Once this PUT request succeeds, the files are served on the User Worker. Requests routed to that Worker will serve the new or updated static assets.

---

## Deploying static assets with Wrangler

If you prefer a CLI-based approach and your platform setup allows direct publishing, you can use Wrangler to deploy both your Worker code and static assets. Wrangler bundles and uploads static assets (from a specified directory) along with your Worker script, so you can manage everything in one place.

Create or update your [Wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) to specify where Wrangler should look for static files:

* [  wrangler.jsonc ](#tab-panel-4551)
* [  wrangler.toml ](#tab-panel-4552)

JSONC

```

{

  "$schema": "./node_modules/wrangler/config-schema.json",

  "name": "my-static-site",

  "main": "./src/index.js",

  // Set this to today's date

  "compatibility_date": "2026-04-30",

  "assets": {

    "directory": "./public",

    "binding": "ASSETS",

  },

}


```

TOML

```

"$schema" = "./node_modules/wrangler/config-schema.json"

name = "my-static-site"

main = "./src/index.js"

# Set this to today's date

compatibility_date = "2026-04-30"


[assets]

directory = "./public"

binding = "ASSETS"


```

* `directory`: The local folder containing your static files (for example, `./public`).
* `binding`: The binding name used to reference these assets within your Worker code.

### 1\. Organize your files

Place your static files (HTML, CSS, images, etc.) in the specified directory (in this example, `./public`). Wrangler will detect and bundle these files when you publish your Worker.

If you need to reference these files in your Worker script to serve them dynamically, you can use the `ASSETS` binding like this:

JavaScript

```

export default {

  async fetch(request, env, ctx) {

    return env.ASSETS.fetch(request);

  },

};


```

### 2\. Deploy the User Worker with the static assets

Run Wrangler to publish both your Worker code and the static assets:

Terminal window

```

npx wrangler deploy --name <USER_WORKER_NAME> --dispatch-namespace <NAMESPACE_NAME>


```

Wrangler will automatically detect your static files, bundle them, and upload them to Cloudflare along with your Worker code.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/static-assets/","name":"Static assets"}}]}
```

---

---
title: Tags
description: Organize, search, and filter user Workers by custom tags like customer ID or plan type in Workers for Platforms.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Tags

Use tags to organize, search, and filter user Workers at scale. Tag Workers based on customer ID, plan type, project ID, or environment. After you tag user Workers, you can perform bulk operations like deleting all Workers for a specific customer.

Note

You can set a maximum of eight tags per script. Avoid special characters like `,` and `&` when naming your tag.

## Add tags via dashboard

1. Go to **Workers for Platforms** in the Cloudflare dashboard and select your namespace.
2. Select a user Worker from the list.
3. Go to **Settings** \> **Tags**.
4. Add your tags (for example, `customer-123`, `pro-plan`, `production`).
5. Select **Save**.

You can also search and filter Workers by tags in the namespace view.

## Tags API reference

For complete API documentation, refer to [Workers for Platforms API](https://developers.cloudflare.com/api/resources/workers%5Ffor%5Fplatforms/subresources/dispatch/subresources/namespaces/subresources/scripts/subresources/tags/).

### Get script tags

Fetch all tags for a Worker script.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Workers Tail Read`
* `Workers Scripts Write`
* `Workers Scripts Read`

Get Script Tags

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$DISPATCH_NAMESPACE/scripts/$SCRIPT_NAME/tags" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

### Set script tags

Replace all tags on a Worker script. Existing tags not in the request are removed.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Workers Scripts Write`

Put Script Tags

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$DISPATCH_NAMESPACE/scripts/$SCRIPT_NAME/tags" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

### Add a single tag

Add one tag to a Worker script without affecting existing tags.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Workers Scripts Write`

Put Script Tag

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$DISPATCH_NAMESPACE/scripts/$SCRIPT_NAME/tags/$TAG" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

### Delete a single tag

Remove one tag from a Worker script.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Workers Scripts Write`

Delete Script Tag

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$DISPATCH_NAMESPACE/scripts/$SCRIPT_NAME/tags/$TAG" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

### Filter Workers by tag

List all Workers that match a tag filter. Use `tag:yes` to include or `tag:no` to exclude.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Workers Tail Read`
* `Workers Scripts Write`
* `Workers Scripts Read`

List Scripts in Namespace

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$DISPATCH_NAMESPACE/scripts?tags=production%3Ayes" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

### Delete Workers by tag

Delete all Workers matching a tag filter. Use this to bulk delete Workers when a customer leaves your platform.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Workers Scripts Write`

Delete Scripts in Namespace

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$DISPATCH_NAMESPACE/scripts?tags=customer-123%3Ayes" \

  --request DELETE \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/","name":"Configuration"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/configuration/tags/","name":"Tags"}}]}
```

---

---
title: Get started
description: Deploy a Workers for Platforms starter kit and create your first multi-tenant platform on Cloudflare.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Get started

Get started with Workers for Platforms by deploying a starter kit to your account.

## Deploy a platform

Deploy the [Platform Starter Kit ↗](https://github.com/cloudflare/templates/tree/main/worker-publisher-template) to your Cloudflare account. This creates a complete Workers for Platforms setup with one click.

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/templates/tree/main/worker-publisher-template)

After deployment completes, open your Worker URL. You now have a platform where you can deploy code snippets.

### Try it out

1. Enter a script name, for example `my-worker`.
2. Write or paste Worker code in the editor.
3. Click **Deploy Worker**.

Once deployed, visit `/<script-name>` on your Worker URL to run your code. For example, if you named your script `my-worker`, go to `https://<your-worker>.<subdomain>.workers.dev/my-worker`.

Each script you deploy becomes its own isolated Worker. The platform calls the Cloudflare API to create the Worker and the dispatch Worker routes requests to it based on the URL path.

## Understand how it works

The template you deployed contains three components that work together:

### Dispatch namespace

A dispatch namespace is a collection of user Workers. Think of it as a container that holds all the Workers your platform deploys on behalf of your customers.

When you deployed the template, it created a dispatch namespace automatically. You can view it in the Cloudflare dashboard under **Workers for Platforms**.

### Dispatch Worker

The dispatch Worker receives incoming requests and routes them to the correct user Worker. It uses a [binding](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) to access the dispatch namespace.

JavaScript

```

export default {

  async fetch(request, env) {

    // Get the user Worker name from the URL path

    const url = new URL(request.url);

    const workerName = url.pathname.split("/")[1];


    // Fetch the user Worker from the dispatch namespace

    const userWorker = env.DISPATCHER.get(workerName);


    // Forward the request to the user Worker

    return userWorker.fetch(request);

  },

};


```

The `env.DISPATCHER.get()` method retrieves a user Worker by name from the dispatch namespace.

### User Workers

User Workers contain the code your customers write and deploy. They run in isolated environments with no access to other customers' data or code.

In the template, user Workers are deployed programmatically through the API. In production, your platform would call the Cloudflare API or SDK to deploy user Workers when your customers save their code.

## Build your platform

Now that you understand how the components work together, customize the template for your use case:

* [Dynamic dispatch](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/) — Route requests by subdomain or hostname
* [Hostname routing](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/hostname-routing/) — Let customers use [custom domains](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) with their applications
* [Bindings](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) — Give each customer access to their own [database](https://developers.cloudflare.com/d1/), [key-value store](https://developers.cloudflare.com/kv/), or [object storage](https://developers.cloudflare.com/r2/)
* [Outbound Workers](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/) — Configure egress policies on outgoing requests from customer code
* [Custom limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/) — Set CPU time and subrequest limits per customer
* [API examples](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/platform-examples/) — Examples for deploying and managing customer code programmatically

## Build an AI vibe coding platform

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/vibesdk)

Build an [AI vibe coding platform](https://developers.cloudflare.com/reference-architecture/diagrams/ai/ai-vibe-coding-platform/) where users describe what they want and AI generates and deploys applications.

With [VibeSDK ↗](https://github.com/cloudflare/vibesdk), Cloudflare's open source vibe coding platform, you can get started with an example that handles AI code generation, code execution in secure sandboxes, live previews, and deployment at scale.

[ View demo ](https://build.cloudflare.dev) [ View on GitHub ](https://github.com/cloudflare/vibesdk) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/get-started/","name":"Get started"}}]}
```

---

---
title: How Workers for Platforms works
description: Understand the architecture of Workers for Platforms, including dispatch namespaces, dynamic dispatch Workers, user Workers, and outbound Workers.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# How Workers for Platforms works

## Architecture

If you are familiar with [Workers](https://developers.cloudflare.com/workers/), Workers for Platforms introduces four key components: dispatch namespaces, dynamic dispatch Workers, user Workers, and optionally outbound Workers.

![Workers for Platforms architecture](https://developers.cloudflare.com/_astro/programmable-platforms-1.BCCEhzLr_2d88FE.svg) 

### Dispatch namespace

A dispatch namespace is a container that holds all of your customers' Workers. Your platform takes the code your customers write, and then makes an API request to deploy that code as a user Worker to a namespace — for example `staging` or `production`. Compared to [Workers](https://developers.cloudflare.com/workers/), this provides:

* **Unlimited number of Workers** \- No per-account script limits apply to Workers in a namespace
* **Isolation by default** \- Each user Worker in a namespace runs in [untrusted mode](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/worker-isolation/) — user Workers never share a cache even when running on the same Cloudflare zone, and cannot access the `request.cf` object
* **Dynamic invocation** \- Your dynamic dispatch Worker can call any Worker in the namespace using `env.DISPATCHER.get("worker-name")`

Best practice

All your customers' Workers should live in a single namespace (for example, `production`). Do not create a namespace per customer.

If you need to test changes safely, create a separate `staging` namespace.

### Dynamic dispatch Worker

A dynamic dispatch Worker is the entry point for all requests to your platform. Your dynamic dispatch Worker:

* **Routes requests** \- Determines which customer Worker should handle each request based on hostname, path, headers, or any other criteria
* **Runs platform logic** \- Executes authentication, rate limiting, or request validation before customer code runs
* **Sets per-customer limits** \- Enforces [custom limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/) on CPU time and subrequests based on plan type
* **Sanitizes responses** \- Modifies or filters responses from customer Workers

The dynamic dispatch Worker uses a [dispatch namespace binding](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/dynamic-dispatch/) to invoke user Workers:

JavaScript

```

export default {

  async fetch(request, env) {

    // Determine which customer Worker to call

    const customerName = new URL(request.url).hostname.split(".")[0];


    // Get and invoke the customer's Worker

    const userWorker = env.DISPATCHER.get(customerName);

    return userWorker.fetch(request);

  },

};


```

### User Workers

User Workers contain code written by your customers. Your customer sends their code to your platform, and then you make an API request to deploy a user Worker on their behalf. User Workers are deployed to a dispatch namespace and invoked by your dynamic dispatch Worker. You can provide user Workers with [bindings](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) to access KV, D1, R2, and other Cloudflare resources.

![Deployment and management flow](https://developers.cloudflare.com/_astro/programmable-platforms-6.BfYznbr5_2d88FE.svg) 

### Outbound Worker (optional)

An [outbound Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/) intercepts [fetch()](https://developers.cloudflare.com/workers/runtime-apis/fetch/) requests made by user Workers. Use it to:

* **Control egress** \- Block or allow external API calls from customer code
* **Log requests** \- Track what external services customers are calling
* **Modify requests** \- Add authentication headers or transform requests before they leave your platform
![Outbound Worker egress control pattern](https://developers.cloudflare.com/_astro/programmable-platforms-3.C-LkeZtS_Z19nioR.svg) 

### Request lifecycle

1. A request arrives at your dynamic dispatch Worker (for example, `customer-a.example.com/api`)
2. Your dynamic dispatch Worker determines which user Worker should handle the request
3. The dynamic dispatch Worker calls `env.DISPATCHER.get("customer-a")` to get the user Worker
4. The user Worker executes. If it makes external `fetch()` calls and an outbound Worker is configured, those requests pass through the outbound Worker first.
5. The user Worker returns a response
6. Your dynamic dispatch Worker can optionally modify the response before returning it

---

## Workers for Platforms versus Service bindings

Both Workers for Platforms and [Service bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) enable Worker-to-Worker communication. Use Service bindings when you know exactly which Workers need to communicate. Use Workers for Platforms when user Workers are uploaded dynamically by your customers.

You can use both simultaneously - your dynamic dispatch Worker can use Service bindings to call internal services while also dispatching to user Workers in a namespace.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/","name":"How Workers for Platforms works"}}]}
```

---

---
title: Limits
description: Review Workers for Platforms limits for scripts, Durable Objects, cache, tags, and API rate limits.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Limits

## Script limits

Cloudflare provides an unlimited number of scripts for Workers for Platforms customers.

## `cf` object

The [cf object](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties) contains Cloudflare-specific properties of a request. This field is not accessible in [user Workers](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/#user-workers) by default because some fields in this object are sensitive and can be used to manipulate Cloudflare features (for example, `cacheKey`, `resolveOverride`, `scrapeShield`.)

To access the `cf` object, you need to enable [trusted mode](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/worker-isolation/#trusted-mode) for your namespace. Only enable this if you control all Worker code in the namespace.

## Durable Object namespace limits

Workers for Platforms do not have a limit for the number of Durable Object namespaces.

## Cache API

For isolation, `caches.default` is disabled for namespaced scripts. To learn more about the cache, refer to [How the cache Works](https://developers.cloudflare.com/workers/reference/how-the-cache-works/).

## ​Tags

You can set a maximum of eight tags per script. Avoid special characters like `,` and `&` when naming your tag.

Need a higher limit?

To request an adjustment to a limit, complete the [Limit Increase Request Form ↗](https://forms.gle/ukpeZVLWLnKeixDu7). If the limit can be increased, Cloudflare will contact you with next steps.

## Gradual Deployments

[Gradual Deployments](https://developers.cloudflare.com/workers/configuration/versions-and-deployments/gradual-deployments/) is not supported yet for user Workers. Changes made to user Workers create a new version that deployed all-at-once to 100% of traffic.

## API Rate Limits

| Type                              | Limit                               |
| --------------------------------- | ----------------------------------- |
| Client API per user/account token | 1200/5 minutes                      |
| Client API per IP                 | 200/second                          |
| GraphQL                           | Varies by query cost. Max 320/5 min |
| User API token quota              | 50                                  |
| Account API token quota           | 500                                 |

Note

The global rate limit for the Cloudflare API is 1,200 requests per five minute period per user, and applies cumulatively regardless of whether the request is made via the dashboard, API key, or API token.

If you exceed this limit, all API calls for the next five minutes will be blocked, receiving a `HTTP 429 - Too Many Requests` response.

Some specific API calls have their own limits and are documented separately, such as the following:

* [Cache Purge APIs](https://developers.cloudflare.com/cache/how-to/purge-cache/#availability-and-limits)
* [GraphQL APIs](https://developers.cloudflare.com/analytics/graphql-api/limits/)
* [Rulesets APIs](https://developers.cloudflare.com/ruleset-engine/rulesets-api/#limits)
* [Lists API](https://developers.cloudflare.com/waf/tools/lists/lists-api/#rate-limiting-for-lists-api-requests)
* [Gateway Lists API](https://developers.cloudflare.com/cloudflare-one/reusable-components/lists/#api-rate-limit)

Enterprise customers can also [contact Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to raise the Client API per user, GraphQL, or API token limits to a higher value.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/limits/","name":"Limits"}}]}
```

---

---
title: Local development
description: Test your dynamic dispatch Worker locally while connecting to deployed user Workers in a Workers for Platforms namespace.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Local development

Test changes to your [dynamic dispatch Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/#dynamic-dispatch-worker) by running the dynamic dispatch Worker locally but connecting it to user Workers that have been deployed to Cloudflare.

Note

Consider using a staging namespace to test changes safely before deploying to production.

This is helpful when:

* **Testing routing changes** and validating that updates continue to work with deployed User Workers
* **Adding new middleware** like authentication, rate limiting, or logging to the dynamic dispatch Worker
* **Debugging issues** in the dynamic dispatcher that may be impacting deployed User Workers

### How to use remote dispatch namespaces

In the dynamic dispatch Worker's Wrangler file, configure the [dispatch namespace binding](https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms) to connect to the remote namespace by setting [remote = true](https://developers.cloudflare.com/workers/development-testing/#remote-bindings):

* [  wrangler.jsonc ](#tab-panel-4553)
* [  wrangler.toml ](#tab-panel-4554)

JSONC

```

{

  "dispatch_namespaces": [

    {

      "binding": "DISPATCH_NAMESPACE",

      "namespace": "production",

      "remote": true

    }

  ]

}


```

TOML

```

[[dispatch_namespaces]]

binding = "DISPATCH_NAMESPACE"

namespace = "production"

remote = true


```

This tells your dispatch Worker that's running locally to connect to the remote `production` namespace. When you run `wrangler dev`, your Dispatch Worker will route requests to the User Workers deployed in that namespace.

For more information about remote bindings during local development, refer to [remote bindings documentation](https://developers.cloudflare.com/workers/development-testing/#remote-bindings).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/local-development/","name":"Local development"}}]}
```

---

---
title: Multipart upload metadata
description: Define Workers configuration in JSON metadata for multipart form-data script uploads.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Multipart upload metadata

Note

There is a new API for uploading Workers. Refer to [these docs](https://developers.cloudflare.com/workers/platform/infrastructure-as-code#cloudflare-rest-api) for more information.

If you're using the [Workers Script Upload API](https://developers.cloudflare.com/api/resources/workers/subresources/scripts/methods/update/) or [Version Upload API](https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/versions/methods/create/) directly, `multipart/form-data` uploads require you to specify a `metadata` part. This metadata defines the Worker's configuration in JSON format, analogue to the [wrangler.toml file](https://developers.cloudflare.com/workers/wrangler/configuration/).

## Sample `metadata`

```

{

  "main_module": "main.js",

  "bindings": [

    {

      "type": "plain_text",

      "name": "MESSAGE",

      "text": "Hello, world!"

    }

  ],

  "compatibility_date": "2021-09-14"

}


```

Note

See examples of metadata being used with the Workers Script Upload API [here](https://developers.cloudflare.com/workers/platform/infrastructure-as-code#cloudflare-rest-api).

## Attributes

The following attributes are configurable at the top-level.

Note

At a minimum, the `main_module` key is required to upload a Worker.

* `main_module` ` string ` required  
   * The part name that contains the module entry point of the Worker that will be executed. For example, `main.js`.
* `assets` ` object ` optional  
   * [Asset](https://developers.cloudflare.com/workers/static-assets/) configuration for a Worker.  
   * `config` ` object ` optional  
         * [html\_handling](https://developers.cloudflare.com/workers/static-assets/routing/advanced/html-handling/) determines the redirects and rewrites of requests for HTML content.  
         * [not\_found\_handling](https://developers.cloudflare.com/workers/static-assets/#routing-behavior) determines the response when a request does not match a static asset.  
   * `jwt` field provides a token authorizing assets to be attached to a Worker.
* `keep_assets` ` boolean ` optional  
   * Specifies whether assets should be retained from a previously uploaded Worker version; used in lieu of providing a completion token.
* `bindings` array\[object\] optional  
   * [Bindings](#bindings) to expose in the Worker.
* `placement` ` object ` optional  
   * [Smart placement](https://developers.cloudflare.com/workers/configuration/placement/) object for the Worker.  
   * `mode` field only supports `smart` for automatic placement.
* `compatibility_date` ` string ` optional  
   * [Compatibility Date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/#setting-compatibility-date) indicating targeted support in the Workers runtime. Backwards incompatible fixes to the runtime following this date will not affect this Worker. Highly recommended to set a `compatibility_date`, otherwise if on upload via the API, it defaults to the oldest compatibility date before any flags took effect (2021-11-02).
* `compatibility_flags` array\[string\] optional  
   * [Compatibility Flags](https://developers.cloudflare.com/workers/configuration/compatibility-flags/#setting-compatibility-flags) that enable or disable certain features in the Workers runtime. Used to enable upcoming features or opt in or out of specific changes not included in a `compatibility_date`.

## Additional attributes: [Workers Script Upload API](https://developers.cloudflare.com/api/resources/workers/subresources/scripts/methods/update/)

For [immediately deployed uploads](https://developers.cloudflare.com/workers/configuration/versions-and-deployments/#upload-a-new-version-and-deploy-it-immediately), the following **additional** attributes are configurable at the top-level.

Note

Except for `annotations`, these attributes are **not available** for version uploads.

* `migrations` array\[object\] optional  
   * [Durable Objects migrations](https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/) to apply.
* `logpush` ` boolean ` optional  
   * Whether [Logpush](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/hostname-analytics/#logpush) is turned on for the Worker.
* `tail_consumers` array\[object\] optional  
   * [Tail Workers](https://developers.cloudflare.com/workers/observability/logs/tail-workers/) that will consume logs from the attached Worker.
* `tags` array\[string\] optional  
   * List of strings to use as tags for this Worker.
* `annotations` ` object ` optional  
   * Annotations object for the Worker version created by this upload. Also available on the [Version Upload API](#additional-attributes-version-upload-api).  
   * `workers/message` specifies a custom message for the version.  
   * `workers/tag` specifies a custom identifier for the version.

## Additional attributes: [Version Upload API](https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/versions/methods/create/)

For [version uploads](https://developers.cloudflare.com/workers/configuration/versions-and-deployments/#upload-a-new-version-to-be-gradually-deployed-or-deployed-at-a-later-time), the following **additional** attributes are configurable at the top-level.

* `annotations` ` object ` optional  
   * Annotations object specific to the Worker version.  
   * `workers/message` specifies a custom message for the version.  
   * `workers/tag` specifies a custom identifier for the version.  
   * `workers/alias` specifies a custom alias for this version.

## Bindings

Workers can interact with resources on the Cloudflare Developer Platform using [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/). Refer to the JSON example below that shows how to add bindings in the `metadata` part.

```

{

  "bindings": [

    {

      "type": "ai",

      "name": "<VARIABLE_NAME>"

    },

    {

      "type": "analytics_engine",

      "name": "<VARIABLE_NAME>",

      "dataset": "<DATASET>"

    },

    {

      "type": "assets",

      "name": "<VARIABLE_NAME>"

    },

    {

      "type": "browser_rendering",

      "name": "<VARIABLE_NAME>"

    },

    {

      "type": "d1",

      "name": "<VARIABLE_NAME>",

      "id": "<D1_ID>"

    },

    {

      "type": "durable_object_namespace",

      "name": "<VARIABLE_NAME>",

      "class_name": "<DO_CLASS_NAME>"

    },

    {

      "type": "hyperdrive",

      "name": "<VARIABLE_NAME>",

      "id": "<HYPERDRIVE_ID>"

    },

    {

      "type": "kv_namespace",

      "name": "<VARIABLE_NAME>",

      "namespace_id": "<KV_ID>"

    },

    {

      "type": "mtls_certificate",

      "name": "<VARIABLE_NAME>",

      "certificate_id": "<MTLS_CERTIFICATE_ID>"

    },

    {

      "type": "plain_text",

      "name": "<VARIABLE_NAME>",

      "text": "<VARIABLE_VALUE>"

    },

    {

      "type": "queue",

      "name": "<VARIABLE_NAME>",

      "queue_name": "<QUEUE_NAME>"

    },

    {

      "type": "r2_bucket",

      "name": "<VARIABLE_NAME>",

      "bucket_name": "<R2_BUCKET_NAME>"

    },

    {

      "type": "secret_text",

      "name": "<VARIABLE_NAME>",

      "text": "<SECRET_VALUE>"

    },

    {

      "type": "service",

      "name": "<VARIABLE_NAME>",

      "service": "<SERVICE_NAME>",

      "environment": "production"

    },

    {

      "type": "vectorize",

      "name": "<VARIABLE_NAME>",

      "index_name": "<INDEX_NAME>"

    },

    {

      "type": "version_metadata",

      "name": "<VARIABLE_NAME>"

    }

  ]

}


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/workers/","name":"Workers"}},{"@type":"ListItem","position":3,"item":{"@id":"/workers/configuration/","name":"Configuration"}},{"@type":"ListItem","position":4,"item":{"@id":"/workers/configuration/multipart-upload-metadata/","name":"Multipart upload metadata"}}]}
```

---

---
title: API examples
description: REST API and TypeScript SDK examples for deploying Workers programmatically.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# API examples

The following examples show how to use Cloudflare's REST API and TypeScript SDK to deploy and manage Workers programmatically.

### Prerequisites

Before using these examples, you need:

* Your **Account ID** \- Found in the Cloudflare dashboard URL or API settings
* A **dispatch namespace** \- Created via the [dashboard](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/get-started/)
* An **API token** with Workers permissions - Create one at [API Tokens ↗](https://dash.cloudflare.com/profile/api-tokens)

For SDK examples, install the Cloudflare SDK:

Terminal window

```

npm install cloudflare


```

### Deploy a user Worker

Upload a Worker script to your dispatch namespace. This is the primary operation your platform performs when customers deploy code.

* [ REST API ](#tab-panel-4555)
* [ TypeScript SDK ](#tab-panel-4556)

Terminal window

```

# First, create the worker script file

cat > worker.mjs << 'EOF'

export default {

  async fetch(request, env, ctx) {

    return new Response("Hello from user Worker!");

  },

};

EOF


# Deploy using multipart form (required for ES modules)

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \

  -H "Authorization: Bearer $API_TOKEN" \

  -F 'metadata={"main_module": "worker.mjs"};type=application/json' \

  -F 'worker.mjs=@worker.mjs;type=application/javascript+module'


```

TypeScript

```

import Cloudflare from "cloudflare";


const client = new Cloudflare({

  apiToken: process.env.API_TOKEN,

});


async function deployUserWorker(

  accountId: string,

  namespace: string,

  scriptName: string,

  scriptContent: string,

) {

  const scriptFile = new File([scriptContent], `${scriptName}.mjs`, {

    type: "application/javascript+module",

  });


  const result =

    await client.workersForPlatforms.dispatch.namespaces.scripts.update(

      namespace,

      scriptName,

      {

        account_id: accountId,

        metadata: {

          main_module: `${scriptName}.mjs`,

        },

        files: [scriptFile],

      },

    );


  return result;

}


// Usage

await deployUserWorker(

  "your-account-id",

  "production",

  "customer-123",

  `export default {

  async fetch(request, env, ctx) {

    return new Response("Hello from customer 123!");

  },

};`,

);


```

### Deploy with bindings and tags

Use [bindings](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) to give each user Worker its own resources like a KV store or database. Use [tags](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/tags/) to organize Workers by customer ID, project ID, or plan type for bulk operations.

The following example shows how to deploy a Worker with its own KV namespace and tags attached:

* [ REST API ](#tab-panel-4557)
* [ TypeScript SDK ](#tab-panel-4558)

Terminal window

```

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \

  -H "Authorization: Bearer $API_TOKEN" \

  -F 'metadata={"main_module": "worker.mjs", "bindings": [{"type": "kv_namespace", "name": "MY_KV", "namespace_id": "your-kv-namespace-id"}], "tags": ["customer-123", "production", "pro-plan"], "compatibility_date": "2024-01-01"};type=application/json' \

  -F 'worker.mjs=@worker.mjs;type=application/javascript+module'


```

TypeScript

```

import Cloudflare from "cloudflare";


const client = new Cloudflare({

  apiToken: process.env.API_TOKEN,

});


async function deployWorkerWithBindingsAndTags(

  accountId: string,

  namespace: string,

  scriptName: string,

  scriptContent: string,

  kvNamespaceId: string,

  tags: string[],

) {

  const scriptFile = new File([scriptContent], `${scriptName}.mjs`, {

    type: "application/javascript+module",

  });


  const result =

    await client.workersForPlatforms.dispatch.namespaces.scripts.update(

      namespace,

      scriptName,

      {

        account_id: accountId,

        metadata: {

          main_module: `${scriptName}.mjs`,

          compatibility_date: "2024-01-01",

          bindings: [

            {

              type: "kv_namespace",

              name: "MY_KV",

              namespace_id: kvNamespaceId,

            },

          ],

          tags: tags, // e.g., ["customer-123", "production", "pro-plan"]

        },

        files: [scriptFile],

      },

    );


  return result;

}


// Usage

const scriptContent = `export default {

  async fetch(request, env, ctx) {

    const value = await env.MY_KV.get("key") || "default";

    return new Response(value);

  },

};`;


await deployWorkerWithBindingsAndTags(

  "your-account-id",

  "production",

  "customer-123-app",

  scriptContent,

  "kv-namespace-id",

  ["customer-123", "production", "pro-plan"],

);


```

For more information, refer to [Bindings](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) and [Tags](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/tags/).

### Deploy a Worker with static assets

Deploy a Worker that serves static files (HTML, CSS, JavaScript, images). This is a three-step process:

1. Create an upload session with a manifest of files
2. Upload the asset files
3. Deploy the Worker with the assets binding

For more details on static assets configuration and options, refer to [Static assets](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/static-assets/).

* [ REST API ](#tab-panel-4559)
* [ TypeScript SDK ](#tab-panel-4560)

**Step 1: Create upload session**

Terminal window

```

curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME/assets-upload-session" \

  -H "Authorization: Bearer $API_TOKEN" \

  -H "Content-Type: application/json" \

  -d '{

    "manifest": {

      "/index.html": {

        "hash": "<sha256-hash-first-16-bytes-hex>",

        "size": 1234

      },

      "/styles.css": {

        "hash": "<sha256-hash-first-16-bytes-hex>",

        "size": 567

      }

    }

  }'


```

The response includes a `jwt` token and `buckets` array indicating which files need uploading.

**Step 2: Upload assets**

Terminal window

```

curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/assets/upload?base64=true" \

  -H "Authorization: Bearer $JWT_FROM_STEP_1" \

  -F '<hash1>=<base64-encoded-content>' \

  -F '<hash2>=<base64-encoded-content>'


```

**Step 3: Deploy Worker with assets**

Terminal window

```

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \

  -H "Authorization: Bearer $API_TOKEN" \

  -F 'metadata={"main_module": "worker.mjs", "assets": {"jwt": "<completion-token>"}, "bindings": [{"type": "assets", "name": "ASSETS"}]};type=application/json' \

  -F 'worker.mjs=export default { async fetch(request, env) { return env.ASSETS.fetch(request); } };type=application/javascript+module'


```

TypeScript

```

interface AssetFile {

  path: string; // e.g., "/index.html"

  content: string; // base64 encoded content

  size: number; // file size in bytes

}


async function hashContent(base64Content: string): Promise<string> {

  const binaryString = atob(base64Content);

  const bytes = new Uint8Array(binaryString.length);

  for (let i = 0; i < binaryString.length; i++) {

    bytes[i] = binaryString.charCodeAt(i);

  }

  const hashBuffer = await crypto.subtle.digest("SHA-256", bytes);

  const hashArray = Array.from(new Uint8Array(hashBuffer));

  // Use first 16 bytes (32 hex chars) per API requirement

  return hashArray

    .slice(0, 16)

    .map((b) => b.toString(16).padStart(2, "0"))

    .join("");

}


async function deployWorkerWithAssets(

  accountId: string,

  namespace: string,

  scriptName: string,

  assets: AssetFile[],

) {

  const apiToken = process.env.API_TOKEN;

  const baseUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers`;


  // Step 1: Build manifest

  const manifest: Record<string, { hash: string; size: number }> = {};

  const hashToAsset = new Map<string, AssetFile>();


  for (const asset of assets) {

    const hash = await hashContent(asset.content);

    const path = asset.path.startsWith("/") ? asset.path : "/" + asset.path;

    manifest[path] = { hash, size: asset.size };

    hashToAsset.set(hash, asset);

  }


  // Step 2: Create upload session

  const sessionResponse = await fetch(

    `${baseUrl}/dispatch/namespaces/${namespace}/scripts/${scriptName}/assets-upload-session`,

    {

      method: "POST",

      headers: {

        Authorization: `Bearer ${apiToken}`,

        "Content-Type": "application/json",

      },

      body: JSON.stringify({ manifest }),

    },

  );


  const sessionData = (await sessionResponse.json()) as {

    success: boolean;

    result?: { jwt: string; buckets?: string[][] };

  };


  if (!sessionData.success || !sessionData.result) {

    throw new Error("Failed to create upload session");

  }


  let completionToken = sessionData.result.jwt;

  const buckets = sessionData.result.buckets;


  // Step 3: Upload assets in buckets

  if (buckets && buckets.length > 0) {

    for (const bucket of buckets) {

      const formData = new FormData();

      for (const hash of bucket) {

        const asset = hashToAsset.get(hash);

        if (asset) {

          formData.append(hash, asset.content);

        }

      }


      const uploadResponse = await fetch(

        `${baseUrl}/assets/upload?base64=true`,

        {

          method: "POST",

          headers: { Authorization: `Bearer ${completionToken}` },

          body: formData,

        },

      );


      const uploadData = (await uploadResponse.json()) as {

        success: boolean;

        result?: { jwt?: string };

      };


      if (uploadData.result?.jwt) {

        completionToken = uploadData.result.jwt;

      }

    }

  }


  // Step 4: Deploy worker with assets binding

  const workerCode = `

export default {

  async fetch(request, env) {

    return env.ASSETS.fetch(request);

  }

};`;


  const deployFormData = new FormData();

  const metadata = {

    main_module: `${scriptName}.mjs`,

    assets: { jwt: completionToken },

    bindings: [{ type: "assets", name: "ASSETS" }],

  };


  deployFormData.append(

    "metadata",

    new Blob([JSON.stringify(metadata)], { type: "application/json" }),

  );

  deployFormData.append(

    `${scriptName}.mjs`,

    new Blob([workerCode], { type: "application/javascript+module" }),

  );


  const deployResponse = await fetch(

    `${baseUrl}/dispatch/namespaces/${namespace}/scripts/${scriptName}`,

    {

      method: "PUT",

      headers: { Authorization: `Bearer ${apiToken}` },

      body: deployFormData,

    },

  );


  return deployResponse.json();

}


// Usage

await deployWorkerWithAssets("your-account-id", "production", "customer-site", [

  {

    path: "/index.html",

    content: btoa("<html><body>Hello World</body></html>"),

    size: 37,

  },

  {

    path: "/styles.css",

    content: btoa("body { font-family: sans-serif; }"),

    size: 33,

  },

]);


```

### List Workers in a namespace

Retrieve all user Workers deployed to a namespace.

* [ REST API ](#tab-panel-4561)
* [ TypeScript SDK ](#tab-panel-4562)

Terminal window

```

curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts" \

  -H "Authorization: Bearer $API_TOKEN"


```

TypeScript

```

async function listWorkers(accountId: string, namespace: string) {

  const response = await fetch(

    `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/dispatch/namespaces/${namespace}/scripts`,

    {

      headers: {

        Authorization: `Bearer ${process.env.API_TOKEN}`,

      },

    },

  );


  const data = (await response.json()) as {

    success: boolean;

    result: Array<{ id: string; tags?: string[] }>;

  };


  return data.result;

}


// Usage

const workers = await listWorkers("your-account-id", "production");

console.log(workers);


```

### Delete Workers by tag

Delete all Workers matching a tag filter. This is useful when a customer deletes their account and you need to remove all their Workers at once.

* [ REST API ](#tab-panel-4563)
* [ TypeScript SDK ](#tab-panel-4564)

Delete all Workers tagged with `customer-123`:

Terminal window

```

curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts?tags=customer-123:yes" \

  -H "Authorization: Bearer $API_TOKEN"


```

TypeScript

```

async function deleteWorkersByTag(

  accountId: string,

  namespace: string,

  tag: string,

) {

  const response = await fetch(

    `https://api.cloudflare.com/client/v4/accounts/${accountId}/workers/dispatch/namespaces/${namespace}/scripts?tags=${tag}:yes`,

    {

      method: "DELETE",

      headers: {

        Authorization: `Bearer ${process.env.API_TOKEN}`,

      },

    },

  );


  return response.json();

}


// Usage: Delete all Workers for a customer

await deleteWorkersByTag("your-account-id", "production", "customer-123");


```

### Delete a single Worker

Delete a specific Worker by name.

* [ REST API ](#tab-panel-4565)
* [ TypeScript SDK ](#tab-panel-4566)

Terminal window

```

curl -X DELETE "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces/$NAMESPACE_NAME/scripts/$SCRIPT_NAME" \

  -H "Authorization: Bearer $API_TOKEN"


```

TypeScript

```

import Cloudflare from "cloudflare";


const client = new Cloudflare({

  apiToken: process.env.API_TOKEN,

});


async function deleteWorker(

  accountId: string,

  namespace: string,

  scriptName: string,

) {

  const result =

    await client.workersForPlatforms.dispatch.namespaces.scripts.delete(

      namespace,

      scriptName,

      { account_id: accountId },

    );


  return result;

}


// Usage

await deleteWorker("your-account-id", "production", "customer-123");


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/platform-examples/","name":"API examples"}}]}
```

---

---
title: Pricing
description: Review Workers for Platforms pricing for requests, CPU time, and scripts, including usage allotments and overage costs.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Pricing

The Workers for Platforms Paid plan is **$25 monthly**. Workers for Platforms can be purchased through the [Cloudflare dashboard ↗](https://dash.cloudflare.com/?to=/:account/workers-for-platforms).

Workers for Platforms comes with the following usage allotments and overage pricing.

| Requests1 2                                                           | Duration                        | CPU time2                                                                                                                                                                                                                                                                                                                                                                             | Scripts                                   |
| --------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| 20 million requests included per month  +$0.30 per additional million | No charge or limit for duration | 60 million CPU milliseconds included per month +$0.02 per additional million CPU milliseconds Max of 30 seconds of CPU time per invocation  Max of 15 minutes of CPU time per [Cron Trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) or [Queue Consumer](https://developers.cloudflare.com/queues/configuration/javascript-apis/#consumer) invocation | 1000 scripts +$0.02 per additional script |

1 Inbound requests to your Worker. Cloudflare does not bill for [subrequests](https://developers.cloudflare.com/workers/platform/limits/#subrequests) you make from your Worker.   
2 Workers for Platforms only charges for 1 request across the chain of [dispatch Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/#dynamic-dispatch-worker) \-> [user Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/how-workers-for-platforms-works/#user-workers) \-> [outbound Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/outbound-workers/). CPU time is charged across these Workers.

## Example pricing:

A Workers for Platforms project that serves 100 million requests per month, uses an average of 10 milliseconds (ms) of CPU time per request and uses 1200 scripts would have the following estimated costs:

| Monthly Costs    | Formula |                                                                                                             |
| ---------------- | ------- | ----------------------------------------------------------------------------------------------------------- |
| **Subscription** | $25.00  |                                                                                                             |
| **Requests**     | $24.00  | (100,000,000 requests - 20,000,000 included requests) / 1,000,000 \* $0.30                                  |
| **CPU time**     | $18.80  | ((10 ms of CPU time per request \* 100,000,000 requests) - 60,000,000 included CPU ms) / 1,000,000 \* $0.02 |
| **Scripts**      | $4.00   | (1200 scripts - 1000 included scripts) \* $0.02                                                             |
| **Total**        | $71.80  |                                                                                                             |

Custom limits

Set [custom limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/) for user Workers to get control over your Cloudflare bill, prevent accidental runaway bills or denial-of-wallet attacks. Configure the maximum amount of CPU time that can be used per invocation by [defining custom limits in your dispatch Worker](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/#set-custom-limits).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/pricing/","name":"Pricing"}}]}
```

---

---
title: Worker Isolation
description: Choose between untrusted and trusted isolation modes for user Workers in a Workers for Platforms dispatch namespace.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Worker Isolation

### Untrusted Mode (Default)

By default, Workers inside of a dispatch namespace are considered "untrusted." This provides the strongest isolation between Workers and is best in cases where your customers have control over the code that's being deployed.

In untrusted mode:

* The [request.cf](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) object is not available in Workers (see [limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/limits/#cf-object) for more information)
* Each Worker has an isolated cache, when using the [Cache API](https://developers.cloudflare.com/workers/runtime-apis/cache/) or when making subrequests using `fetch()`, which egress via [Cloudflare's cache](https://developers.cloudflare.com/cache/)
* [caches.default](https://developers.cloudflare.com/workers/reference/how-the-cache-works/#cache-api) is disabled for all Workers in the namespace

This mode ensures complete isolation between customer Workers, preventing any potential cross-tenant data access.

### Trusted Mode

If you control the Worker code and want to disable isolation mode, you can configure the namespace as "trusted". This is useful when building internal platforms where your company controls all Worker code.

In trusted mode:

* The [request.cf](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) object becomes available, providing access to request metadata
* All Workers in the namespace share the same cache space when using the Cache API

Note

In trusted mode, Workers can potentially access cached responses from other Workers in the namespace. Only enable this if you control all Worker code or have appropriate cache key isolation strategies.

To convert a namespace from untrusted to trusted:

Terminal window

```

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/dispatch/namespaces/{namespace_name}" \

  -H "Authorization: Bearer {api_token}" \

  -H "Content-Type: application/json" \

  -d '{

    "name": "{namespace_name}",

    "trusted_workers": true

  }'


```

If you enable trusted mode for a namespace that already has deployed Workers, you'll need to redeploy those Workers for the `request.cf` object to become available. Any new Workers you deploy after enabling trusted mode will automatically have access to it.

### Maintaining cache isolation in trusted mode

If you need access to `request.cf` but want to maintain cache isolation between customers, use customer-specific [cache keys](https://developers.cloudflare.com/workers/examples/cache-using-fetch/#custom-cache-keys) or the [Cache API](https://developers.cloudflare.com/workers/examples/cache-api/) with isolated keys.

## Related Resources

* [Platform Limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/limits) \- Understanding script and API limits
* [Cache API Documentation](https://developers.cloudflare.com/workers/runtime-apis/cache/) \- Learn about cache behavior in Workers
* [Request cf object](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestcf) \- Details on the cf object properties

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/","name":"Workers for Platforms"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/workers-for-platforms/reference/worker-isolation/","name":"Worker Isolation"}}]}
```

---

## List dispatch namespaces

**get** `/accounts/{account_id}/workers/dispatch/namespaces`

Fetch a list of Workers for Platforms namespaces.

### Path Parameters

- `account_id: string`

  Identifier.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional array of object { created_by, created_on, modified_by, 5 more }`

  - `created_by: optional string`

    Identifier.

  - `created_on: optional string`

    When the script was created.

  - `modified_by: optional string`

    Identifier.

  - `modified_on: optional string`

    When the script was last modified.

  - `namespace_id: optional string`

    API Resource UUID tag.

  - `namespace_name: optional string`

    Name of the Workers for Platforms dispatch namespace.

  - `script_count: optional number`

    The current number of scripts in this Dispatch Namespace.

  - `trusted_workers: optional boolean`

    Whether the Workers in the namespace are executed in a "trusted" manner. When a Worker is trusted, it has access to the shared caches for the zone in the Cache API, and has access to the `request.cf` object on incoming Requests. When a Worker is untrusted, caches are not shared across the zone, and `request.cf` is undefined. By default, Workers in a namespace are "untrusted".

### Example

```http
curl https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/dispatch/namespaces \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": [
    {
      "created_by": "023e105f4ecef8ad9ca31a8372d0c353",
      "created_on": "2017-01-01T00:00:00Z",
      "modified_by": "023e105f4ecef8ad9ca31a8372d0c353",
      "modified_on": "2017-01-01T00:00:00Z",
      "namespace_id": "f174e90a-fafe-4643-bbbc-4a0ed4fc8415",
      "namespace_name": "my-dispatch-namespace",
      "script_count": 800,
      "trusted_workers": false
    }
  ]
}
```

---

---
title: Cloudflare for SaaS
description: Extend Cloudflare security and performance to your customers' custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare for SaaS

Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare's network to your customers via their own custom or vanity domains.

  
As a SaaS provider, you may want to support subdomains under your own zone in addition to letting your customers use their own domain names with your services. For example, a customer may want to use their vanity domain `app.customer.com` to point to an application hosted on your Cloudflare zone `service.saas.com`. Cloudflare for SaaS allows you to increase security, performance, and reliability of your customers' domains.

Note

Eligible 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.

## Benefits

When you use Cloudflare for SaaS, it helps you to:

* Provide custom domain support.
* Keep your customers' traffic encrypted.
* Keep your customers online.
* Facilitate fast load times of your customers' domains.
* Gain insight through traffic analytics.

## Limitations

If your customers already have their applications on Cloudflare, they cannot control some Cloudflare features for hostnames managed by your Custom Hostnames configuration, including:

* Argo
* Early Hints
* Client-side security (formerly known as Page Shield)
* Spectrum
* Wildcard DNS

## How it works

As the SaaS provider, you can extend Cloudflare's products to customer-owned custom domains by adding them to your zone [as custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/). Through a suite of easy-to-use products, Cloudflare for SaaS routes traffic from custom hostnames to an origin, set up on your domain. Cloudflare for SaaS is highly customizable. Three possible configurations are shown below.

### Standard Cloudflare for SaaS configuration:

Custom hostnames are routed to a default origin server called fallback origin. This configuration is available on all plans.

![Standard case](https://developers.cloudflare.com/_astro/Standard.DlPYrpsG_Z1aQodp.webp) 

### Cloudflare for SaaS with Apex Proxying:

This allows you to support apex domains even if your customers are using a DNS provider that does not allow a CNAME at the apex. This is available as an add-on for Enterprise plans. For more details, refer to [Apex Proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/).

![Advanced case](https://developers.cloudflare.com/_astro/Advanced.BaQXgT8v_Z1DP3hz.webp) 

### Cloudflare for SaaS with BYOIP:

This allows you to support apex domains even if your customers are using a DNS provider that does not allow a CNAME at the apex. Also, you can point to your own IPs if you want to bring an IP range to Cloudflare (instead of Cloudflare provided IPs). This is available as an add-on for Enterprise plans.

![Pro Case](https://developers.cloudflare.com/_astro/Pro.DTAC_nZK_Z23M1FF.webp) 

## Availability

Cloudflare for SaaS is bundled with non-Enterprise plans and available as an add-on for Enterprise plans. For more details, refer to [Plans](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

## Next steps

[ Get started ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) [ Learn more ](https://blog.cloudflare.com/introducing-ssl-for-saas/) 

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}}]}
```

---

## List Custom Hostnames

**get** `/zones/{zone_id}/custom_hostnames`

List, search, sort, and filter all of your custom hostnames.

### Path Parameters

- `zone_id: string`

  Identifier.

### Query Parameters

- `id: optional string`

  Hostname ID to match against. This ID was generated and returned during the initial custom_hostname creation. This parameter cannot be used with the 'hostname' parameter.

- `certificate_authority: optional "google" or "lets_encrypt" or "ssl_com"`

  Filter by the certificate authority that issued the SSL certificate.

  - `"google"`

  - `"lets_encrypt"`

  - `"ssl_com"`

- `custom_origin_server: optional string`

  Filter by custom origin server name.

- `direction: optional "asc" or "desc"`

  Direction to order hostnames.

  - `"asc"`

  - `"desc"`

- `hostname: optional object { contain }`

  - `contain: optional string`

    Filters hostnames by a substring match on the hostname value. This parameter cannot be used with the 'id' parameter.

- `hostname_status: optional "active" or "pending" or "active_redeploying" or 13 more`

  Filter by the hostname's activation status.

  - `"active"`

  - `"pending"`

  - `"active_redeploying"`

  - `"moved"`

  - `"pending_deletion"`

  - `"deleted"`

  - `"pending_blocked"`

  - `"pending_migration"`

  - `"pending_provisioned"`

  - `"test_pending"`

  - `"test_active"`

  - `"test_active_apex"`

  - `"test_blocked"`

  - `"test_failed"`

  - `"provisioned"`

  - `"blocked"`

- `order: optional "ssl" or "ssl_status"`

  Field to order hostnames by.

  - `"ssl"`

  - `"ssl_status"`

- `page: optional number`

  Page number of paginated results.

- `per_page: optional number`

  Number of hostnames per page.

- `ssl: optional 0 or 1`

  Whether to filter hostnames based on if they have SSL enabled.

  - `0`

  - `1`

- `ssl_status: optional "initializing" or "pending_validation" or "deleted" or 18 more`

  Filter by SSL certificate status.

  - `"initializing"`

  - `"pending_validation"`

  - `"deleted"`

  - `"pending_issuance"`

  - `"pending_deployment"`

  - `"pending_deletion"`

  - `"pending_expiration"`

  - `"expired"`

  - `"active"`

  - `"initializing_timed_out"`

  - `"validation_timed_out"`

  - `"issuance_timed_out"`

  - `"deployment_timed_out"`

  - `"deletion_timed_out"`

  - `"pending_cleanup"`

  - `"staging_deployment"`

  - `"staging_active"`

  - `"deactivating"`

  - `"inactive"`

  - `"backup_issued"`

  - `"holding_deployment"`

- `wildcard: optional boolean`

  Filter by whether the custom hostname is a wildcard hostname.

### Returns

- `errors: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `messages: array of object { code, message, documentation_url, source }`

  - `code: number`

  - `message: string`

  - `documentation_url: optional string`

  - `source: optional object { pointer }`

    - `pointer: optional string`

- `success: true`

  Whether the API call was successful.

  - `true`

- `result: optional array of object { id, hostname, created_at, 8 more }`

  - `id: string`

    Identifier.

  - `hostname: string`

    The custom hostname that will point to your hostname via CNAME.

  - `created_at: optional string`

    This is the time the hostname was created.

  - `custom_metadata: optional map[string]`

    Unique key/value metadata for this hostname. These are per-hostname (customer) settings.

  - `custom_origin_server: optional string`

    a valid hostname that’s been added to your DNS zone as an A, AAAA, or CNAME record.

  - `custom_origin_sni: optional string`

    A hostname that will be sent to your custom origin server as SNI for TLS handshake. This can be a valid subdomain of the zone or custom origin server name or the string ':request_host_header:' which will cause the host header in the request to be used as SNI. Not configurable with default/fallback origin server.

  - `ownership_verification: optional object { name, type, value }`

    This is a record which can be placed to activate a hostname.

    - `name: optional string`

      DNS Name for record.

    - `type: optional "txt"`

      DNS Record type.

      - `"txt"`

    - `value: optional string`

      Content for the record.

  - `ownership_verification_http: optional object { http_body, http_url }`

    This presents the token to be served by the given http url to activate a hostname.

    - `http_body: optional string`

      Token to be served.

    - `http_url: optional string`

      The HTTP URL that will be checked during custom hostname verification and where the customer should host the token.

  - `ssl: optional object { id, bundle_method, certificate_authority, 17 more }`

    - `id: optional string`

      Custom hostname SSL identifier tag.

    - `bundle_method: optional BundleMethod`

      A ubiquitous bundle has the highest probability of being verified everywhere, even by clients using outdated or unusual trust stores. An optimal bundle uses the shortest chain and newest intermediates. And the force bundle verifies the chain, but does not otherwise modify it.

      - `"ubiquitous"`

      - `"optimal"`

      - `"force"`

    - `certificate_authority: optional CertificateCA`

      The Certificate Authority that will issue the certificate

      - `"digicert"`

      - `"google"`

      - `"lets_encrypt"`

      - `"ssl_com"`

    - `custom_certificate: optional string`

      If a custom uploaded certificate is used.

    - `custom_csr_id: optional string`

      The identifier for the Custom CSR that was used.

    - `custom_key: optional string`

      The key for a custom uploaded certificate.

    - `dcv_delegation_records: optional array of object { cname, cname_target, emails, 5 more }`

      DCV Delegation records for domain validation.

      - `cname: optional string`

        The CNAME record hostname for DCV delegation.

      - `cname_target: optional string`

        The CNAME record target value for DCV delegation.

      - `emails: optional array of string`

        The set of email addresses that the certificate authority (CA) will use to complete domain validation.

      - `http_body: optional string`

        The content that the certificate authority (CA) will expect to find at the http_url during the domain validation.

      - `http_url: optional string`

        The url that will be checked during domain validation.

      - `status: optional string`

        Status of the validation record.

      - `txt_name: optional string`

        The hostname that the certificate authority (CA) will check for a TXT record during domain validation .

      - `txt_value: optional string`

        The TXT record that the certificate authority (CA) will check during domain validation.

    - `expires_on: optional string`

      The time the custom certificate expires on.

    - `hosts: optional array of string`

      A list of Hostnames on a custom uploaded certificate.

    - `issuer: optional string`

      The issuer on a custom uploaded certificate.

    - `method: optional DCVMethod`

      Domain control validation (DCV) method used for this hostname.

      - `"http"`

      - `"txt"`

      - `"email"`

    - `serial_number: optional string`

      The serial number on a custom uploaded certificate.

    - `settings: optional object { ciphers, early_hints, http2, 2 more }`

      - `ciphers: optional array of string`

        An allowlist of ciphers for TLS termination. These ciphers must be in the BoringSSL format.

      - `early_hints: optional "on" or "off"`

        Whether or not Early Hints is enabled.

        - `"on"`

        - `"off"`

      - `http2: optional "on" or "off"`

        Whether or not HTTP2 is enabled.

        - `"on"`

        - `"off"`

      - `min_tls_version: optional "1.0" or "1.1" or "1.2" or "1.3"`

        The minimum TLS version supported.

        - `"1.0"`

        - `"1.1"`

        - `"1.2"`

        - `"1.3"`

      - `tls_1_3: optional "on" or "off"`

        Whether or not TLS 1.3 is enabled.

        - `"on"`

        - `"off"`

    - `signature: optional string`

      The signature on a custom uploaded certificate.

    - `status: optional "initializing" or "pending_validation" or "deleted" or 18 more`

      Status of the hostname's SSL certificates.

      - `"initializing"`

      - `"pending_validation"`

      - `"deleted"`

      - `"pending_issuance"`

      - `"pending_deployment"`

      - `"pending_deletion"`

      - `"pending_expiration"`

      - `"expired"`

      - `"active"`

      - `"initializing_timed_out"`

      - `"validation_timed_out"`

      - `"issuance_timed_out"`

      - `"deployment_timed_out"`

      - `"deletion_timed_out"`

      - `"pending_cleanup"`

      - `"staging_deployment"`

      - `"staging_active"`

      - `"deactivating"`

      - `"inactive"`

      - `"backup_issued"`

      - `"holding_deployment"`

    - `type: optional DomainValidationType`

      Level of validation to be used for this hostname. Domain validation (dv) must be used.

      - `"dv"`

    - `uploaded_on: optional string`

      The time the custom certificate was uploaded.

    - `validation_errors: optional array of object { message }`

      Domain validation errors that have been received by the certificate authority (CA).

      - `message: optional string`

        A domain validation error.

    - `validation_records: optional array of object { cname, cname_target, emails, 5 more }`

      - `cname: optional string`

        The CNAME record hostname for DCV delegation.

      - `cname_target: optional string`

        The CNAME record target value for DCV delegation.

      - `emails: optional array of string`

        The set of email addresses that the certificate authority (CA) will use to complete domain validation.

      - `http_body: optional string`

        The content that the certificate authority (CA) will expect to find at the http_url during the domain validation.

      - `http_url: optional string`

        The url that will be checked during domain validation.

      - `status: optional string`

        Status of the validation record.

      - `txt_name: optional string`

        The hostname that the certificate authority (CA) will check for a TXT record during domain validation .

      - `txt_value: optional string`

        The TXT record that the certificate authority (CA) will check during domain validation.

    - `wildcard: optional boolean`

      Indicates whether the certificate covers a wildcard.

  - `status: optional "active" or "pending" or "active_redeploying" or 13 more`

    Status of the hostname's activation.

    - `"active"`

    - `"pending"`

    - `"active_redeploying"`

    - `"moved"`

    - `"pending_deletion"`

    - `"deleted"`

    - `"pending_blocked"`

    - `"pending_migration"`

    - `"pending_provisioned"`

    - `"test_pending"`

    - `"test_active"`

    - `"test_active_apex"`

    - `"test_blocked"`

    - `"test_failed"`

    - `"provisioned"`

    - `"blocked"`

  - `verification_errors: optional array of string`

    These are errors that were encountered while trying to activate a hostname.

- `result_info: optional object { count, page, per_page, 2 more }`

  - `count: optional number`

    Total number of results for the requested service.

  - `page: optional number`

    Current page within paginated list of results.

  - `per_page: optional number`

    Number of results per page of results.

  - `total_count: optional number`

    Total results available without any search parameters.

  - `total_pages: optional number`

    The number of total pages in the entire result set.

### Example

```http
curl https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames \
    -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
```

#### Response

```json
{
  "errors": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "messages": [
    {
      "code": 1000,
      "message": "message",
      "documentation_url": "documentation_url",
      "source": {
        "pointer": "pointer"
      }
    }
  ],
  "success": true,
  "result": [
    {
      "id": "023e105f4ecef8ad9ca31a8372d0c353",
      "hostname": "app.example.com",
      "created_at": "2020-02-06T18:11:23.531995Z",
      "custom_metadata": {
        "foo": "string"
      },
      "custom_origin_server": "origin2.example.com",
      "custom_origin_sni": "sni.example.com",
      "ownership_verification": {
        "name": "_cf-custom-hostname.app.example.com",
        "type": "txt",
        "value": "5cc07c04-ea62-4a5a-95f0-419334a875a4"
      },
      "ownership_verification_http": {
        "http_body": "5cc07c04-ea62-4a5a-95f0-419334a875a4",
        "http_url": "http://custom.test.com/.well-known/cf-custom-hostname-challenge/0d89c70d-ad9f-4843-b99f-6cc0252067e9"
      },
      "ssl": {
        "id": "0d89c70d-ad9f-4843-b99f-6cc0252067e9",
        "bundle_method": "ubiquitous",
        "certificate_authority": "google",
        "custom_certificate": "-----BEGIN CERTIFICATE-----\nMIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBN\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E...SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/O\nOeH8gMJ+FuwtXYEPa4hBf38M5eU5xWG7\n-----END CERTIFICATE-----\n",
        "custom_csr_id": "7b163417-1d2b-4c84-a38a-2fb7a0cd7752",
        "custom_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAwQHoetcl9+5ikGzV6cMzWtWPJHqXT3wpbEkRU9Yz7lgvddmG\ndtcGbg/1CGZu0jJGkMoppoUo4c3dts3iwqRYmBikUP77wwY2QGmDZw2FvkJCJlKn\nabIRuGvBKwzESIXgKk2016aTP6/dAjEHyo6SeoK8lkIySUvK0fyOVlsiEsCmOpid\ntnKX/a+50GjB79CJH4ER2lLVZnhePFR/zUOyPxZQQ4naHf7yu/b5jhO0f8fwt+py\nFxIXjbEIdZliWRkRMtzrHOJIhrmJ2A1J7iOrirbbwillwjjNVUWPf3IJ3M12S9pE\newooaeO2izNTERcG9HzAacbVRn2Y2SWIyT/18QIDAQABAoIBACbhTYXBZYKmYPCb\nHBR1IBlCQA2nLGf0qRuJNJZg5iEzXows/6tc8YymZkQE7nolapWsQ+upk2y5Xdp/\naxiuprIs9JzkYK8Ox0r+dlwCG1kSW+UAbX0bQ/qUqlsTvU6muVuMP8vZYHxJ3wmb\n+ufRBKztPTQ/rYWaYQcgC0RWI20HTFBMxlTAyNxYNWzX7RKFkGVVyB9RsAtmcc8g\n+j4OdosbfNoJPS0HeIfNpAznDfHKdxDk2Yc1tV6RHBrC1ynyLE9+TaflIAdo2MVv\nKLMLq51GqYKtgJFIlBRPQqKoyXdz3fGvXrTkf/WY9QNq0J1Vk5ERePZ54mN8iZB7\n9lwy/AkCgYEA6FXzosxswaJ2wQLeoYc7ceaweX/SwTvxHgXzRyJIIT0eJWgx13Wo\n/WA3Iziimsjf6qE+SI/8laxPp2A86VMaIt3Z3mJN/CqSVGw8LK2AQst+OwdPyDMu\niacE8lj/IFGC8mwNUAb9CzGU3JpU4PxxGFjS/eMtGeRXCWkK4NE+G08CgYEA1Kp9\nN2JrVlqUz+gAX+LPmE9OEMAS9WQSQsfCHGogIFDGGcNf7+uwBM7GAaSJIP01zcoe\nVAgWdzXCv3FLhsaZoJ6RyLOLay5phbu1iaTr4UNYm5WtYTzMzqh8l1+MFFDl9xDB\nvULuCIIrglM5MeS/qnSg1uMoH2oVPj9TVst/ir8CgYEAxrI7Ws9Zc4Bt70N1As+U\nlySjaEVZCMkqvHJ6TCuVZFfQoE0r0whdLdRLU2PsLFP+q7qaeZQqgBaNSKeVcDYR\n9B+nY/jOmQoPewPVsp/vQTCnE/R81spu0mp0YI6cIheT1Z9zAy322svcc43JaWB7\nmEbeqyLOP4Z4qSOcmghZBSECgYACvR9Xs0DGn+wCsW4vze/2ei77MD4OQvepPIFX\ndFZtlBy5ADcgE9z0cuVB6CiL8DbdK5kwY9pGNr8HUCI03iHkW6Zs+0L0YmihfEVe\nPG19PSzK9CaDdhD9KFZSbLyVFmWfxOt50H7YRTTiPMgjyFpfi5j2q348yVT0tEQS\nfhRqaQKBgAcWPokmJ7EbYQGeMbS7HC8eWO/RyamlnSffdCdSc7ue3zdVJxpAkQ8W\nqu80pEIF6raIQfAf8MXiiZ7auFOSnHQTXUbhCpvDLKi0Mwq3G8Pl07l+2s6dQG6T\nlv6XTQaMyf6n1yjzL+fzDrH3qXMxHMO/b13EePXpDMpY7HQpoLDi\n-----END RSA PRIVATE KEY-----\n",
        "dcv_delegation_records": [
          {
            "cname": "_acme-challenge.example.com",
            "cname_target": "dcv.cloudflare.com",
            "emails": [
              "administrator@example.com",
              "webmaster@example.com"
            ],
            "http_body": "ca3-574923932a82475cb8592200f1a2a23d",
            "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt",
            "status": "pending",
            "txt_name": "_acme-challenge.app.example.com",
            "txt_value": "810b7d5f01154524b961ba0cd578acc2"
          }
        ],
        "expires_on": "2021-02-06T18:11:23.531995Z",
        "hosts": [
          "app.example.com",
          "*.app.example.com"
        ],
        "issuer": "DigiCertInc",
        "method": "http",
        "serial_number": "6743787633689793699141714808227354901",
        "settings": {
          "ciphers": [
            "ECDHE-RSA-AES128-GCM-SHA256",
            "AES128-SHA"
          ],
          "early_hints": "on",
          "http2": "on",
          "min_tls_version": "1.2",
          "tls_1_3": "on"
        },
        "signature": "SHA256WithRSA",
        "status": "pending_validation",
        "type": "dv",
        "uploaded_on": "2020-02-06T18:11:23.531995Z",
        "validation_errors": [
          {
            "message": "SERVFAIL looking up CAA for app.example.com"
          }
        ],
        "validation_records": [
          {
            "cname": "_acme-challenge.example.com",
            "cname_target": "dcv.cloudflare.com",
            "emails": [
              "administrator@example.com",
              "webmaster@example.com"
            ],
            "http_body": "ca3-574923932a82475cb8592200f1a2a23d",
            "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt",
            "status": "pending",
            "txt_name": "_acme-challenge.app.example.com",
            "txt_value": "810b7d5f01154524b961ba0cd578acc2"
          }
        ],
        "wildcard": false
      },
      "status": "pending",
      "verification_errors": [
        "None of the A or AAAA records are owned by this account and the pre-generated ownership verification token was not found."
      ]
    }
  ],
  "result_info": {
    "count": 1,
    "page": 1,
    "per_page": 20,
    "total_count": 2000,
    "total_pages": 100
  }
}
```

---

---
title: Extend Cloudflare's benefits to SaaS providers' end-customers
description: Learn how to use Cloudflare to extend performance, security, and data localization to your end users.
image: https://developers.cloudflare.com/core-services-preview.png
---

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

[Skip to content](#%5Ftop) 

# Extend Cloudflare's benefits to SaaS providers' end-customers

**Last reviewed:**  over 1 year ago 

## Introduction

A key aspect of developing a Software-as-a-service (SaaS) application is ensuring its security against the wide array of potential attacks it faces on the Internet. Cloudflare's network and security services can be used to protect your customers using your SaaS application, off-loading the risk to a vendor with experience in [protecting applications ↗](https://radar.cloudflare.com/reports/ddos).

This design guide illustrates how providers, building and hosting their own product/application offering, can leverage Cloudflare to extend the security, performance, and compliance benefits of Cloudflare's network to their end-customers.

The following diagrams visualize the use of the following services:

* Data Localization Suite (specifically, [Regional Services](https://developers.cloudflare.com/data-localization/regional-services/))
* [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/)
* [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/) to securely expose web applications (with [public hostnames](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/) and [private networks](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/))
* Load Balancers to manage traffic and ensure reliability and performance, implementing Global Traffic Management (GTM) and [Private Network Load Balancing](https://developers.cloudflare.com/load-balancing/private-network/).

This setup is ideal for SaaS providers who need to ensure minimal downtime, auto-renewal of SSL/TLS certificates, efficiently distribute traffic to healthy endpoints, and regional traffic management for compliance and performance optimization.

This document assumes that the provider's application DNS is registered and managed through Cloudflare as the primary and authoritative DNS provider. You can find details on how to set this up in the [Cloudflare DNS Zone Setup Guide](https://developers.cloudflare.com/dns/zone-setups/full-setup/).

This solution supports subdomains under your own zone while also allowing your customers to use their own domain names (vanity or custom domains) with your services. For example, for each customer you may create the custom hostname `mycustomer.myappexample.com` but also want to allow them to use their own domain, `app.mycustomerexample.com` to point to their tenant on your service. Each subdomain (`mycustomer.myappexample.com`) can be created on the main domain (`myappexample.com`) through the [Cloudflare API](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records), allowing you to easily automate the creation of DNS records when your customers create an account on your service.

## Benefits

Before looking at how Cloudflare can be configured to protect your SaaS application through your custom hostnames, it's worth reviewing the benefits of taking this approach.

| Benefit                  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Minimized Downtime       | Ensure [minimal downtime](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/#minimize-downtime) not only during custom hostname migrations to Cloudflare for SaaS but also throughout the entire lifecycle of the application.                                                                                                                                                                                                                                                     |
| Security and Performance | Extends Cloudflare's [security](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/) and [performance](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/) benefits to end-customers through their custom domains.                                                                                                                                                                                                                                                                            |
| Auto-Renewal             | Automates the [renewal](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/renew-certificates/) and management process for custom hostname certificates.                                                                                                                                                                                                                                                                                                                                                  |
| Apex Proxying            | Supports end-customers using [domain apex](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/#apex-proxying) (otherwise known as root domain) as custom hostnames. Used where your DNS service doesn't allow [CNAMEs for root domains](https://developers.cloudflare.com/dns/cname-flattening/), instead a [static IP](https://developers.cloudflare.com/byoip/address-maps/#static-ips-or-byoip) is used to allow an A record to be used.                                                           |
| Smart Load Balancing     | Use the load balancer as [custom origins](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/) to steer traffic with [session affinity](https://developers.cloudflare.com/load-balancing/understand-basics/session-affinity/). In the context of Cloudflare for SaaS, a custom origin lets you send traffic from one or more custom hostnames to somewhere besides your default proxy fallback origin.                                                                                                                 |
| O2O                      | For end-customers who already proxy traffic through Cloudflare, [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) may be required. Generally, it's recommended for those end-customers to [not proxy](https://developers.cloudflare.com/dns/proxy-status/#dns-only-records) the hostnames used by the SaaS provider. If O2O functionality is required, please review the [product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/). |
| Regional Services        | Allows [regional traffic management](https://developers.cloudflare.com/data-localization/regional-services/) to comply with data localization requirements.                                                                                                                                                                                                                                                                                                                                                                                                                              |

## Products included in this guide

The following products are used to deliver this solution.

| Product                                                                                                                           | Function                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/)                            | Extends the security and performance benefits of Cloudflare’s network to your customers through their own custom or vanity domains. This includes [Certificate Management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/), [WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/), [Early Hints for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/early-hints-for-saas/) and [Cache for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/cache-for-saas/). |
| [DDoS Protection](https://developers.cloudflare.com/ddos-protection/)                                                             | Volumetric attack protection is automatically enabled for [proxied](https://developers.cloudflare.com/dns/proxy-status/) hostnames.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| [Regional Services](https://developers.cloudflare.com/data-localization/regional-services/) (part of the Data Localization Suite) | Restrict inspection of data (processing) to only those data centers within jurisdictional boundaries.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| [Load Balancer](https://developers.cloudflare.com/load-balancing/)                                                                | Distributes traffic across your endpoints, which reduces endpoint strain and latency and improves the experience for end users.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/)                      | Secure method to connect to customers' networks and servers without creating holes in [firewalls](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/tunnel-with-firewall/). cloudflared is the daemon (software) installed on origin servers to create a secure tunnel from applications back to Cloudflare.                                                                                                                                                                                                                                                                                                                            |

## Cloudflare for SaaS examples

The primary objective of using Cloudflare is to ensure that all requests to your application's custom hostname are routed through Cloudflare's security and performance services first to apply security controls and routing or load balancing of traffic. Since the origin server often needs to be publicly accessible, securing the connection between Cloudflare and the origin server is crucial. For comprehensive guidance on securing origin servers, please refer to Cloudflare's documentation: [Protect your origin server](https://developers.cloudflare.com/fundamentals/security/protect-your-origin-server/).

The diagrams below begin by illustrating the simplest approach to achieving this goal, followed by more complex configurations.

### Standard fallback origin setup

This standard Cloudflare for SaaS setup is the most commonly used and easiest to implement for most providers. Typically, these providers are SaaS companies, which develop and deliver software as a service solutions. This setup requires only a single DNS record to direct requests to Cloudflare, which then proxies the traffic to your application using an A record.

![Figure 1: Standard fallback origin setup.](https://developers.cloudflare.com/_astro/standard-fallback-origin-setup.DrGJNOUB_1wPLqh.svg "Figure 1: Standard fallback origin setup.")

Figure 1: Standard fallback origin setup.

1. The custom hostname (`custom.example.com`) is configured as a CNAME record pointing to the fallback origin of the provider. The fallback origin is the server or servers that Cloudflare will route traffic to by default when a request is made to the custom hostname. This DNS record does not need to be managed within Cloudflare; it just needs to point to the Cloudflare-hosted record from the provider (`fallback.myappexample.com`).
2. The Fallback Origin is set up as an A record that points to the public IP address of the origin server. Cloudflare will route traffic sent to the custom hostnames to this origin server by default.

The origin server receives the details of the custom domain through either the [host header or SNI](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/reference/connection-details/). This enables the origin server to determine which application to direct the request to. This method is applicable for both custom hostnames (for example, `app.mycustomerexample.com`) and vanity domains (for example, `customer1.myappexample.com`). Since all requests for your application are now routed through the Cloudflare network, you can leverage a range of security and performance services for every request, including:

* [Web Application Firewall](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/)
* [Access control policies](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/secure-with-access/)
* [Caching of application content](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/cache-for-saas/)
* [Support browser early hints](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/early-hints-for-saas/)
* [Image Transformations](https://developers.cloudflare.com/images/)
* [Waiting Room](https://developers.cloudflare.com/waiting-room/)
* [Workers for Platform](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/)

For implementation details to get started, review the [developer documentation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/).

### Standard fallback origin setup with regional services

This approach introduces using Cloudflare's [Regional Services](https://developers.cloudflare.com/data-localization/regional-services/) solution to regionalize TLS termination and HTTP processing to confirm with any compliance regulations that dictate your service process data in specific geographic locations. This ensures that traffic destined for the origin server is handled exclusively within the chosen region.

![Figure 2: Standard fallback origin setup with regional services.](https://developers.cloudflare.com/_astro/standard-fallback-origin-setup-regional-services.DgKfyYv8_1GmwVA.svg "Figure 2: Standard fallback origin setup with regional services.")

Figure 2: Standard fallback origin setup with regional services.

1. The custom hostname (`custom.example.com`) is configured as a CNAME record that points to a regionalized SaaS hostname (`eu-customers.myappexample.com`). This configuration ensures that all processing, including TLS termination, occurs exclusively within the specified geographic region.
2. The regionalized SaaS hostname is set up as a CNAME record that directs traffic to the standard [Fallback Origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin) of the SaaS provider (`fallback.myappexample.com`).
3. The fallback origin is set up as an A record that points to the public IP address of the origin server. Cloudflare will route traffic sent to the custom hostnames to this origin server by default.

### Cloudflare Tunnel as fallback origin setup with regional services

For enhanced security, rather than exposing your application servers directly to the Internet via public IPs, SaaS providers can use [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/). These tunnels connect your network to Cloudflare's nearest data centers, allowing SaaS applications to be accessed through [public hostnames](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/). As a result, Cloudflare becomes the sole entry point for end-customers from the public Internet into your application network.

![Figure 3: Cloudflare Tunnel as Fallback Origin Setup with Regional Services.](https://developers.cloudflare.com/_astro/cloudflare-tunnel-fallback-origin-setup-regional-services.h18fhKDd_Z2kIyIF.svg "Figure 3: Cloudflare Tunnel as Fallback Origin Setup with Regional Services.")

Figure 3: Cloudflare Tunnel as Fallback Origin Setup with Regional Services.

1. The custom hostname (`custom.example.com`) is configured as a CNAME record that points to a regionalized SaaS hostname (`eu-customers.myappexample.com`). This configuration ensures that all processing, including TLS termination, occurs exclusively within the specified geographic region.
2. The regionalized SaaS hostname is set up as a CNAME record that directs traffic to the standard [Fallback Origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin) of the SaaS provider (`fallback.myappexample.com`).
3. The fallback origin is a CNAME DNS record that points to a [public hostname](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/) exposed by Cloudflare Tunnel. This public hostname should be configured to route traffic to your application, for example, `localhost:8080`.

This setup is ideal for SaaS providers that do not need granular load balancing, such as [geo-based traffic steering](https://developers.cloudflare.com/load-balancing/understand-basics/traffic-steering/), across multiple origin servers. It's also well-suited for simple testing and development environments, where [protecting your origin server](https://developers.cloudflare.com/fundamentals/security/protect-your-origin-server/) by only allowing requests through the Cloudflare Tunnel is sufficient. However, for distributed applications requiring load balancing at both global and local levels, we recommend using [Cloudflare's Load Balancer](https://developers.cloudflare.com/load-balancing/) with global and private network load balancing capabilities.

### Global Traffic Management (GTM) & Private Network Load Balancing as custom origin setup

Cloudflare offers a powerful set of load balancing capabilities. These allow you to reliably steer traffic to different origin servers where your SaaS applications are hosted, whether through public hostnames (as described above) or private IP addresses. This setup helps prevent origin overload by distributing traffic across multiple servers and enhances security by only permitting requests through the Cloudflare Tunnel.

![Figure 4: Global Traffic Management \(GTM\) & Private Network Load Balancing as custom origin setup.](https://developers.cloudflare.com/_astro/gtm-ltm-custom-origin-setup.C_l8lMsz_60Ayr.svg "Figure 4: Global Traffic Management (GTM) & Private Network Load Balancing as custom origin setup.")

Figure 4: Global Traffic Management (GTM) & Private Network Load Balancing as custom origin setup.

1. The custom hostname (`custom.example.com`) is configured as a CNAME record pointing to a Cloudflare [regionalized Load Balancer](https://developers.cloudflare.com/data-localization/how-to/load-balancing/) (`eu-lb.myappexample.com`). This ensures that all processing, including TLS termination, takes place within a specified geographic region. Additionally, the SaaS provider needs to set up the load balancer as the [custom origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/) for the custom hostname.
2. The regional load balancer is set up with [origin pools](https://developers.cloudflare.com/load-balancing/pools/) to distribute requests across multiple downstream servers. Each pool can be configured to use either [public hostnames](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/) with Global Traffic Management (GTM) or [private network](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/) addresses with Private Network Load Balancing. In the diagram above, we utilize both options:  
   * Origin pool 1 uses the [Cloudflare Tunnel hostname](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/dns/) (`<UUID>.cfargotunnel.com`) as the endpoint or origin server for handling those requests. When using a public hostname, it is necessary to set the [HTTP host header value](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/) to match the public hostname configured and exposed by the [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/). This ensures that the origin server can correctly route the incoming requests.  
   * Origin pool 2 uses the private IP address or private network (that is, `10.0.0.5`) within the SaaS provider's internal network, where the SaaS application resides. This pool must be configured to operate within the specified [virtual network](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/cloudflared/tunnel-virtual-networks/) to ensure proper routing of requests.
3. Cloudflare Tunnel exposes both [public hostnames](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/routing-to-tunnel/) with GTM and [private networks](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/private-net/) (private IPs) with Private Network Load Balancing.

For enhanced granularity in application serving and scalability, it is generally recommended to use private networks rather than public hostnames. Private networks enable Cloudflare to preserve and accurately pass the host header to the origin server. In contrast, when using public hostnames, providers must configure the [header value](https://developers.cloudflare.com/load-balancing/additional-options/override-http-host-headers/) on the load balancer, which is restricted to one public hostname per load balancer endpoint, potentially limiting flexibility.

Be aware of the Zero Trust [Tunnel limitations](https://developers.cloudflare.com/cloudflare-one/account-limits/#cloudflare-tunnel), Cloudflare for SaaS [connection request details](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/reference/connection-details/), and the Custom Origin [SNI specification](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/#sni-rewrites). For further information about the Cloudflare Load Balancer, review its [reference architecture](https://developers.cloudflare.com/reference-architecture/architectures/load-balancing/).

## Automation

As a SaaS provider, it is advisable to automate most, if not all, of these processes using [APIs](https://developers.cloudflare.com/fundamentals/api/), [SDKs](https://developers.cloudflare.com/fundamentals/api/reference/sdks/), scripts, [Terraform](https://developers.cloudflare.com/terraform/), or other automation tools.

An example of a high-level migration plan can be [downloaded here](https://developers.cloudflare.com/reference-architecture/static/example-cloudflare-saas-migration-plan.pdf).

It is highly recommended to migrate to Cloudflare for SaaS in phases and address any issues as they arise, particularly with [Domain Control Validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/troubleshooting/). Be sure to review the [validation status](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/validation-status/) and relevant [documentation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/) during the process.

## Summary

By leveraging Cloudflare's infrastructure, SaaS providers can deliver secure, reliable, and performance services to their end-customers. This ensures a seamless and secure user experience while meeting compliance requirements, such as regionalization.

Several Cloudflare customers are currently using the Cloudflare for SaaS solution (formerly known as SSL for SaaS). Notable public use cases include:

* [Shopify ↗](https://www.cloudflare.com/case-studies/shopify/)
* [Porsche Informatik ↗](https://www.cloudflare.com/case-studies/porsche-informatik/)
* [Divio ↗](https://www.cloudflare.com/case-studies/divio/)
* [mogenius ↗](https://www.cloudflare.com/case-studies/mogenius/)
* [Quickbutik ↗](https://www.cloudflare.com/case-studies/quickbutik/)

Additionally, when migrating to Cloudflare for SaaS, it is crucial to have a runbook and clear public documentation to communicate relevant details to your end-customers. Excellent public examples of this are the [Salesforce CDN ↗](https://help.salesforce.com/s/articleView?id=sf.community%5Fbuilder%5Fcdn.htm&type=5) and [Shopify ↗](https://help.shopify.com/en/manual/domains/add-a-domain/connecting-domains) documentation.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/reference-architecture/","name":"Reference Architecture"}},{"@type":"ListItem","position":3,"item":{"@id":"/reference-architecture/design-guides/","name":"Design Guides"}},{"@type":"ListItem","position":4,"item":{"@id":"/reference-architecture/design-guides/extending-cloudflares-benefits-to-saas-providers-end-customers/","name":"Extend Cloudflare's benefits to SaaS providers' end-customers"}}]}
```

---

---
title: Custom hostnames
description: Add customer vanity domains and subdomains to your SaaS zone as custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom hostnames

Cloudflare for SaaS allows you, as a SaaS provider, to extend the benefits of Cloudflare products to custom domains by adding them to your zone as custom hostnames. We support adding hostnames that are a subdomain of your zone (for example, `sub.serviceprovider.com`) and vanity domains (for example, `customer.com`) to your SaaS zone.

## Resources

* [ Create custom hostnames ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/)
* [ Hostname validation ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/)
* [ Move hostnames ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/migrating-custom-hostnames/)
* [ Remove custom hostnames ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/remove-custom-hostnames/)
* [ Custom metadata ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}}]}
```

---

---
title: Create custom hostnames
description: Learn how to create custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Create custom hostnames

There are several required steps before a custom hostname can become active. For more details, refer to our [Get started guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/).

Zone name restriction

Do not configure a custom hostname which matches the zone name. For example, if your SaaS zone is `example.com`, do not create a custom hostname named `example.com`.

To create a custom hostname:

* [ Dashboard ](#tab-panel-4527)
* [ API ](#tab-panel-4528)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Select **Add Custom Hostname**.
3. Add your customer's hostname `app.customer.com` and set the relevant options, including:  
   * The [minimum TLS version](https://developers.cloudflare.com/ssl/reference/protocols/).  
   * Defining whether you want to use a certificate provided by Cloudflare or [upload a custom certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/).  
   * Selecting the [certificate authority (CA)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) that will issue the certificate.  
   * Choosing the [validation method](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/).  
   * Whether you want to **Enable wildcard**, which adds a `*.<custom-hostname>` SAN to the custom hostname certificate. For more details, refer to [Hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority).  
   * Choosing a value for [Custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/).
4. Select **Add Custom Hostname**.

Default behavior

When you create a custom hostname:

* If you issue a custom hostname certificate with wildcards enabled, you cannot customize TLS settings for these wildcard hostnames.
* If you do not specify the **Minimum TLS Version**, it defaults to the zone's Minimum TLS Version. You can still [edit this setting](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version) after creation.

1. To create a custom hostname using the API, use the [Create Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) endpoint.  
   * You can leave the `certificate_authority` parameter empty to set it to "default CA". With this option, Cloudflare checks the CAA records before requesting the certificates, which helps ensure the certificates can be issued from the CA.
2. For the newly created custom hostname, the `POST` response may not return the DCV validation token `validation_records`. It is recommended to make a second [GET command](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/list/) (with a delay) to retrieve these details.

The response contains the complete definition of the new custom hostname.

Default behavior

When you create a custom hostname:

* If you issue a custom hostname certificate with wildcards enabled, you cannot customize TLS settings for these wildcard hostnames.
* If you do not specify the **Minimum TLS Version**, it defaults to the zone's Minimum TLS Version. You can still [edit this setting](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version) after creation.

For each custom hostname, Cloudflare issues two certificates bundled in chains that maximize browser compatibility (unless you [upload custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/)).

The primary certificate uses a `P-256` key, is `SHA-2/ECDSA` signed, and will be presented to browsers that support elliptic curve cryptography (ECC). The secondary or fallback certificate uses an `RSA 2048-bit` key, is `SHA-2/RSA` signed, and will be presented to browsers that do not support ECC.

## Hostnames over 64 characters

The Common Name (CN) restriction establishes a limit of 64 characters ([RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280.html)). If you have a hostname that exceeds this length, you can set `cloudflare_branding` to `true` when creating your custom hostnames [via API](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/).

```

"ssl": {

    "cloudflare_branding": true

  }


```

Cloudflare branding means that `sni.cloudflaressl.com` will be added as the certificate Common Name (CN) and the long hostname will be included as a part of the Subject Alternative Name (SAN).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/","name":"Create custom hostnames"}}]}
```

---

---
title: Custom metadata
description: Configure per-hostname settings such as URL rewriting and custom headers.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ JSON ](https://developers.cloudflare.com/search/?tags=JSON)[ TypeScript ](https://developers.cloudflare.com/search/?tags=TypeScript) 

# Custom metadata

You may wish to configure per-hostname (customer) settings beyond the scale of Rules or Rate Limiting.

To do this, you will first need to reach out to your account team to enable access to Custom Metadata. After configuring custom metadata, you can use it in the following ways:

* Read the metadata JSON from [Cloudflare Workers](https://developers.cloudflare.com/workers/) (requires access to Workers) to define per-hostname behavior.
* Use custom metadata values in [rule expressions](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/) of different Cloudflare security products to define the rule scope.

Note

Only certain customers have access to this feature. For more details, see the [Plans page](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

---

## Examples

* Per-customer URL rewriting — for example, customers 1-10,000 fetch assets from server A, 10,001-20,000 from server B, etc.
* Adding custom headers — for example, `X-Customer-ID: $number` based on the metadata you provided
* Setting HTTP Strict Transport Security (“HSTS”) headers on a per-customer basis

Please speak with your Solutions Engineer to discuss additional logic and requirements.

## Submitting custom metadata

You may add custom metadata to Cloudflare via the Custom Hostnames API. This data can be added via a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) to the specific hostname ID to set metadata for that hostname, for example:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "ssl": {

        "method": "http",

        "type": "dv"

    },

    "custom_metadata": {

        "customer_id": "12345",

        "redirect_to_https": true,

        "security_tag": "low"

    }

  }'


```

Changes to metadata will propagate across Cloudflare's edge within 30 seconds.

---

## Accessing custom metadata from a Cloudflare Worker

The metadata object will be accessible on each request using the `request.cf.hostMetadata` property. You can then read the data, and customize any behavior on it using the Worker.

In the example below we will use the user\_id in the Worker that was submitted using the API call above `"custom_metadata":{"customer_id":"12345","redirect_to_https": true,"security_tag":"low"}`, and set a request header to send the `customer_id` to the origin:

* [  JavaScript ](#tab-panel-4529)
* [  TypeScript ](#tab-panel-4530)

JavaScript

```

export default {

  /**

   * Fetch and add a X-Customer-Id header to the origin based on hostname

   * @param {Request} request

   */

  async fetch(request, env, ctx) {

    const customer_id = request.cf.hostMetadata.customer_id;

    const newHeaders = new Headers(request.headers);

    newHeaders.append("X-Customer-Id", customer_id);


    const init = {

      headers: newHeaders,

      method: request.method,

    };

    return fetch(request.url, init);

  },

};


```

TypeScript

```

export default {

  /**

   * Fetch and add a X-Customer-Id header to the origin based on hostname

   * @param {Request} request

   */

  async fetch(request, env, ctx): Promise<Response> {

    const customer_id = request.cf.hostMetadata.customer_id;

    const newHeaders = new Headers(request.headers);

    newHeaders.append("X-Customer-Id", customer_id);


    const init = {

      headers: newHeaders,

      method: request.method,

    };

    return fetch(request.url, init);

  },

} satisfies ExportedHandler<Env>;


```

## Accessing custom metadata in a rule expression

Use the [cf.hostname.metadata](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.hostname.metadata/) field to access the metadata object in rule expressions. To obtain the different values from the JSON object, use the [lookup\_json\_string](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#lookup%5Fjson%5Fstring) function.

The following rule expression defines that there will be a rule match if the `security_tag` value in custom metadata contains the value `low`:

```

lookup_json_string(cf.hostname.metadata, "security_tag") eq "low"


```

---

## Best practices

* Ensure that the JSON schema used is fixed: changes to the schema without corresponding Cloudflare Workers changes will potentially break websites, or fall back to any defined “default” behavior
* Prefer a flat JSON structure
* Use string keys in snake\_case (rather than camelCase or PascalCase)
* Use proper booleans (true/false rather than `true` or `1` or `0`)
* Use numbers to represent integers instead of strings (`1` or `2` instead of `"1"` or `"2"`)
* Define fallback behaviour in the non-presence of metadata
* Define fallback behaviour if a key or value in the metadata are unknown

General guidance is to follow [Google's JSON Style guide ↗](https://google.github.io/styleguide/jsoncstyleguide.xml) where appropriate.

---

## Limitations

There are some limitations to the metadata that can be provided to Cloudflare:

* It must be valid JSON.
* Any origin resolution — for example, directing requests for a given hostname to a specific backend — must be provided as a hostname that exists within Cloudflare's DNS (even for non-authoritative setups). Providing an IP address directly will cause requests to error.
* The total payload must not exceed 4 KB.
* It requires a Cloudflare Worker that knows how to process the schema and trigger logic based on the contents.

Note

Be careful when modifying the schema. Adding, removing, or changing keys and possible values may cause the Cloudflare Worker to either ignore the data or return an error for requests that trigger it.

### Terraform support

[Terraform](https://developers.cloudflare.com/terraform/) only allows maps of a single type, so Cloudflare's Terraform support for custom metadata for custom hostnames is limited to string keys and values.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/","name":"Custom metadata"}}]}
```

---

---
title: Hostname validation
description: Verify customer ownership of custom hostnames before proxying traffic.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Hostname validation

Before Cloudflare can proxy traffic through a custom hostname, we need to verify your customer's ownership of that hostname.

Note

If a custom hostname is already on Cloudflare, using the [pre-validation methods](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/pre-validation/) will not shift the traffic to the SaaS zone. That will only happen once the [DNS target](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record) of the custom hostnames changes to point to the SaaS zone.

## Options

If minimizing downtime is more important to you, refer to our [pre-validation methods](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/pre-validation/).

If ease of use for your customers is more important, review our [real-time validation methods](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/).

## Limitations

Custom hostnames using another CDN are not compatible with Cloudflare for SaaS. Since Cloudflare must be able to validate your customer's ownership of the hostname you add, if their usage of another CDN obfuscates their DNS records, hostname validation will fail.

## Related resources

* [ Pre-validation ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/pre-validation/)
* [ Real-time validation ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/)
* [ Backoff schedule ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/backoff-schedule/)
* [ Validation status ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/validation-status/)
* [ Error codes ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/error-codes/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/","name":"Hostname validation"}}]}
```

---

---
title: Backoff schedule
description: Retry schedule for custom hostname validation over a seven-day period.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Backoff schedule

After you create a custom hostname, Cloudflare has to [validate that hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/).

Attempts to validate a Custom Hostname are distributed over seven days (a total of 75 retries). At the end of this schedule, if the validation is unsuccessful, the custom hostname will be deleted. The function that determines the next check varies based on the number of attempts:

* For the first 10 attempts:

```

now() + min((floor(60 * pow(1.05, retry_attempt)) * INTERVAL '1 second'), INTERVAL '4 hours')


```

* For the remaining 65 attempts:

```

now() + min((floor(60 * pow(1.15, retry_attempt)) * INTERVAL '1 second'), INTERVAL '4 hours')


```

The first 10 checks complete within 20 minutes and most checks complete in the first four hours. The check back off is capped to a maximum of four hours to avoid exponential growth. The back off behavior causes larger gaps between check intervals towards the end of the back off schedule:

| Retry Attempt | In Seconds | In Minutes | In Hours |
| ------------- | ---------- | ---------- | -------- |
| 0             | 60         | 1          | 0.016667 |
| 1             | 63         | 1.05       | 0.0175   |
| 2             | 66         | 1.1        | 0.018333 |
| 3             | 69         | 1.15       | 0.019167 |
| 4             | 72         | 1.2        | 0.02     |
| 5             | 76         | 1.266667   | 0.021111 |
| 6             | 80         | 1.333333   | 0.022222 |
| 7             | 84         | 1.4        | 0.023333 |
| 8             | 88         | 1.466667   | 0.024444 |
| 9             | 93         | 1.55       | 0.025833 |
| 10            | 242        | 4.033333   | 0.067222 |
| 11            | 279        | 4.65       | 0.0775   |
| 12            | 321        | 5.35       | 0.089167 |
| 13            | 369        | 6.15       | 0.1025   |
| 14            | 424        | 7.066667   | 0.117778 |
| 15            | 488        | 8.133333   | 0.135556 |
| 16            | 561        | 9.35       | 0.155833 |
| 17            | 645        | 10.75      | 0.179167 |
| 18            | 742        | 12.366667  | 0.206111 |
| 19            | 853        | 14.216667  | 0.236944 |
| 20            | 981        | 16.35      | 0.2725   |
| 21            | 1129       | 18.816667  | 0.313611 |
| 22            | 1298       | 21.633333  | 0.360556 |
| 23            | 1493       | 24.883333  | 0.414722 |
| 24            | 1717       | 28.616667  | 0.476944 |
| 25            | 1975       | 32.916667  | 0.548611 |
| 26            | 2271       | 37.85      | 0.630833 |
| 27            | 2612       | 43.533333  | 0.725556 |
| 28            | 3003       | 50.05      | 0.834167 |
| 29            | 3454       | 57.566667  | 0.959444 |
| 30            | 3972       | 66.2       | 1.103333 |
| 31            | 4568       | 76.133333  | 1.268889 |
| 32            | 5253       | 87.55      | 1.459167 |
| 33            | 6041       | 100.683333 | 1.678056 |
| 34            | 6948       | 115.8      | 1.93     |
| 35            | 7990       | 133.166667 | 2.219444 |
| 36            | 9189       | 153.15     | 2.5525   |
| 37            | 10567      | 176.116667 | 2.935278 |
| 38            | 12152      | 202.533333 | 3.375556 |
| 39            | 13975      | 232.916667 | 3.881944 |
| 40            | 14400      | 240        | 4        |
| 41            | 14400      | 240        | 4        |
| 42            | 14400      | 240        | 4        |
| 43            | 14400      | 240        | 4        |
| 44            | 14400      | 240        | 4        |
| 45            | 14400      | 240        | 4        |
| 46            | 14400      | 240        | 4        |
| 47            | 14400      | 240        | 4        |
| 48            | 14400      | 240        | 4        |
| 49            | 14400      | 240        | 4        |
| 50            | 14400      | 240        | 4        |
| 51            | 14400      | 240        | 4        |
| 52            | 14400      | 240        | 4        |
| 53            | 14400      | 240        | 4        |
| 54            | 14400      | 240        | 4        |
| 55            | 14400      | 240        | 4        |
| 56            | 14400      | 240        | 4        |
| 57            | 14400      | 240        | 4        |
| 58            | 14400      | 240        | 4        |
| 59            | 14400      | 240        | 4        |
| 60            | 14400      | 240        | 4        |
| 61            | 14400      | 240        | 4        |
| 62            | 14400      | 240        | 4        |
| 63            | 14400      | 240        | 4        |
| 64            | 14400      | 240        | 4        |
| 65            | 14400      | 240        | 4        |
| 66            | 14400      | 240        | 4        |
| 67            | 14400      | 240        | 4        |
| 68            | 14400      | 240        | 4        |
| 69            | 14400      | 240        | 4        |
| 70            | 14400      | 240        | 4        |
| 71            | 14400      | 240        | 4        |
| 72            | 14400      | 240        | 4        |
| 73            | 14400      | 240        | 4        |
| 74            | 14400      | 240        | 4        |
| 75            | 14400      | 240        | 4        |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/","name":"Hostname validation"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/backoff-schedule/","name":"Backoff schedule"}}]}
```

---

---
title: Error codes
description: Error codes you may encounter when validating custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Error codes

When you [validate a custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/), you might encounter the following error codes.

| Error                                                                                                                   | Cause                                                                                                                                                                                                                                    |
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Zone does not have a fallback origin set.                                                                               | Fallback is not active.                                                                                                                                                                                                                  |
| Fallback origin is in a status of initializing, pending\_deployment, pending\_deletion, or deleted.                     | Fallback is not active.                                                                                                                                                                                                                  |
| Custom hostname does not CNAME to this zone.                                                                            | Zone does not have [apex proxying entitlement](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/) and custom hostname does not CNAME to zone.                        |
| None of the A or AAAA records are owned by this account and the pre-generated ownership validation token was not found. | Account has [apex proxying enabled](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/) but the custom hostname failed the hostname validation check on the A record. |
| This account and the pre-generated ownership validation token was not found.                                            | Hostname does not CNAME to zone or none of the A/AAAA records match reserved IPs for zone.                                                                                                                                               |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/","name":"Hostname validation"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/error-codes/","name":"Error codes"}}]}
```

---

---
title: Pre-validation
description: Verify domain ownership before customer traffic begins proxying through Cloudflare.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Pre-validation

Pre-validation methods help verify domain ownership before your customer's traffic is proxying through Cloudflare.

## Use when

Use pre-validation methods when your customers cannot tolerate any downtime, which often occurs with production domains.

The downside is that these methods require an additional setup step for your customers. Especially if you already need them to add something to their domain for [certificate validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/), pre-validation might make their onboarding more complicated.

If your customers can tolerate a bit of downtime and you want their setup to be simpler, review our [real-time validation methods](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/).

## How to

### TXT records

TXT validation is when your customer adds a `TXT` record to their authoritative DNS to verify domain ownership.

Note

If your customer cannot update their authoritative DNS, you could also use [HTTP validation](#http-tokens).

To set up `TXT` validation:

1. When you [create a custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/), save the `ownership_verification` information.  
```  
{  
"result": [  
    {  
    "id": "3537a672-e4d8-4d89-aab9-26cb622918a1",  
    "hostname": "app.example.com",  
    // ...  
    "status": "pending",  
    "verification_errors": ["custom hostname does not CNAME to this zone."],  
    "ownership_verification": {  
        "type": "txt",  
        "name": "_cf-custom-hostname.app.example.com",  
        "value": "0e2d5a7f-1548-4f27-8c05-b577cb14f4ec"  
    },  
    "created_at": "2020-03-04T19:04:02.705068Z"  
    }  
]  
}  
```
2. Have your customer add a `TXT` record with that `name` and `value` at their authoritative DNS provider.
3. After a few minutes, you will see the hostname status become **Active** in the UI.
4. Once you activate the custom hostname, your customer can remove the `TXT` record.

### HTTP tokens

HTTP validation is when you or your customer places an HTTP token on their origin server to verify domain ownership.

To set up HTTP validation:

When you [create a custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/issue-certificates/) using the API, Cloudflare provides an HTTP `ownership_verification` record in the response.

To get and use the `ownership_verification` record:

1. Make an API call to [create a Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/).
2. In the response, copy the `http_url` and `http_body` from the `ownership_verification_http` object:  
Example response (truncated)  
```  
{  
  "result": [  
    {  
      "id": "24c8c68e-bec2-49b6-868e-f06373780630",  
      "hostname": "app.example.com",  
      // ...  
      "ownership_verification_http": {  
          "http_url": "http://app.example.com/.well-known/cf-custom-hostname-challenge/24c8c68e-bec2-49b6-868e-f06373780630",  
          "http_body": "48b409f6-c886-406b-8cbc-0fbf59983555"  
      },  
      "created_at": "2020-03-04T20:06:04.117122Z"  
    }  
  ]  
}  
```
3. Have your customer place the `http_url` and `http_body` on their origin web server.  
Example response (truncated)  
```  
location "/.well-known/cf-custom-hostname-challenge/24c8c68e-bec2-49b6-868e-f06373780630" {  
    return 200 "48b409f6-c886-406b-8cbc-0fbf59983555\n";  
}  
```  
Cloudflare will access this token by sending `GET` requests to the `http_url` using `User-Agent: Cloudflare Custom Hostname Verification`.  
Note  
If you can serve these tokens on behalf of your customers, you can simplify their overall setup.
4. After a few minutes, you will see the hostname status become **Active** in the UI.
5. Once the hostname is active, your customer can remove the token from their origin server.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/","name":"Hostname validation"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/pre-validation/","name":"Pre-validation"}}]}
```

---

---
title: Real-time validation
description: Validate custom hostnames when customers add DNS routing records to their domain.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Real-time validation

When you use a real-time validation method, Cloudflare verifies your customer's hostname when your customers adds their [DNS routing record](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record) to their authoritative DNS.

## Use when

Real-time validation methods put less burden on your customers because it does not require any additional actions.

However, it may cause some downtime since Cloudflare takes a few seconds to iterate over DNS records. This downtime also can increase - due to the increasing [validation backoff schedule](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/backoff-schedule/) \- if your customer takes additional time to add their DNS routing record.

To minimize this downtime, you can continually send no-change [PATCH requests](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) for the specific custom hostname until it validates (which resets the validation backoff schedule).

To avoid any chance of downtime, use a [pre-validation method](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/pre-validation/)

## How to

Real-time validation occurs automatically when your customer adds their [DNS routing record](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record).

The exact record depends on your Cloudflare for SaaS setup.

### Normal setup (CNAME target)

Most customers will have a `CNAME` target, which requires their customers to create a `CNAME` record similar to:

```

mystore.com CNAME customers.saasprovider.com


```

### Apex proxying

With [apex proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/), SaaS customers need to create an `A` record for their hostname that points to the IP prefix allocated to the SaaS provider's account.

```

example.com.  60  IN  A   192.0.2.1


```

Note

For [BYOIP](https://developers.cloudflare.com/byoip/) customers, Cloudflare automatically enables the Apex Proxy Access feature on your BYOIP block, which allows Custom Hostnames to be activated via [Apex proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/#apex-proxying) when Authoritative DNS for a customer's hostname targets any IP addresses in your BYOIP block.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/","name":"Hostname validation"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/","name":"Real-time validation"}}]}
```

---

---
title: Validation status
description: Possible statuses for custom hostname validation and their meanings.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Validation status

When you [validate a custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/), that hostname can be in several different statuses.

| Status              | Description                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pending             | Custom hostname is pending hostname validation.                                                                                                                                                                                                                                                                                                                                  |
| Active              | Custom hostname has completed hostname validation and is active.                                                                                                                                                                                                                                                                                                                 |
| Active re-deploying | Customer hostname is active and the changes have been processed.                                                                                                                                                                                                                                                                                                                 |
| Blocked             | Custom hostname cannot be added to Cloudflare at this time. Custom hostname was likely associated with Cloudflare previously and flagged for abuse.If you are an Enterprise customer, contact your Customer Success Manager. Otherwise, email abusereply@cloudflare.com with the name of the web property and a detailed explanation of your association with this web property. |
| Moved               | Custom hostname is not active after **Pending** for the entirety of the [Validation Backoff Schedule](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/backoff-schedule/) or it no longer points to the fallback origin.                                                                                        |
| Deleted             | Custom hostname was deleted from the zone. Occurs when status is **Moved** for more than seven days.                                                                                                                                                                                                                                                                             |

## Refresh validation

To run the custom hostname validation check again, select **Refresh** on the dashboard or send a `PATCH` request to the [Edit custom hostname endpoint](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/). If using the API, make sure that the `--data` field contains an `ssl` object with the same `method` and `type` as the original request.

If the hostname is in a **Moved** or **Deleted** state, the refresh will set the custom hostname back to **Pending validation**.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/","name":"Hostname validation"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/validation-status/","name":"Validation status"}}]}
```

---

---
title: Move hostnames
description: Learn how to move hostnames between different zones.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ Migration ](https://developers.cloudflare.com/search/?tags=Migration) 

# Move hostnames

As a SaaS provider, you may want, or have, multiple zones to manage hostnames. Each zone can have different configurations or origins, as well as correlate to varying products. You might shift custom hostnames between zones to enable or disable certain features. Cloudflare allows migration within the same account through the steps below:

---

## CNAME

If your custom hostname uses a CNAME record, add the custom hostname to the new zone and [update your DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#edit-dns-records) to point to the new zone.

Note

If you would like to migrate the custom hostname without end customers changing the DNS target, use [apex proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/).

1. [Add custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) to your new zone.
2. Direct your customer to [change the DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#edit-dns-records) so that it points to the new zone.
3. Confirm that the custom hostname has validated in the new zone.
4. Wait for the certificate to validate automatically through Cloudflare or [validate it using Domain Control Validation (DCV)](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/#perform-dcv).
5. Remove custom hostname from the old zone.

Once these steps are complete, the custom hostname's traffic will route to the second SaaS zone and will use its configuration.

## A record

Through [Apex Proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/) or [BYOIP](https://developers.cloudflare.com/byoip/), you can migrate the custom hostname without action from your end customer.

1. Verify with the account team that your apex proxying IPs have been assigned to both SaaS zones.
2. [Add custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) to the new zone.
3. Confirm that the custom hostname has validated in the new zone.
4. Wait for the certificate to validate automatically through Cloudflare or [validate it using DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/#perform-dcv).
5. Remove custom hostname from the old zone.

Note

The most recently edited custom hostname will be active. For instance, `example.com` exists on `SaaS Zone 1`. It is added to `SaaS Zone 2`. Because it was activated more recently on `SaaS Zone 2`, that is where it will be active. However, if edits are made to example.com on `SaaS Zone 1`, it will reactivate on that zone instead of `SaaS Zone 2`.

## Wildcard certificate

If you are migrating custom hostnames that rely on a Wildcard certificate, Cloudflare cannot automatically complete Domain Control Validation (DCV).

1. [Add custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) to the new zone.
2. Direct your customer to [change the DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#edit-dns-records) so that it points to the new zone.
3. [Validate the certificate](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/#perform-dcv) on the new zone through DCV.

The custom hostname can activate on the new zone even if the certificate is still active on the old zone. This ensures a valid certificate exists during migration. However, it is important to validate the certificate on the new zone as soon as possible.

Note

Verify that the custom hostname successfully activated after the migration on the [**Custom Hostnames** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames) page.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/migrating-custom-hostnames/","name":"Move hostnames"}}]}
```

---

---
title: Remove custom hostnames
description: Learn how to remove custom hostnames for inactive customers.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Remove custom hostnames

As a SaaS provider, your customers may decide to no longer participate in your service offering. If that happens, you need to stop routing traffic through those custom hostnames.

## Domains using Cloudflare

If your customer's domain is also using Cloudflare, they can stop routing their traffic through your custom hostname by updating their Cloudflare DNS.

If they update their [CNAME record](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record) so that it no longer points to your `CNAME` target:

* The domain's traffic will not route through your custom hostname.
* The custom hostname will enter into a **Moved** state.

If the custom hostname is in a **Moved** state for seven days, it will transition into a **Deleted** state.

You should remove a customer's custom hostname from your zone if they decide to churn. This is especially important if your end customers are using Cloudflare because if the churned customer changes the DNS target to point away from your SaaS zone but you have not removed it, the custom hostname will continue to route to your service. This is a result of the [custom hostname priority logic](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority).

## Domains not using Cloudflare

If your customer's domain is not using Cloudflare, you must remove a customer's custom hostname from your zone if they decide to churn.

* [ Dashboard ](#tab-panel-4531)
* [ API ](#tab-panel-4532)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Select the custom hostname and select **Delete**.
3. A confirmation window will appear. Acknowledge the warning and select **Delete** again.

To delete a custom hostname and any issued certificates using the API, send a [DELETE request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/delete/).

## For end customers

If your SaaS domain is also a [domain using Cloudflare](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/), you can use your Cloudflare DNS to remove your domain from your SaaS provider.

This means that - if you [remove the DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) pointing to your SaaS provider - Cloudflare will stop routing domain traffic through your SaaS provider and the associated custom hostname will enter a **Moved** state.

This also means that you need to keep DNS records pointing to your SaaS provider for as long as you are a customer. Otherwise, you could accidentally remove your domain from their services.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/","name":"Custom hostnames"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/domain-support/remove-custom-hostnames/","name":"Remove custom hostnames"}}]}
```

---

---
title: Analytics
description: View per-hostname analytics for traffic, bots, cache, and security events.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ Analytics ](https://developers.cloudflare.com/search/?tags=Analytics)[ GraphQL ](https://developers.cloudflare.com/search/?tags=GraphQL) 

# Analytics

You can use custom hostname analytics for two general purposes: exploring how your customers use your product and sharing the benefits provided by Cloudflare with your customers.

These analytics include **Site Analytics**, **Bot Analytics**, **Cache Analytics**, **Security Events**, and [any other datasets](https://developers.cloudflare.com/analytics/graphql-api/features/data-sets/) with the `clientRequestHTTPHost` field.

Note

The plan of your Cloudflare for SaaS application determines the analytics available for your custom hostnames.

## Explore customer usage

Use custom hostname analytics to help your organization with billing and infrastructure decisions, answering questions like:

* "How many total requests is your service getting?"
* "Is one customer transferring significantly more data than the others?"
* "How many global customers do you have and where are they distributed?"

If you see one customer is using more data than another, you might increase their bill. If requests are increasing in a certain geographic region, you might want to increase the origin servers in that region.

To access custom hostname analytics, either [use the dashboard](https://developers.cloudflare.com/analytics/faq/about-analytics/) and filter by the `Host` field or [use the GraphQL API](https://developers.cloudflare.com/analytics/graphql-api/) and filter by the `clientRequestHTTPHost` field. For more details, refer to our tutorial on [Querying HTTP events by hostname with GraphQL](https://developers.cloudflare.com/analytics/graphql-api/tutorials/end-customer-analytics/).

## Share Cloudflare data with your customers

With custom hostname analytics, you can also share site information with your customers, including data about:

* How many pageviews their site is receiving.
* Whether their site has a large percentage of bot traffic.
* How fast their site is.

Build custom dashboards to share this information by specifying an individual custom hostname in `clientRequestHTTPHost` field of [any dataset](https://developers.cloudflare.com/analytics/graphql-api/features/data-sets/) that includes this field.

## Logpush

[Logpush](https://developers.cloudflare.com/logs/logpush/) sends metadata from Cloudflare products to your cloud storage destination or SIEM.

Using [filters](https://developers.cloudflare.com/logs/logpush/logpush-job/filters/), you can send set sample rates (or not include logs altogether) based on filter criteria. This flexibility allows you to maintain selective logs for custom hostnames without massively increasing your log volume.

Filtering is available for [all Cloudflare datasets](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/).

Note

Filtering is not supported on the following data types: `objects`, `array[object]`.

For the Firewall events dataset, the following fields are not supported: `Action`, `Description`, `Kind`, `MatchIndex`, `Metadata`, `OriginatorRayID`, `RuleID`, and `Source`.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/hostname-analytics/","name":"Analytics"}}]}
```

---

---
title: Performance
description: Reduce latency for custom hostnames with Argo, Early Hints, caching, and anycast.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Performance

Cloudflare for SaaS allows you to deliver the best performance to your end customers by helping enable you to reduce latency through:

* [Argo Smart Routing for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/argo-for-saas/) calculates and optimizes the fastest path for requests to travel to your origin.
* [Early Hints for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/early-hints-for-saas/) provides faster loading speeds for individual custom hostnames by allowing the browser to begin loading responses while the origin server is compiling the full response.
* [Cache for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/performance/cache-for-saas/) makes customer websites faster by storing a copy of the website’s content on the servers of our globally distributed data centers.
* By using Cloudflare for SaaS, your customers automatically inherit the benefits of Cloudflare's vast [anycast network ↗](https://www.cloudflare.com/network/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/","name":"Performance"}}]}
```

---

---
title: Argo Smart Routing for SaaS
description: Optimize routing for custom hostname traffic with Argo Smart Routing.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Argo Smart Routing for SaaS

Argo Smart Routing uses real-time global network information to route traffic on the fastest possible path across the Internet. Regardless of geographic location, this allows Cloudflare to optimize routing to make it faster, more reliable, and more secure. As a SaaS provider, you may want to emphasize the quickest traffic delivery for your end customers. To do so, [enable Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/get-started/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/","name":"Performance"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/argo-for-saas/","name":"Argo Smart Routing for SaaS"}}]}
```

---

---
title: Cache for SaaS
description: Cache static content on custom hostnames to reduce latency for end users.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cache for SaaS

Cloudflare makes customer websites faster by storing a copy of the website’s content on the servers of our globally distributed data centers. Content can be either static or dynamic: static content is “cacheable” or eligible for caching, and dynamic content is “uncacheable” or ineligible for caching. The cached copies of content are stored physically closer to users, optimized to be fast, and do not require recomputing.

As a SaaS provider, enabling caching reduces latency on your custom domains. For more information, refer to [Cache](https://developers.cloudflare.com/cache/). If you would like to enable caching, review [Getting Started with Cache](https://developers.cloudflare.com/cache/get-started/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/","name":"Performance"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/cache-for-saas/","name":"Cache for SaaS"}}]}
```

---

---
title: Early Hints for SaaS
description: Enable Early Hints per custom hostname to preload resources and speed up page loads.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Early Hints for SaaS

[Early Hints](https://developers.cloudflare.com/cache/advanced-configuration/early-hints/) allows the browser to begin loading resources while the origin server is compiling the full response. This improves webpage’s loading speed for the end user. As a SaaS provider, you may prioritize speed for some of your custom hostnames. Using custom metadata, you can [enable Early Hints](https://developers.cloudflare.com/cache/advanced-configuration/early-hints/#enable-early-hints) per custom hostname.

---

## Prerequisites

Before you can employ Early Hints for SaaS, you need to create a custom hostname. Review [Get Started with Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) if you have not already done so.

---

## Enable Early Hints per custom hostname via the API

1. [Locate your zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/), available in the Cloudflare dashboard.
2. Locate your Authentication Key on the [**API Tokens** ↗](https://dash.cloudflare.com/?to=/:account/profile/api-tokens) page, under **Global API Key**.
3. If you are [creating a new custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/), make an API call such as the example below, specifying `"early_hints": "on"`:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Create Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "hostname": "<CUSTOM_HOSTNAME>",

    "ssl": {

        "method": "http",

        "type": "dv",

        "settings": {

            "http2": "on",

            "min_tls_version": "1.2",

            "tls_1_3": "on",

            "early_hints": "on"

        },

        "bundle_method": "ubiquitous",

        "wildcard": false

    }

  }'


```

1. For an existing custom hostname, locate the `id` of that hostname via a `GET` call:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

List Custom Hostnames

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames?hostname=%7Bhostname%7D" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

1. Then make an API call such as the example below, specifying `"early_hints": "on"`:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "ssl": {

        "method": "http",

        "type": "dv",

        "settings": {

            "http2": "on",

            "min_tls_version": "1.2",

            "tls_1_3": "on",

            "early_hints": "on"

        }

    }

  }'


```

Currently, all options within `settings` are required in order to prevent those options from being set to default. You can pull the current settings state prior to updating Early Hints by leveraging the output that returns the `id` for the hostname.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/","name":"Performance"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/performance/early-hints-for-saas/","name":"Early Hints for SaaS"}}]}
```

---

---
title: Plans
description: Learn what features and limits are part of various Cloudflare plans.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Plans

| Free                                                                                                                                                                            | Pro                              | Business                         | Enterprise                       |                                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------------------------------- | -------------------------------- | -------------------------------------------------- |
| Availability                                                                                                                                                                    | Yes                              | Yes                              | Yes                              | Contact your account team                          |
| Hostnames included                                                                                                                                                              | 100                              | 100                              | 100                              | Custom                                             |
| Max hostnames                                                                                                                                                                   | 50,000                           | 50,000                           | 50,000                           | Unlimited, but contact sales if using over 50,000. |
| Price per additional hostname                                                                                                                                                   | $0.10                            | $0.10                            | $0.10                            | Custom pricing                                     |
| [Custom analytics](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/hostname-analytics/)                                                          | Yes                              | Yes                              | Yes                              | Yes                                                |
| [Custom origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/)                                          | Yes                              | Yes                              | Yes                              | Yes                                                |
| [SNI Rewrite for Custom Origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/#sni-rewrites)             | No                               | No                               | No                               | Contact your account team                          |
| [Custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/)                      | No                               | No                               | No                               | Yes                                                |
| [CSR support](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/certificate-signing-requests/) | No                               | No                               | No                               | Yes                                                |
| [Selectable CA](https://developers.cloudflare.com/ssl/reference/certificate-authorities/)                                                                                       | No                               | No                               | No                               | Yes                                                |
| Wildcard custom hostnames                                                                                                                                                       | No                               | No                               | No                               | Yes                                                |
| Non-SNI support for SaaS zone                                                                                                                                                   | No                               | Yes                              | Yes                              | Yes                                                |
| [mTLS support](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/)                                    | No                               | No                               | No                               | Yes                                                |
| [WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/)                                                           | WAF rules with current zone plan | WAF rules with current zone plan | WAF rules with current zone plan | Create and apply custom firewall rulesets.         |
| [Apex proxying/BYOIP](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/)                                    | No                               | No                               | No                               | Paid add-on                                        |
| [Custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/)                                               | No                               | No                               | No                               | Paid add-on                                        |

## Enterprise plan benefits

The Enterprise plan offers features that give SaaS providers flexibility when it comes to meeting their end customer's requirements. In addition to that, Enterprise customers are able to extend all of the benefits of the Enterprise plan to their customer's custom hostnames. This includes advanced Bot Mitigation, WAF rules, analytics, DDoS mitigation, and more.

In addition, large SaaS providers rely on Enterprise level support, multi-user accounts, SSO, and other benefits that are not provided in non-Enterprise plans.

Note

Eligible 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.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/plans/","name":"Plans"}}]}
```

---

---
title: Certificate authorities
description: For publicly trusted certificates, Cloudflare partners with different certificate authorities (CAs). Refer to this page to check what CAs are used for each Cloudflare offering and for more details about the CAs features, limitations, and browser compatibility.
image: https://developers.cloudflare.com/core-services-preview.png
---

> 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.

[Skip to content](#%5Ftop) 

# Certificate authorities

For publicly trusted certificates, Cloudflare partners with different certificate authorities (CAs). Refer to this page to check what CAs are used for each Cloudflare offering and for more details about the CAs [features, limitations, and browser compatibility](#features-limitations-and-browser-compatibility).

## Availability per certificate type and encryption algorithm

| Certificate                                                                                                                                        | Algorithm                 | [Let's Encrypt](#lets-encrypt) | [Google Trust Services](#google-trust-services) | [SSL.com](#sslcom) | [Sectigo](#sectigo) |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------ | ----------------------------------------------- | ------------------ | ------------------- |
| [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/)                                                                | ECDSARSA(Paid plans only) | ✅✅                             | ✅✅                                              | ✅✅                 | N/AN/A              |
| [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)                                                  | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅  ✅               | N/AN/A              |
| [Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/)                                                 | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅  ✅               | N/AN/A              |
| [SSL for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/) | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅  ✅               | N/AN/A              |
| [Backup](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/)                                                             | ECDSARSA                  | ✅✅                             | ✅✅                                              | ✅✅                 | ✅✅                  |

## Features, limitations, and browser compatibility

Universal SSL

For Universal certificates, Cloudflare controls the validity periods and certificate authorities (CAs), making sure that renewal always occur. For details, refer to [Universal SSL](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/).

---

### Let's Encrypt

* Supports [validity periods](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) of 90 days.
* [DCV tokens](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) are valid for 7 days.

#### Limitations

* Hostname on certificate can contain up to 10 levels of subdomains.
* Duplicate certificate limit of [5 certificates ↗](https://letsencrypt.org/docs/rate-limits/) per week.
* Redsys[1](#user-content-fn-1) is not compatible with Let's Encrypt certificates. If you use Redsys and find issues with Let's Encrypt certificates, order an advanced certificate or upload a custom certificate to use a different CA.

#### Browser compatibility

Warning

This section summarizes commonly requested client support information. For the complete and most up-to-date certificate compatibility, refer to [Let's Encrypt documentation ↗](https://letsencrypt.org/docs/certificate-compatibility/).

The main determining factor for whether a platform can validate Let's Encrypt certificates is whether that platform trusts the self-signed ISRG Root X1 certificate. As Let's Encrypt announced a [change in its chain of trust in 2024 ↗](https://blog.cloudflare.com/shortening-lets-encrypt-change-of-trust-no-impact-to-cloudflare-customers/), older devices (for example Android 7.0 and earlier) that only trust the cross-signed version of the ISRG Root X1 are no longer compatible.

You can find the full list of supported clients in the [Let's Encrypt documentation ↗](https://letsencrypt.org/docs/certificate-compatibility/). Older versions of Android and Java clients might not be compatible with Let's Encrypt certificates.

#### Other resources

[Let's Encrypt Root CAs ↗](https://letsencrypt.org/certificates/): For checking compatibility between chain and client. As explained in [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/), you should **not** use this list for pinning against.

---

### Google Trust Services

* Supports [validity periods](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) of 14, 30, and 90 days.
* [DCV tokens](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) are valid for 14 days.

#### Browser compatibility (most compatible)

Warning

This section summarizes commonly requested client support information. For the complete and most up-to-date certificate compatibility, refer to [Google Trust Services documentation ↗](https://pki.goog/faq/).

By cross-signing with a [GlobalSign root CA ↗](https://valid.r1.roots.globalsign.com/) that has been installed in client devices for more than 20 years, Google Trust Services can ensure optimal support across a wide range of devices.

Currently trusted by Microsoft, Mozilla, Safari, Cisco, Oracle Java, and Qihoo’s 360 browser, all browsers or operating systems that depend on these root programs are covered.

You can use the [root CAs list ↗](https://pki.goog/faq/#connecting-to-google) for checking compatibility between chain and client but, as explained in [Certificate pinning](https://developers.cloudflare.com/ssl/reference/certificate-pinning/), you should **not** use this list for pinning against.

---

### SSL.com

* Supports [validity periods](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/) of 14, 30, and 90 days. Enterprise customers using [advanced certificates](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/) can also choose a validity period of one year.
* [DCV tokens](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/) are valid for 14 days.

#### Limitations

SSL.com DCV tokens are specific for RSA certificates and ECDSA certificates. This means that, for cases where you have to [manually perform DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/#partial-dns-setup---action-sometimes-required), you will have to place two validation tokens per certificate order. To avoid management overhead, consider using a [full setup](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/#full-dns-setup---no-action-required), or setting up [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/).

#### Browser compatibility

Warning

This section summarizes commonly requested client support information. For the complete and most up-to-date certificate compatibility, refer to [SSL.com documentation ↗](https://www.ssl.com/browser%5Fcompatibility/).

SSL.com is highly compatible, being accepted by over 99.9% of browsers, tablets, and mobile devices.

SSL.com certificates are [cross-signed with Certum ↗](https://www.ssl.com/repository/) and the [CA that cross-signs intermediates ↗](https://crt.sh/?caid=840) is from 2004.

#### Other resources

[Acceptable top level domains (TLDs) and current restrictions ↗](https://www.ssl.com/acceptable-top-level-domains-tlds-for-ssl-certificates/)

---

### Sectigo

* Only used for [Backup certificates](https://developers.cloudflare.com/ssl/edge-certificates/backup-certificates/).
* Backup certificates are valid for 90 days.

#### Browser compatibility

Refer to [Sectigo documentation ↗](https://www.sectigo.com/resource-library/sectigo-certificate-authority-root-keys).

---

## CAA records

A Certificate Authority Authorization (CAA) DNS record specifies which certificate authorities (CAs) are allowed to issue certificates for a domain. This record reduces the chance of unauthorized certificate issuance and promotes standardization across your organization.

  
If you are using Cloudflare as your DNS provider, then the CAA records will be added on your behalf. If you need to add CAA records, refer to [Add CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

The following table lists the CAA record content for each CA:

| Certificate authority | CAA record content                 |
| --------------------- | ---------------------------------- |
| Let's Encrypt         | letsencrypt.org                    |
| Google Trust Services | pki.goog; cansignhttpexchanges=yes |
| SSL.com               | ssl.com                            |
| Sectigo               | sectigo.com                        |

## Footnotes

1. A payment gateway used with some ecommerce plugins. [↩](#user-content-fnref-1)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-authorities/","name":"Certificate authorities"}}]}
```

---

---
title: Certificate statuses
description: Understand certificate statuses in Cloudflare SSL/TLS, including stages like Initializing, Pending Validation, and Active. Monitor via dashboard or command line.
image: https://developers.cloudflare.com/core-services-preview.png
---

> 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.

[Skip to content](#%5Ftop) 

# Certificate statuses

Certificates statuses show which stage of the issuance process each certificate is in.

## New certificates

When you order a new certificate, either an [edge certificate](https://developers.cloudflare.com/ssl/edge-certificates/) or a certificate used for a [custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/), its status will move through various stages as it progresses to Cloudflare's global network:

1. Initializing
2. Pending Validation
3. Pending Issuance
4. Pending Deployment
5. Active

Once you issue a certificate, it should be in **Pending Validation**, but change to **Active** after the validation is completed. If you see any errors, you or your customer may need to take additional actions to validate the certificate.

If you deactivate a certificate, it will become a **Deactivating** and then an **Inactive** status.

### Certificate replacement

When replacing a certificate, you may note a **Pending Cleanup** status. Old certificates are not deleted until the replacement has been successfully issued. This ensures TLS will not break for the hostname while the certificate is being replaced.

When the new certificate is successfully issued and activated, the status for the old certificate will transition from **Pending Cleanup**, and the certificate will be deleted.

## Custom certificates

If you are using a [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) and your [zone status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) is **Pending** or **Moved**, your certificate may have a status of **Holding Deployment**.

When your zone becomes active, your custom certificate will deploy automatically (also moving to an **Active** status).

If your zone is already active when you upload a custom certificate, you will not see this status.

## Staging certificates

When you create certificates in your [staging environment](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/), those staging certificates have their own set of statuses:

* **Staging deployment**: Similar to **Pending Deployment**, but for staging certificates.
* **Staging active**: Similar to **Active**, but for staging certificates.
* **Deactivating**: Your staging certificate is in the process of becoming **Inactive**.
* **Inactive**: Your staging certificate is not at the edge, but you can deploy it if needed.

## Client certificates

When you use [client certificates](https://developers.cloudflare.com/ssl/client-certificates/), those client certificates have their own set of statuses:

* **Active**: The client certificate is active.
* **Revoked**: The client certificate is revoked.
* **Pending Reactivation**: The client certificate was revoked, but it is being restored.
* **Pending Revocation**: The client certificate was active, but it is being revoked.

---

## Monitor certificate statuses

### SSL/TLS

Monitor a certificate's status on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page or by using the [Get Certificate Pack endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/get/).

For more details on certificate validation, refer to [Domain Control Validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

### SSL for SaaS

Monitor a certificate's status on the [**Custom Hostnames** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames) page or by using the [Custom Hostname Details endpoint](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/).

For more details on certificate validation, refer to [Issue and validate certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/).

### Via the command line

To view certificates, use `openssl` or your browser. The command below can be used in advance of your customer pointing the `app.example.com` hostname to the edge ([provided validation was completed](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/)).

Terminal window

```

openssl s_client -servername app.example.com -connect $CNAME_TARGET:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep app.example.com


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-statuses/","name":"Certificate statuses"}}]}
```

---

---
title: Connection request details
description: How Cloudflare sets Host headers and SNI when forwarding connections to your origin.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ TLS ](https://developers.cloudflare.com/search/?tags=TLS) 

# Connection request details

When forwarding connections to your origin server, Cloudflare will set request parameters according to the following:

## Host header

Cloudflare will not alter the Host header by default, and will forward exactly as sent by the client. If you wish to change the value of the Host header you can utilise [Page-Rules](https://developers.cloudflare.com/workers/configuration/workers-with-page-rules/) or [Workers](https://developers.cloudflare.com/workers/) using the steps outlined in [certificate management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/).

## SNI

When establishing a TLS connection to your origin server, if the request is being sent to your configured Fallback Host then the value of the SNI sent by Cloudflare will match the value of the Host header sent by the client (i.e. the custom hostname).

If however the request is being forwarded to a Custom Origin, then the value of the SNI will be that of the Custom Origin.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/connection-details/","name":"Connection request details"}}]}
```

---

---
title: Validation backoff schedule
description: Consider what happens if a domain control validation (DCV) fails and what schedule Cloudflare follows for new attempts and backoff.
image: https://developers.cloudflare.com/core-services-preview.png
---

> 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.

[Skip to content](#%5Ftop) 

# Validation backoff schedule

Domain control validation (DCV) has to happen before a certificate authority (CA) will issue a certificate for a domain. If DCV fails during issuance or renewal, Cloudflare automatically retries it on a schedule.

If you use [Delegated DCV](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/delegated-dcv/) or if [Cloudflare automatically performs DCV for you](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/), this page is only informational. If you have to manually perform DCV, consider the following sections about the validation schedule and remember that DCV tokens have a [fixed validity period](#dcv-tokens-validity).

Note

You can also request an immediate recheck by using the [Edit SSL Certificate Pack Validation Method endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/verification/methods/edit/), specifying the same `validation_method` as the [method](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/methods/) you currently use.

---

## DCV tokens validity

The DCV process relies on tokens that are generated by the issuing certificate authority. These tokens have a validity period defined by each CA:

* Google Trust Services - 14 days
* Let's Encrypt - 7 days
* SSL.com - 14 days

After this period, DCV tokens expire as dictated by the [CA/B Baseline Requirements ↗](https://cabforum.org/baseline-requirements-documents/), and new, valid tokens must be placed.

Warning

Tokens may also become invalid upon validation failure. For more details, refer to [Domain control validation flow](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/dcv-flow/#dcv-tokens).

---

## Successive checks function

Cloudflare caps the check backoff to a maximum of four hours to avoid the function growing exponentially, which would result in large gaps between checks towards the end of the month.

```

now() + min((floor(60 * pow(1.05, retry_attempt)) * INTERVAL '1 second'), INTERVAL '4 hours')


```

---

## Capped attempts reference table

As presented in the following table, most of the checks take place on the first day after the DCV token is generated.

In manual processes, it is possible that you fall behind schedule when you place the token, meaning that it may not be validated immediately.

In automatic processes, most validations complete within the first five minutes, unless there is a setup misconfiguration.

| Retry Attempt | In Seconds | In Minutes | In Hours |
| ------------- | ---------- | ---------- | -------- |
| 0             | 60         | 1.000      | 0.016667 |
| 1             | 63         | 1.050      | 0.017500 |
| 2             | 66         | 1.100      | 0.018333 |
| 3             | 69         | 1.150      | 0.019167 |
| 4             | 72         | 1.200      | 0.020000 |
| 5             | 76         | 1.267      | 0.021111 |
| 6             | 80         | 1.333      | 0.022222 |
| 7             | 84         | 1.400      | 0.023333 |
| 8             | 88         | 1.467      | 0.024444 |
| 9             | 93         | 1.550      | 0.025833 |
| 10            | 242        | 4.033      | 0.067222 |
| 11            | 279        | 4.650      | 0.077500 |
| 12            | 321        | 5.350      | 0.089167 |
| 13            | 369        | 6.150      | 0.102500 |
| 14            | 424        | 7.067      | 0.117778 |
| 15            | 488        | 8.133      | 0.135556 |
| 16            | 561        | 9.350      | 0.155833 |
| 17            | 645        | 10.750     | 0.179167 |
| 18            | 742        | 12.367     | 0.206111 |
| 19            | 853        | 14.217     | 0.236944 |
| 20            | 981        | 16.350     | 0.272500 |
| 21            | 1129       | 18.817     | 0.313611 |
| 22            | 1298       | 21.633     | 0.360556 |
| 23            | 1493       | 24.883     | 0.414722 |
| 24            | 1717       | 28.617     | 0.476944 |
| 25            | 1975       | 32.917     | 0.548611 |
| 26            | 2271       | 37.850     | 0.630833 |
| 27            | 2612       | 43.533     | 0.725556 |
| 28            | 3003       | 50.050     | 0.834167 |
| 29            | 3454       | 57.567     | 0.959444 |
| 30            | 3972       | 66.200     | 1.103333 |
| 31            | 4568       | 76.133     | 1.268889 |
| 32            | 5253       | 87.550     | 1.459167 |
| 33            | 6041       | 100.683    | 1.678056 |
| 34            | 6948       | 115.800    | 1.930000 |
| 35            | 7990       | 133.167    | 2.219444 |
| 36            | 9189       | 153.150    | 2.552500 |
| 37            | 10567      | 176.117    | 2.935278 |
| 38            | 12152      | 202.533    | 3.375556 |
| 39            | 13975      | 232.917    | 3.881944 |
| 40            | 14400      | 240.000    | 4.000000 |
| 41            | 14400      | 240.000    | 4.000000 |
| 42            | 14400      | 240.000    | 4.000000 |
| 43            | 14400      | 240.000    | 4.000000 |
| 44            | 14400      | 240.000    | 4.000000 |
| 45            | 14400      | 240.000    | 4.000000 |
| 46            | 14400      | 240.000    | 4.000000 |
| 47            | 14400      | 240.000    | 4.000000 |
| 48            | 14400      | 240.000    | 4.000000 |
| 49            | 14400      | 240.000    | 4.000000 |
| 50            | 14400      | 240.000    | 4.000000 |
| 51            | 14400      | 240.000    | 4.000000 |
| 52            | 14400      | 240.000    | 4.000000 |
| 53            | 14400      | 240.000    | 4.000000 |
| 54            | 14400      | 240.000    | 4.000000 |
| 55            | 14400      | 240.000    | 4.000000 |
| 56            | 14400      | 240.000    | 4.000000 |
| 57            | 14400      | 240.000    | 4.000000 |
| 58            | 14400      | 240.000    | 4.000000 |
| 59            | 14400      | 240.000    | 4.000000 |
| 60            | 14400      | 240.000    | 4.000000 |
| 61            | 14400      | 240.000    | 4.000000 |
| 62            | 14400      | 240.000    | 4.000000 |
| 63            | 14400      | 240.000    | 4.000000 |
| 64            | 14400      | 240.000    | 4.000000 |
| 65            | 14400      | 240.000    | 4.000000 |
| 66            | 14400      | 240.000    | 4.000000 |
| 67            | 14400      | 240.000    | 4.000000 |
| 68            | 14400      | 240.000    | 4.000000 |
| 69            | 14400      | 240.000    | 4.000000 |
| 70            | 14400      | 240.000    | 4.000000 |
| 71            | 14400      | 240.000    | 4.000000 |
| 72            | 14400      | 240.000    | 4.000000 |
| 73            | 14400      | 240.000    | 4.000000 |
| 74            | 14400      | 240.000    | 4.000000 |
| 75            | 14400      | 240.000    | 4.000000 |
| 76            | 14400      | 240.000    | 4.000000 |
| 77            | 14400      | 240.000    | 4.000000 |
| 78            | 14400      | 240.000    | 4.000000 |
| 79            | 14400      | 240.000    | 4.000000 |
| 80            | 14400      | 240.000    | 4.000000 |
| 81            | 14400      | 240.000    | 4.000000 |
| 82            | 14400      | 240.000    | 4.000000 |
| 83            | 14400      | 240.000    | 4.000000 |
| 84            | 14400      | 240.000    | 4.000000 |
| 85            | 14400      | 240.000    | 4.000000 |
| 86            | 14400      | 240.000    | 4.000000 |
| 87            | 14400      | 240.000    | 4.000000 |
| 88            | 14400      | 240.000    | 4.000000 |
| 89            | 14400      | 240.000    | 4.000000 |
| 90            | 14400      | 240.000    | 4.000000 |
| 91            | 14400      | 240.000    | 4.000000 |
| 92            | 14400      | 240.000    | 4.000000 |
| 93            | 14400      | 240.000    | 4.000000 |
| 94            | 14400      | 240.000    | 4.000000 |
| 95            | 14400      | 240.000    | 4.000000 |
| 96            | 14400      | 240.000    | 4.000000 |
| 97            | 14400      | 240.000    | 4.000000 |
| 98            | 14400      | 240.000    | 4.000000 |
| 99            | 14400      | 240.000    | 4.000000 |
| 100           | 14400      | 240.000    | 4.000000 |
| 101           | 14400      | 240.000    | 4.000000 |
| 102           | 14400      | 240.000    | 4.000000 |
| 103           | 14400      | 240.000    | 4.000000 |
| 104           | 14400      | 240.000    | 4.000000 |
| 105           | 14400      | 240.000    | 4.000000 |
| 106           | 14400      | 240.000    | 4.000000 |
| 107           | 14400      | 240.000    | 4.000000 |
| 108           | 14400      | 240.000    | 4.000000 |
| 109           | 14400      | 240.000    | 4.000000 |
| 110           | 14400      | 240.000    | 4.000000 |
| 111           | 14400      | 240.000    | 4.000000 |
| 112           | 14400      | 240.000    | 4.000000 |
| 113           | 14400      | 240.000    | 4.000000 |
| 114           | 14400      | 240.000    | 4.000000 |
| 115           | 14400      | 240.000    | 4.000000 |
| 116           | 14400      | 240.000    | 4.000000 |
| 117           | 14400      | 240.000    | 4.000000 |
| 118           | 14400      | 240.000    | 4.000000 |
| 119           | 14400      | 240.000    | 4.000000 |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/edge-certificates/","name":"Edge certificates"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/","name":"Domain control validation (DCV)"}},{"@type":"ListItem","position":5,"item":{"@id":"/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/","name":"Validation backoff schedule"}}]}
```

---

---
title: Certificate and hostname priority
description: Learn about how Cloudflare decides which certificate and associated SSL/TLS settings to apply to individual hostnames.
image: https://developers.cloudflare.com/core-services-preview.png
---

> 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.

[Skip to content](#%5Ftop) 

# Certificate and hostname priority

When a new certificate is created, Cloudflare first deploys the certificate and then serves it.

---

## Certificate deployment

For any given hostname, Cloudflare uses the following order to determine which certificate (and associated TLS settings) to apply to that hostname:

1. **Hostname specificity**: A specific subdomain certificate (`www.example.com`) would take precedence over a wildcard certificate (`*.example.com`) for requests to `www.example.com`.
2. **Zone specificity**: A specific subdomain certificate (`www.example.com`) would take precedence over a custom hostname certificate if the domain is active as a zone on Cloudflare.
3. **Certificate priority**: If the hostname is the same, certain types of certificates take precedence over others.  
| Priority | Certificate Type                                                                                                         |  
| -------- | ------------------------------------------------------------------------------------------------------------------------ |  
| 1        | [Keyless SSL](https://developers.cloudflare.com/ssl/keyless-ssl/)                                                        |  
| 2        | [Custom Legacy](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)                            |  
| 3        | [Custom Modern](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/)                            |  
| 4        | [Custom Hostname (Cloudflare for SaaS)](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) |  
| 5        | [Advanced](https://developers.cloudflare.com/ssl/edge-certificates/advanced-certificate-manager/)                        |  
| 6        | [Advanced - Total TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/total-tls/)            |  
| 7        | [Universal](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/)                                      |
4. **Certificate expiration**: The most recently ordered certificate takes precedence unless a certificate deletion has occurred. If and when a certificate is deleted, the certificate with the latest expiration date is deployed.

Note

In this case, when the certificate with the closest expiration date is renewed, it will then become the one with the latest expiration date and get presented.

---

## Certificate presentation

Cloudflare uses the following order to determine the certificate and settings used during a TLS handshake:

1. **SNI match**: Certificates and settings that match the SNI hostname _exactly_ take precedence.
2. **SNI wildcard match**: If there is not an exact match between the hostname and SNI hostname, Cloudflare uses certificates and settings that match an SNI wildcard.
3. **IP address**: If no SNI is presented, Cloudflare uses certificate based on the IP address (the hostname can support TLS handshakes made without SNI).

---

## Hostname priority

When multiple proxied DNS records exist for a hostname, in multiple zones — usually due to [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) — only one record will control the zone settings and associated origin server.

Cloudflare determines this priority in the following order, assuming each record exists and is proxied (orange-clouded):

1. **Exact hostname match**:  
   1. [New custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) (belonging to a SaaS provider)  
   2. [Legacy custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/reference/versioning/) (belonging to a SaaS provider)  
   3. [DNS](https://developers.cloudflare.com/dns/proxy-status/) (belonging to the logical DNS zone)
2. **Wildcard hostname match**:  
   1. DNS (belonging to the logical DNS zone)  
   2. New custom hostname (belonging to a SaaS provider)

If a hostname resource record is not proxied (gray-clouded) for a zone on Cloudflare, that zone's settings are not applied and any settings configured at the associated origin are applied instead. This origin could be another zone on Cloudflare or any other server.

### Example scenarios

#### Scenario 1

Customer1 uses Cloudflare as authoritative DNS for the zone `shop.example.com`. Customer2 is a SaaS provider that creates and successfully [verifies the new custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/) `shop.example.com`. Afterward, traffic starts routing over Customer2's zone:

* If Customer1 wants to regain control of their zone, Customer1 contacts Customer2 and requests them to delete the custom hostname record. Customer1 should make sure to have their record target updated to something other than the SaaS provider target, otherwise Customer1 would get a [1014 error](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1014/).
* If Customer1 already has a proxied record for `www.example.com` when Customer2 creates and verifies a new custom hostname `www.example.com`, [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) applies.
* If Customer1 already has a proxied record for `www.example.com` in a legacy custom hostname setup (with another SaaS provider, Customer3) and Customer2 creates and verifies a new wildcard custom hostname for `*.example.com`, legacy custom hostname on Customer3 platform takes precedence due to exact hostname match.

#### Scenario 2

A customer has a [proxied](https://developers.cloudflare.com/dns/proxy-status/) DNS record for their domain. The customer's zone on Cloudflare is using a Free plan.

This customer is also using a SaaS provider that uses Cloudflare for SaaS. The SaaS provider is using a Cloudflare Enterprise plan.

If the provider is using a wildcard custom hostname, then the original customer's plan limits will take precedence over the provider's plan limits (Cloudflare will treat the zone as a Free zone). To apply the Enterprise limits through Cloudflare for SaaS, the original customer's zone would need to either use a [DNS-only](https://developers.cloudflare.com/dns/proxy-status/) record or the SaaS provider would need to use an exact hostname match.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-and-hostname-priority/","name":"Certificate and hostname priority"}}]}
```

---

---
title: Custom CSRs
description: HTTP status codes for certificate signing request API endpoints.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom CSRs

## Success codes

| Endpoint                                              | Method | HTTP Status Code |
| ----------------------------------------------------- | ------ | ---------------- |
| /api/v4/zones/:zone\_id/custom\_csrs                  | POST   | 201 Created      |
| /api/v4/zones/:zone\_id/custom\_csrs                  | GET    | 200 OK           |
| /api/v4/zones/:zone\_id/custom\_csrs/:custom\_csr\_id | GET    | 200 OK           |
| /api/v4/zones/:zone\_id/custom\_csrs/:custom\_csr\_id | DELETE | 200 OK           |

## Error codes

| HTTP Status Code | API Error Code | Error Message                                                                                                                                                                                                                                                                                                                                   |
| ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400              | 1400           | Unable to decode the JSON request body. Check your input and try again.                                                                                                                                                                                                                                                                         |
| 400              | 1401           | Zone ID is required. Check your input and try again.                                                                                                                                                                                                                                                                                            |
| 400              | 1402           | The request has no Authorization header. Check your input and try again.                                                                                                                                                                                                                                                                        |
| 400              | 1405           | Country field is required. Check your input and try again.                                                                                                                                                                                                                                                                                      |
| 400              | 1406           | State field is required. Check your input and try again.                                                                                                                                                                                                                                                                                        |
| 400              | 1407           | Locality field is required. Check your input and try again.                                                                                                                                                                                                                                                                                     |
| 400              | 1408           | Organization field is required. Check your input and try again.                                                                                                                                                                                                                                                                                 |
| 400              | 1409           | Common Name field is required. Check your input and try again.                                                                                                                                                                                                                                                                                  |
| 400              | 1410           | The specified Common Name is too long. Maximum allowed length is %d characters. Check your input and try again.                                                                                                                                                                                                                                 |
| 400              | 1411           | At least one subject alternative name (SAN) is required. Check your input and try again.                                                                                                                                                                                                                                                        |
| 400              | 1412           | Invalid subject alternative name(s) (SAN). SANs have to be smaller than 256 characters in length, cannot be IP addresses, cannot contain any special characters such as \~\`!@#$%^&\*()=+\[\]                                                                                                                                                   |
| 400              | 1413           | Subject Alternative Names (SANs) with non-ASCII characters are not supported. Check your input and try again.                                                                                                                                                                                                                                   |
| 400              | 1414           | Reserved top domain subject alternative names (SAN), such as 'test', 'example', 'invalid' or 'localhost', is not supported. Check your input and try again.                                                                                                                                                                                     |
| 400              | 1415           | Unable to parse subject alternative name(s) (SAN) - :reason. Check your input and try again. Reasons: publicsuffix: cannot derive eTLD+1 for domain %q; publicsuffix: invalid public suffix %q for domain %q;                                                                                                                                   |
| 400              | 1416           | Subject Alternative Names (SANs) ending in example.com, example.net, or example.org are prohibited. Check your input and try again.                                                                                                                                                                                                             |
| 400              | 1417           | Invalid key type. Only 'rsa2048' or 'p256v1' is accepted. Check your input and try again.                                                                                                                                                                                                                                                       |
| 400              | 1418           | The custom CSR ID is invalid. Check your input and try again.                                                                                                                                                                                                                                                                                   |
| 401              | 1000           | Unable to extract bearer token                                                                                                                                                                                                                                                                                                                  |
| 401              | 1001           | Unable to parse JWT token                                                                                                                                                                                                                                                                                                                       |
| 401              | 1002           | Bad JWT header                                                                                                                                                                                                                                                                                                                                  |
| 401              | 1003           | Failed to verify JWT token                                                                                                                                                                                                                                                                                                                      |
| 401              | 1004           | Failed to get claims from JWT token                                                                                                                                                                                                                                                                                                             |
| 401              | 1005           | JWT token does not have required claims                                                                                                                                                                                                                                                                                                         |
| 403              | 1403           | No quota has been allocated for this zone. If you are already a paid Cloudflare for SaaS customer, contact your Customer Success Manager for additional provisioning. If you are not yet enrolled, [fill out this contact form ↗](https://www.cloudflare.com/plans/enterprise/contact/) and our sales team will contact you.                    |
| 403              | 1404           | Access to generating CSRs has not been granted for this zone. If you are already a paid Cloudflare for SaaS customer, contact your Customer Success Manager for additional provisioning. If you are not yet enrolled, [fill out this contact form ↗](https://www.cloudflare.com/plans/enterprise/contact/) and our sales team will contact you. |
| 404              | 1419           | The custom CSR was not found.                                                                                                                                                                                                                                                                                                                   |
| 409              | 1420           | The custom CSR is associated with an active certificate pack. You will need to delete all associated active certificate packs before you can delete the custom CSR.                                                                                                                                                                             |
| 500              | 1500           | Internal Server Error                                                                                                                                                                                                                                                                                                                           |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/status-codes/","name":"Status codes"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/status-codes/custom-csrs/","name":"Custom CSRs"}}]}
```

---

---
title: Custom hostnames
description: HTTP status codes for custom hostname API endpoints.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom hostnames

---

## Success codes

| Endpoint                                                    | Method | Code         |
| ----------------------------------------------------------- | ------ | ------------ |
| /v4/zones/:zone\_id/custom\_hostnames                       | POST   | 201 Created  |
| /v4/zones/:zone\_id/custom\_hostnames/:custom\_hostname\_id | GET    | 200 OK       |
| /v4/zones/:zone\_id/custom\_hostnames                       | GET    | 200 OK       |
| /v4/zones/:zone\_id/custom\_hostnames/:custom\_hostname\_id | DELETE | 200 OK       |
| /v4/zones/:zone\_id/custom\_hostnames/:custom\_hostname\_id | PATCH  | 202 Accepted |

---

## Error codes

| HTTP Status Code | API Error Code | Error Message                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 400              | 1400           | Unable to decode the JSON request body. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                          |
| 400              | 1401           | Unable to encode the Custom Metadata as JSON. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                    |
| 400              | 1402           | Zone ID is required. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                                             |
| 400              | 1403           | The request has no Authorization header. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                         |
| 400              | 1407           | Invalid custom hostname. Custom hostnames have to be smaller than 256 characters in length, cannot be IP addresses, cannot contain any special characters such as \`\`\~\`!@#$%^&\*()=+\[\]\\                                                                                                                                                                                                                                                    |
| 400              | 1408           | Custom hostnames with non-ASCII characters are not supported. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                    |
| 400              | 1409           | Reserved top domain custom hostnames, such as 'test', 'example', 'invalid' or 'localhost', is not supported. Check your input and try again.                                                                                                                                                                                                                                                                                                     |
| 400              | 1410           | Unable to parse custom hostname - :reason. Check your input and try again. **Reasons:**  publicsuffix: cannot derive eTLD+1 for domain :domain  publicsuffix: invalid public suffix :suffix for domain :domain                                                                                                                                                                                                                                   |
| 400              | 1411           | Custom hostnames ending in example.com, example.net, or example.org are prohibited. Check your input and try again.                                                                                                                                                                                                                                                                                                                              |
| 400              | 1412           | Custom metadata for wildcard custom hostnames is not supported. Check your input and try again. **Note:**  This message is only presented to customers who have opted out of wildcard support for custom metadata.                                                                                                                                                                                                                               |
| 400              | 1415           | Invalid custom origin hostname. Custom origin hostnames have to be smaller than 256 characters in length, cannot be IP addresses, cannot contain any special characters such as ~~\`\`~~\`!@#$%^&\*()=+\[\]\\                                                                                                                                                                                                                                    |
| 400              | 1416           | Custom origin hostnames with non-ASCII characters are not supported. Check your input and try again.                                                                                                                                                                                                                                                                                                                                             |
| 400              | 1417           | Reserved top domain custom origin hostnames, such as 'test', 'example', 'invalid' or 'localhost', is not supported. Check your input and try again.                                                                                                                                                                                                                                                                                              |
| 400              | 1418           | Unable to parse custom origin hostname - :reason. Check your input and try again. **Reasons:**  publicsuffix: cannot derive eTLD+1 for domain :domain publicsuffix: invalid public suffix:suffixfor domain:domain                                                                                                                                                                                                                                |
| 400              | 1419           | Custom origin hostnames ending in example.com, example.net, or example.org are prohibited. Check your input and try again.                                                                                                                                                                                                                                                                                                                       |
| 400              | 1420           | Wildcard custom origin hostnames are not supported. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                              |
| 400              | 1421           | The custom origin hostname you specified does not exist on Cloudflare as a DNS record (A, AAAA or CNAME) in your zone::zone\\\_tag. Check your input and try again.                                                                                                                                                                                                                                                                              |
| 400              | 1422           | Invalid http2setting. Only 'on' or 'off' is accepted. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                            |
| 400              | 1423           | Invalidtls\\\_1\\\_2\\\_onlysetting. Only 'on' or 'off' is accepted. Check your input and try again.                                                                                                                                                                                                                                                                                                                                             |
| 400              | 1424           | Invalidtls\\\_1\\\_3setting. Only 'on' or 'off' is accepted. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                     |
| 400              | 1425           | Invalidmin\\\_tls\\\_versionsetting. Only '1.0','1.1','1.2' or '1.3' is accepted. Check your input and try again.                                                                                                                                                                                                                                                                                                                                |
| 400              | 1426           | The certificate that you uploaded cannot be parsed. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                              |
| 400              | 1427           | The certificate that you uploaded is empty. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                      |
| 400              | 1428           | The private key you uploaded cannot be parsed. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                   |
| 400              | 1429           | The private key you uploaded does not match the certificate. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                     |
| 400              | 1430           | The custom CSR ID is invalid. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                                    |
| 404              | 1431           | The custom CSR was not found.                                                                                                                                                                                                                                                                                                                                                                                                                    |
| 400              | 1432           | The validation method is not supported. Onlyhttp, email, or txt are accepted. Check your input and try again.                                                                                                                                                                                                                                                                                                                                    |
| 400              | 1433           | The validation type is not supported. Only 'dv' is accepted. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                     |
| 400              | 1434           | The SSL attribute is invalid. Refer to the API documentation, check your input and try again.                                                                                                                                                                                                                                                                                                                                                    |
| 400              | 1435           | The custom hostname ID is invalid. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                               |
| 404              | 1436           | The custom hostname was not found.                                                                                                                                                                                                                                                                                                                                                                                                               |
| 400              | 1437           | Invalid hostname.contain query parameter. The hostname.contain query parameter has to be smaller than 256 characters in length, cannot be IP addresses, cannot contain any special characters such as \`\`\~\`!@#$%^&\*()=+\[\]\\                                                                                                                                                                                                                |
| 400              | 1438           | Cannot specify other filter parameters in addition to id. Only one must be specified. Check your input and try again.                                                                                                                                                                                                                                                                                                                            |
| 409              | 1439           | Modifying the custom hostname is not supported. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                                  |
| 400              | 1440           | Both validation type and validation method are required. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                         |
| 400              | 1441           | The certificate that you uploaded is having trouble bundling against the public trust store. Check your input and try again.                                                                                                                                                                                                                                                                                                                     |
| 400              | 1442           | Invalid ciphers setting. Refer to the documentation for the list of accepted cipher suites. Check your input and try again.                                                                                                                                                                                                                                                                                                                      |
| 400              | 1443           | Cipher suite selection is not supported for a minimum TLS version of 1.3\. Check your input and try again.                                                                                                                                                                                                                                                                                                                                       |
| 400              | 1444           | The certificate chain that you uploaded has multiple leaf certificates. Check your input and try again.                                                                                                                                                                                                                                                                                                                                          |
| 400              | 1445           | The certificate chain that you uploaded has no leaf certificates. Check your input and try again.                                                                                                                                                                                                                                                                                                                                                |
| 400              | 1446           | The certificate that you uploaded does not include the custom hostname - :custom\_hostname. Review your input and try again.                                                                                                                                                                                                                                                                                                                     |
| 400              | 1447           | The certificate that you uploaded does not use a supported signature algorithm. Only SHA-256/ECDSA, SHA-256/RSA, and SHA-1/RSA signature algorithms are supported. Review your input and try again.                                                                                                                                                                                                                                              |
| 400              | 1448           | Custom hostnames with wildcards are not supported for certificates managed by Cloudflare. Review your input and try again.                                                                                                                                                                                                                                                                                                                       |
| 400              | 1449           | The request input bundle\_method must be one of: ubiquitous, optimal, force.                                                                                                                                                                                                                                                                                                                                                                     |
| 401              | 1000           | Unable to extract bearer token                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 401              | 1001           | Unable to parse JWT token                                                                                                                                                                                                                                                                                                                                                                                                                        |
| 401              | 1002           | Bad JWT header                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 401              | 1003           | Failed to verify JWT token                                                                                                                                                                                                                                                                                                                                                                                                                       |
| 401              | 1004           | Failed to get claims from JWT token                                                                                                                                                                                                                                                                                                                                                                                                              |
| 401              | 1005           | JWT token does not have required claims                                                                                                                                                                                                                                                                                                                                                                                                          |
| 403              | 1404           | No quota has been allocated for this zone. If you are already a paid Cloudflare for SaaS customer, contact your Customer Success Manager for additional provisioning. If you are not yet enrolled, [fill out this contact form ↗](https://www.cloudflare.com/plans/enterprise/contact/) and our sales team will reach out to you.                                                                                                                |
| 403              | 1405           | Quota exceeded. If you are already a paid Cloudflare for SaaS customer, contact your Customer Success Manager for additional provisioning. If you are not yet enrolled, [fill out this contact form ↗](https://www.cloudflare.com/plans/enterprise/contact/) and our sales team will reach out to you.                                                                                                                                           |
| 403              | 1413           | No [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) access has been allocated for this zone. If you are already a paid customer, contact your Customer Success Manager for additional provisioning. If you are not yet enrolled, [fill out this contact form ↗](https://www.cloudflare.com/plans/enterprise/contact/) and our sales team will reach out to you. |
| 403              | 1414           | Access to setting a custom origin server has not been granted for this zone. If you are already a paid Cloudflare for SaaS customer, contact your Customer Success Manager for additional provisioning. If you are not yet enrolled, [fill out this contact form ↗](https://www.cloudflare.com/plans/enterprise/contact/) and our sales team will reach out to you.                                                                              |
| 409              | 1406           | Duplicate custom hostname found.                                                                                                                                                                                                                                                                                                                                                                                                                 |
| 500              | 1500           | Internal Server Error                                                                                                                                                                                                                                                                                                                                                                                                                            |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/status-codes/","name":"Status codes"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/status-codes/custom-hostnames/","name":"Custom hostnames"}}]}
```

---

---
title: Token validity periods
description: DCV token expiration periods by certificate authority for TXT validation.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Token validity periods

When you perform [TXT](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/) domain control validation, you will need to share these tokens with your customers.

However, these tokens expire after a certain amount of time, depending on your chosen certificate authority.

| Certificate authority | Token validity |
| --------------------- | -------------- |
| Let's Encrypt         | 7 days         |
| Google Trust Services | 14 days        |
| SSL.com               | 14 days        |

Warning

Tokens may also become invalid upon validation failure. For more details, refer to [Domain control validation flow](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/dcv-flow/#dcv-tokens).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/token-validity-periods/","name":"Token validity periods"}}]}
```

---

---
title: Troubleshooting
description: Resolve common issues with custom hostnames, certificates, and rate limits.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## Rate limits

By default, you may issue up to 15 certificates per minute. Only successful submissions (POSTs that return 200) are counted towards your limit. If you exceed your limit, you will be prevented from issuing new certificates for 30 seconds.

If you require a higher rate limit, contact your Customer Success Manager.

---

## Purge cache

To remove specific files from Cloudflare’s cache, [purge the cache](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-hostname/) while specifying one or more hostnames.

---

## Resolution error 1016 (Origin DNS error) when accessing the custom hostname

Cloudflare returns a 1016 error when the custom hostname cannot be routed or proxied.

There are three main causes of error 1016:

1. Custom Hostname ownership validation is not complete. To check validation status, run an API call to [search for a certificate by hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/common-api-calls/) and check the verification error field: `"verification_errors": ["custom hostname does not CNAME to this zone."]`.
2. Fallback Origin is not [correctly set](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin). Confirm that you have created a DNS record for the fallback origin and also set the fallback origin.
3. A Wildcard Custom Hostname has been created, but the requested hostname is associated with a domain that exists in Cloudflare as a standalone zone. In this case, the [hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority) for the standalone zone will take precedence over the wildcard custom hostname. This behavior applies even if there is no DNS record for this standalone zone hostname.

In this scenario each hostname that needs to be served by the [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) parent zone needs to be added as an individual Custom Hostname.

Note

If you encounter other 1XXX errors, refer to [Troubleshooting Cloudflare 1XXX Errors](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/).

---

## Old SaaS provider content after updating a CNAME

When switching SaaS providers, an older configuration can take precedence if the old provider provisioned a specific custom hostname and the new provider provisioned a wildcard custom hostname. This is expected as per the [certificate and hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority).

In this case there are two ways forward:

* (Recommended) Ask the new SaaS provider to provision a specific custom hostname for you instead of the wildcard - `mystore.example.com` instead of `*.example.com`.
* Ask the Super Administrator of your account to contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) to request an update of the SaaS configuration.

---

## Custom hostname in Moved status

To move a custom hostname back to an Active status, send a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) to restart the hostname validation. A Custom Hostname in a Moved status is deleted after 7 days.

In some circumstances, custom hostnames can also enter a **Moved** state if your customer changes their DNS records pointing to your SaaS service. For more details, refer to [Remove custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/remove-custom-hostnames/).

---

## CAA Errors

The `caa_error` in the status of a custom hostname means that the CAA records configured on the domain prevented the Certificate Authority to issue the certificate.

You can check which CAA records are configured on a domain using the `dig` command:`dig CAA example.com`

You will need to ensure that the required CAA records for the selected Certificate Authority are configured. For example, here are the records required to issue [Let's Encrypt ↗](https://letsencrypt.org/docs/caa/) and [Google Trust Services ↗](https://pki.goog/faq/#caa) certificates:

```

example.com CAA 0 issue "pki.goog; cansignhttpexchanges=yes"

example.com CAA 0 issuewild "pki.goog; cansignhttpexchanges=yes"


example.com CAA 0 issue "letsencrypt.org"

example.com CAA 0 issuewild "letsencrypt.org"


example.com CAA 0 issue "ssl.com"

example.com CAA 0 issuewild "ssl.com"


```

For more details, refer to [CAA records FAQ](https://developers.cloudflare.com/ssl/faq/#caa-records).

---

## Custom hostname matches zone name (403 Forbidden)

Do not configure a custom hostname which matches the zone name. For example, if your SaaS zone is `example.com`, do not create a custom hostname named `example.com`.

This configuration will cause a 403 Forbidden error due to DNS override restrictions applied for security reasons. This limitation also affects Worker Routes making subrequests.

---

## Older devices have issues connecting

As Let's Encrypt - one of the [certificate authorities (CAs)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) used by Cloudflare - has announced changes in its [chain of trust](https://developers.cloudflare.com/ssl/concepts/#chain-of-trust), starting September 9, 2024, there may be issues with older devices trying to connect to your custom hostname certificate.

Consider the following solutions:

* Use the [Edit Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) endpoint to set the `certificate_authority` parameter to an empty string (`""`): this sets the custom hostname certificate to "default CA", leaving the choice up to Cloudflare. Cloudflare will always attempt to issue the certificate from a more compatible CA, such as [Google Trust Services](https://developers.cloudflare.com/ssl/reference/certificate-authorities/#google-trust-services), and will only fall back to using Let’s Encrypt if there is a [CAA record](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/) in place that blocks Google from issuing a certificate.  
Example API call  
Terminal window  
```  
curl --request PATCH \  
"https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_hostnames/{custom_hostname_id}" \  
--header "X-Auth-Email: <EMAIL>" \  
--header "X-Auth-Key: <API_KEY>" \  
--header "Content-Type: application/json" \  
--data '{  
  "ssl": {  
      "method": "txt",  
      "type": "dv",  
      "certificate_authority": ""  
  }  
}'  
```
* Use the [Edit Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) endpoint to set the `certificate_authority` parameter to `google`: this sets Google Trust Services as the CA for your custom hostnames. In your API call, make sure to also include `method` and `type` in the `ssl` object.
* If you are using a custom certificate for your custom hostname, refer to the [custom certificates troubleshooting](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/troubleshooting/#lets-encrypt-chain-update).

## Custom hostname fails to verify because the zone is held

The [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/) is a toggle that will prevent their zone from being activated on other Cloudflare account. When enabled, Cloudflare is not able to issue an SSL/TLS certificate on behalf of that domain name for either a zone or custom hostname. When the option `Also prevent subdomains` is enabled, this prevents the verification of custom hostnames for this domain. The custom hostname will remain in the `Blocked` status, with the following error message: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.` In this case, the owner of the zone needs to [release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds) before the custom hostname can become activated. After the hostname has been validated, the zone hold can be enabled again.

## Hostnames over 64 characters

The Common Name (CN) restriction establishes a limit of 64 characters ([RFC 5280 ↗](https://www.rfc-editor.org/rfc/rfc5280.html)). If you have a hostname that exceeds this length, you may find the following error:

```

Since no host is 64 characters or fewer, Cloudflare Branding is required. Please check your input and try again. (1469)


```

To solve this, you can set `cloudflare_branding` to `true` when [creating your custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/#hostnames-over-64-characters) via API.

Cloudflare branding means that `sni.cloudflaressl.com` will be added as the certificate Common Name (CN) and the long hostname will be included as a part of the Subject Alternative Name (SAN).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: Deprecation - Version 1
description: Deprecation notice and migration guide for SSL for SaaS Version 1.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ Migration ](https://developers.cloudflare.com/search/?tags=Migration) 

# Deprecation - Version 1

The first version of SSL for SaaS will be deprecated on September 1, 2021.

## Why is SSL for SaaS changing?

In SSL for SaaS v1, traffic for Custom Hostnames is proxied to the origin based on the IP addresses assigned to the zone with SSL for SaaS enabled. This IP-based routing introduces complexities that prevented customers from making changes with zero downtime.

SSL for SaaS v2 removes IP-based routing and its associated problems. Instead, traffic is proxied to the origin based on the custom hostname of the SaaS zone. This means that Custom Hostnames will now need to pass a **hostname verification** step after Custom Hostname creation and in addition to SSL certificate validation. This adds a layer of security from SSL for SaaS v1 by ensuring that only verified hostnames are proxied to your origin.

## What action is needed?

To ensure that your service is not disrupted, you need to perform an additional ownership check on every new Custom Hostname. There are three methods to verify ownership: TXT, HTTP, and CNAME. Use TXT and HTTP for pre-validation to validate the Custom Hostname before traffic is proxied by Cloudflare’s edge.

### Recommended validation methods

Using a [TXT](#dns-txt-record) or [HTTP](#http-token) validation method helps you avoid downtime during your migration. If you choose to use [CNAME validation](#cname-validation), your domain might fall behind on its [backoff schedule](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/).

#### DNS TXT Record

When creating a Custom Hostname with the TXT method through the [API](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/), a TXT ownership\_verification record is provided for your customer to add to their DNS for the ownership validation check. When the TXT record is added, the Custom Hostname will be marked as **Active** in the Cloudflare SSL/TLS app under the Custom Hostnames tab.

#### HTTP Token

When creating a Custom Hostname with the HTTP through the [API](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/), an HTTP ownership\_verification token is provided. HTTP verification is used mainly by organizations with a large deployed base of custom domains with HTTPS support. Serving the HTTP token from your origin web server allows hostname verification before proxying domain traffic through Cloudflare.

Cloudflare sends GET requests to the http\_url using `User-Agent: Cloudflare Custom Hostname Verification`.

If you validated a hostname that is not proxying traffic through Cloudflare, the Custom Hostname will be marked as **Active** in the Cloudflare SSL/TLS app when the HTTP token is verified (under the **Custom Hostnames** tab).

If your hostname is already proxying traffic through Cloudflare, then HTTP validation is not enough by itself and the hostname will only go active when DNS-based validation is complete.

### Other validation methods

Though you can use [CNAME validation](#cname-validation), we recommend you either use a [TXT](#dns-txt-record) or [HTTP](#http-token) validation method.

#### CNAME Validation

Custom Hostnames can also be validated once Cloudflare detects that the Custom Hostname is a CNAME record pointing to the fallback record configured for the SSL for SaaS domain. Though this is the simplest validation method, it increases the risk of errors. Since a CNAME record would also route traffic to Cloudflare’s edge, traffic may reach our edge before the Custom Hostname has completed validation or the SSL certificate has issued.

Once you have tested and added the hostname validation step to your Custom Hostname creation process, please contact your account team to schedule a date to migrate your SSL for SaaS v1 zones. Your account team will work with you to validate your existing Custom Hostnames without downtime.

## If you are using BYOIP or Apex Proxying:

Both BYOIP addresses and IP addresses configured for Apex Proxying allow for hostname validation to complete successfully by having either a BYOIP address or an Apex Proxy IP address as the target of a DNS A record for a custom hostname.

## What is available in the new version of SSL for SaaS?

SSL for SaaS v2 is functionally equivalent to SSL for SaaS v1, but removes the requirements to use specific anycast IP addresses at Cloudflare’s edge and Cloudflare’s Universal SSL product with the SSL for SaaS zone.

Note

SSL for SaaS v2 is now called Cloudflare for SaaS.

## What happens during the migration?

Once the migration has been started for your zone(s), Cloudflare will require every Custom Hostname to pass a hostname verification check. Existing Custom Hostnames that are proxying to Cloudflare with a DNS CNAME record will automatically re-validate and migrate to the new version with no downtime. Any Custom Hostnames created after the start of the migration will need to pass the hostname validation check using one of the validation methods mentioned above.

Note

You can revert the migration at any time.

### Before the migration

Before your migration, you should:

1. To test validation methods, set up a test zone and ask your account team to enable SSL for SaaS v2.
2. Wait for your account team to run our pre-migration tool. This tool groups your hostnames into one of the following statuses:  
   * `test_pending`: In the process of being verified or was unable to be verified and re-queued for verification. A custom hostname will be re-queued 25 times before moving to the `test_failed` status.  
   * `test_active`: Passed CNAME verification  
   * `test_active_apex`: Passed Apex Proxy verification  
   * `test_blocked`: Hostname will be blocked during the migration because hostname belongs to a banned zone. Contact your account team to verify banned custom hostnames and proceed with the migration.  
   * `test_failed`: Failed hostname verification 25 times
3. Review the results of our pre-migration tool (run by your account team) using one of the following methods:  
   * Via the API: `https://api.cloudflare.com/client/v4/zones/{zone_tag}/custom_hostnames?hostname_status={status}`  
   * Via a CSV file (provided by your account team)  
   * Via the Cloudflare dashboard:![Review SSL migration status in the dashboard](https://developers.cloudflare.com/_astro/ssl-migration-status.CLPmua84_25MgVb.webp)
4. Approve the migration. Your account team will work with you to schedule a migration window for each of your SSL for SaaS zones.

## During the migration

After the migration has started and has had some time to progress, Cloudflare will generate a list of Custom Hostnames that failed to migrate and ask for your approval to complete the migration. When you give your approval, the migration will be complete, SSL for SaaS v1 will be disabled for the zone, and any Custom Hostname that has not completed hostname validation will no longer function.

The migration timeline depends on the number of Custom Hostnames. For example, if a zone has fewer than 10,000 Custom Hostnames, the list can be generated around an hour after beginning the migration. If a zone has millions of Custom Hostnames, it may take up to 24 hours to identify instances that failed to successfully migrate.

When your account team asks for approval to complete the migration, please respond in a timely manner. You will have **two weeks** to validate any remaining Custom Hostnames before they are systematically deleted.

## When is the migration?

The migration process starts on March 31, 2021 and will continue until final deprecation on September 1, 2021.

If you would like to begin the migration process before March 31, 2021, please contact your account team and they will work with you to expedite the process. Otherwise, your account team will reach out to you with a time for a migration window so that your zones are migrated before **September 1, 2021** end-of-life date.

## What if I have additional questions?

If you have any questions, please contact your account team or [SaaSv2@cloudflare.com](mailto:saasv2@cloudflare.com).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/","name":"Reference"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/reference/versioning/","name":"Deprecation - Version 1"}}]}
```

---

---
title: SaaS customers
description: Resources for customers whose domains are managed by a SaaS provider using Cloudflare.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# SaaS customers

Cloudflare partners with many [SaaS providers](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/) to extend our performance and security benefits to your website.

If you are a SaaS customer, you can take this process a step further by managing your own zone on Cloudflare. This setup - known as **O2O** \- allows you to benefit from your provider's setup but still customize how Cloudflare treats incoming traffic to your zone.

## Related resources

* [ How it works ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/)
* [ Provider guides ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/)
* [ Product compatibility ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/)
* [ Remove domain ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/remove-domain/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}}]}
```

---

---
title: How it works
description: How O2O routes traffic through two Cloudflare zones for SaaS provider configurations.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# How it works

O2O is a specific traffic routing configuration where traffic routes through two Cloudflare zones: the first Cloudflare zone is owned by customer 1 and the second Cloudflare zone is owned by customer 2, who is considered a SaaS provider.

If one or more hostnames are onboarded to a SaaS Provider that uses Cloudflare products as part of their platform - specifically the [Cloudflare for SaaS product](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) \- those hostnames will be created as [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/) in the SaaS Provider's zone.

To give the SaaS provider permission to route traffic through their zone, any custom hostname must be activated by you (the SaaS customer) by placing a [CNAME record](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record) on your authoritative DNS. If your authoritative DNS is Cloudflare, you have the option to [proxy](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/#application-services) your CNAME record, achieving an O2O setup.

## Prerequisites

* O2O only applies when the two zones are part of different Cloudflare accounts.
* Since O2O is based on CNAME, it does not apply when an A record is used to point to the SaaS provider's ([apex proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/)).

## With O2O

If you have your own Cloudflare zone (`example.com`) and your zone contains a [proxied DNS record](https://developers.cloudflare.com/dns/proxy-status/) matching the custom hostname (`mystore.example.com`) with a **CNAME** target defined by the SaaS Provider, then O2O will be enabled.

DNS management for **example.com**

| **Type** | **Name** | **Target**                 | **Proxy status** |
| -------- | -------- | -------------------------- | ---------------- |
| CNAME    | mystore  | customers.saasprovider.com | Proxied          |

With O2O enabled, the settings configured in your Cloudflare zone will be applied to the traffic first, and then the settings configured in the SaaS provider's zone will be applied to the traffic second. In the SaaS provider-owned zone, a HTTP header will be set to `cf-connecting-o2o: 1`.

flowchart TD
accTitle: O2O-enabled traffic flow diagram

A[Website visitor]

subgraph Cloudflare
  B[Customer-owned zone]
  C[SaaS Provider-owned zone]
end

D[SaaS Provider Origin]

A --> B
B --> C
C --> D

## Without O2O

If you do not have your own Cloudflare zone and have only onboarded one or more of your hostnames to a SaaS Provider, then O2O will not be enabled.

Without O2O enabled, the settings configured in the SaaS Provider's zone will be applied to the traffic.

flowchart TD
accTitle: Your zone using a SaaS provider, but without O2O

A[Website visitor]

subgraph Cloudflare
    B[SaaS Provider-owned zone]
end

C[SaaS Provider Origin]

A --> B
B --> C

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/","name":"How it works"}}]}
```

---

---
title: Product compatibility
description: Cloudflare product compatibility guidelines for O2O custom hostname zones.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Product compatibility

As a general rule, settings on the customer zone will override settings on the SaaS zone. In addition, [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/) does not permit traffic directed to a custom hostname zone into another custom hostname zone.

The following table provides a list of compatibility guidelines for various Cloudflare products and features.

Note

This is not an exhaustive list of Cloudflare products and features.

| Product                                                                                                               | Customer zone | SaaS provider zone | Notes                                                                                                                                                                                                                                                                                                                                         |
| --------------------------------------------------------------------------------------------------------------------- | ------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Access](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/secure-with-access/) | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [API Shield](https://developers.cloudflare.com/api-shield/)                                                           | Yes           | No                 |                                                                                                                                                                                                                                                                                                                                               |
| [Argo Smart Routing](https://developers.cloudflare.com/argo-smart-routing/)                                           | No            | Yes                | Customer zones can still use Smart Routing for non-O2O traffic.                                                                                                                                                                                                                                                                               |
| [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/)                                       | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [Browser Integrity Check](https://developers.cloudflare.com/waf/tools/browser-integrity-check/)                       | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [Cache](https://developers.cloudflare.com/cache/)                                                                     | Yes\*         | Yes                | Though caching is possible on a customer zone, it is generally discouraged (especially for HTML).Your SaaS provider likely performs its own caching outside of Cloudflare and caching on your zone might lead to out-of-sync or stale cache states.Customer zones can still cache content that are not routed through a SaaS provider's zone. |
| [China Network](https://developers.cloudflare.com/china-network/)                                                     | No            | No                 |                                                                                                                                                                                                                                                                                                                                               |
| [DNS](https://developers.cloudflare.com/dns/)                                                                         | Yes\*         | Yes                | As a SaaS customer, do not remove the records related to your Cloudflare for SaaS setup.Otherwise, your traffic will begin routing away from your SaaS provider.                                                                                                                                                                              |
| [HTTP/2 prioritization ↗](https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/)                 | Yes           | Yes\*              | This feature must be enabled on the customer zone to function.                                                                                                                                                                                                                                                                                |
| [Image resizing](https://developers.cloudflare.com/images/optimization/transformations/overview/)                     | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| IPv6                                                                                                                  | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [IPv6 Compatibility](https://developers.cloudflare.com/network/ipv6-compatibility/)                                   | Yes           | Yes\*              | If the customer zone has **IPv6 Compatibility** enabled, generally the SaaS zone should as well.If not, make sure the SaaS zone enables [Pseudo IPv4](https://developers.cloudflare.com/network/pseudo-ipv4/).                                                                                                                                |
| [Load Balancing](https://developers.cloudflare.com/load-balancing/)                                                   | No            | Yes                | Customer zones can still use Load Balancing for non-O2O traffic.                                                                                                                                                                                                                                                                              |
| [Page Rules](https://developers.cloudflare.com/rules/page-rules/)                                                     | Yes\*         | Yes                | Page Rules that match the subdomain used for O2O may block or interfere with the flow of visitors to your website.                                                                                                                                                                                                                            |
| [Origin Rules](https://developers.cloudflare.com/rules/origin-rules/)                                                 | Yes           | Yes                | Enterprise zones can configure Origin Rules, by setting the Host Header and DNS Overrides to direct traffic to a SaaS zone.                                                                                                                                                                                                                   |
| [Client-side security](https://developers.cloudflare.com/client-side-security/) (formerly Page Shield)                | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [Polish](https://developers.cloudflare.com/images/polish/)                                                            | Yes\*         | Yes                | Polish only runs on cached assets. If the customer zone is bypassing cache for SaaS zone destined traffic, then images optimized by Polish will not be loaded from origin.                                                                                                                                                                    |
| [Rate Limiting](https://developers.cloudflare.com/waf/rate-limiting-rules/)                                           | Yes\*         | Yes                | Rate Limiting rules that match the subdomain used for O2O may block or interfere with the flow of visitors to your website.                                                                                                                                                                                                                   |
| [Rocket Loader](https://developers.cloudflare.com/speed/optimization/content/rocket-loader/)                          | No            | No                 |                                                                                                                                                                                                                                                                                                                                               |
| [Security Level](https://developers.cloudflare.com/waf/tools/security-level/)                                         | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [Spectrum](https://developers.cloudflare.com/spectrum/)                                                               | No            | No                 |                                                                                                                                                                                                                                                                                                                                               |
| [Transform Rules](https://developers.cloudflare.com/rules/transform/)                                                 | Yes\*         | Yes                | Transform Rules that match the subdomain used for O2O may block or interfere with the flow of visitors to your website.                                                                                                                                                                                                                       |
| [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/)                                               | Yes           | Yes                | WAF custom rules that match the subdomain used for O2O may block or interfere with the flow of visitors to your website.                                                                                                                                                                                                                      |
| [WAF managed rules](https://developers.cloudflare.com/waf/managed-rules/)                                             | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [Waiting Room](https://developers.cloudflare.com/waiting-room/)                                                       | Yes           | Yes                |                                                                                                                                                                                                                                                                                                                                               |
| [WebSockets](https://developers.cloudflare.com/network/websockets/)                                                   | No            | No                 |                                                                                                                                                                                                                                                                                                                                               |
| [Workers](https://developers.cloudflare.com/workers/)                                                                 | Yes\*         | Yes                | Similar to Page Rules, Workers that match the subdomain used for O2O may block or interfere with the flow of visitors to your website.                                                                                                                                                                                                        |
| [Zaraz](https://developers.cloudflare.com/zaraz/)                                                                     | Yes           | No                 |                                                                                                                                                                                                                                                                                                                                               |

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/","name":"Product compatibility"}}]}
```

---

---
title: BigCommerce
description: Learn how to configure your Enterprise zone with BigCommerce.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# BigCommerce

Cloudflare partners with BigCommerce to provide BigCommerce customers’ websites with Cloudflare’s performance and security benefits.

If you use BigCommerce and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then BigCommerce's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as [WAF](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), [Waiting Room](https://developers.cloudflare.com/waiting-room/), and more — on the traffic destined for your BigCommerce environment.

## How it works

For more details about how O2O is different than other Cloudflare setups, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

BigCommerce customers can enable O2O on any Cloudflare zone plan.

To enable O2O on your account, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a `CNAME` DNS record.

| Type  | Name             | Target                  | Proxy status |
| ----- | ---------------- | ----------------------- | ------------ |
| CNAME | <YOUR\_HOSTNAME> | shops.mybigcommerce.com | Proxied      |

Note

For more details about a BigCommerce setup, refer to their [support guide ↗](https://support.bigcommerce.com/s/article/Cloudflare-for-Performance-and-Security?language=en%5FUS#orange-to-orange).

If you cannot activate your domain using [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/), reach out to your account team.

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to BigCommerce. BigCommerce would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on BigCommerce, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to BigCommerce, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow BigCommerce's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a BigCommerce customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult BigCommerce if there are technical issues that Cloudflare cannot resolve.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/bigcommerce/","name":"BigCommerce"}}]}
```

---

---
title: HubSpot
description: Learn how to configure your zone with HubSpot.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# HubSpot

Cloudflare partners with HubSpot to provide HubSpot customers’ websites with Cloudflare’s performance and security benefits.

If you use HubSpot and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then HubSpot's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as [WAF](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), [Waiting Room](https://developers.cloudflare.com/waiting-room/), and more — on the traffic destined for your HubSpot environment.

## How it works

For more details about how O2O is different than other Cloudflare setups, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

O2O is enabled per hostname, so to enable O2O for a specific hostname within your Cloudflare zone, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a Proxied `CNAME` DNS record with a target of your corresponding HubSpot CNAME. Which HubSpot CNAME is targeted will depend on your current [HubSpot proxy settings ↗](https://developers.hubspot.com/docs/cms/developer-reference/reverse-proxy-support#configure-the-proxy).

| Type  | Name             | Target                               | Proxy status |
| ----- | ---------------- | ------------------------------------ | ------------ |
| CNAME | <YOUR\_HOSTNAME> | <HUBID>.sites-proxy.hscoscdn<##>.net | Proxied      |

Note

For questions about your HubSpot setup, refer to [HubSpot's reverse proxy support guide ↗](https://developers.hubspot.com/docs/cms/developer-reference/reverse-proxy-support).

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to HubSpot. HubSpot would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on HubSpot, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to HubSpot, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow HubSpot's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a HubSpot customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult HubSpot if there are technical issues that Cloudflare cannot resolve.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/hubspot/","name":"HubSpot"}}]}
```

---

---
title: Kinsta
description: Learn how to configure your Enterprise zone with Kinsta.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Kinsta

Cloudflare partners with Kinsta to provide Kinsta customers’ websites with Cloudflare’s performance and security benefits.

If you use Kinsta and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then Kinsta's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as [WAF](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), [Waiting Room](https://developers.cloudflare.com/waiting-room/), and more — on the traffic destined for your Kinsta environment.

## How it works

For additional detail about how traffic routes when O2O is enabled, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

Kinsta customers can enable O2O on any Cloudflare zone plan.

To enable O2O for a specific hostname within a Cloudflare zone, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a Proxied `CNAME` DNS record with your Kinsta site name as the target. Kinsta’s domain addition setup will walk you through other validation steps.

| Type  | Name             | Target                        | Proxy status |
| ----- | ---------------- | ----------------------------- | ------------ |
| CNAME | <YOUR\_HOSTNAME> | sitename.hosting.kinsta.cloud | Proxied      |

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to Kinsta. Kinsta would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on Kinsta, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to Kinsta, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow Kinsta's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a Kinsta customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult Kinsta if there are technical issues that Cloudflare cannot resolve.

### Resolving SSL errors using Cloudflare Managed Certificates

If you encounter SSL errors when attempting to activate a Cloudflare Managed Certificate, verify if you have a `CAA` record on your domain name with command `dig +short example.com CAA`.

If you do have a `CAA` record, verify that it permits SSL certificates to be issued by the [certificate authorities supported by Cloudflare](https://developers.cloudflare.com/ssl/reference/certificate-authorities/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/kinsta/","name":"Kinsta"}}]}
```

---

---
title: Render
description: Learn how to configure your Enterprise zone with Render.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Render

Cloudflare partners with [Render](https://render.com) to provide Render customers’ web services and static sites with Cloudflare’s performance and security benefits.

If you use Render and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then Render's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as [WAF](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), [Waiting Room](https://developers.cloudflare.com/waiting-room/), and more — on the traffic destined for your Render services.

## How it works

For additional detail about how traffic routes when O2O is enabled, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

Render customers can enable O2O on any Cloudflare zone plan. Cloudflare support for O2O setups is only available for Enterprise customers.

To enable O2O for a specific hostname within a Cloudflare zone, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a Proxied `CNAME` DNS record with your Render site name as the target. Render's domain addition setup will walk you through other validation steps.

| Type  | Name             | Target                                                  | Proxy status |
| ----- | ---------------- | ------------------------------------------------------- | ------------ |
| CNAME | <YOUR\_HOSTNAME> | <RENDER\_SUBDOMAIN> (for example, example.onrender.com) | Proxied      |

Note

For more details about Render setup, refer to their [documentation ↗](https://render.com/docs/configure-cloudflare-dns).

If you cannot activate your domain using [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/), reach out to your Cloudflare account team or your Render support team.

### Additional requirements for wildcard subdomains

With O2O enabled, adding a wildcard subdomain to a Render service requires that the corresponding root domain is also routed to Render. If the root domain is routed elsewhere, wildcard routing will fail.

If your root domain needs to route somewhere besides Render, add individual subdomains to your Render service instead of a wildcard.

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to Render. Render would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on Render, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to Render, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow Render's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a Render customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult Render if there are technical issues that Cloudflare cannot resolve.

### Resolving SSL errors

If you encounter SSL errors, check if you have a `CAA` record.

If you have a `CAA` record, verify that it permits SSL certificates to be issued by Google Trust Services (`pki.goog`).

For more details, refer to [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/render/","name":"Render"}}]}
```

---

---
title: Salesforce Commerce Cloud
description: Learn how to configure your Enterprise zone with Salesforce Commerce Cloud.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ Salesforce ](https://developers.cloudflare.com/search/?tags=Salesforce) 

# Salesforce Commerce Cloud

Cloudflare partners with Salesforce Commerce Cloud to provide Salesforce Commerce Cloud customers’ websites with Cloudflare’s performance and security benefits.

If you use Salesforce Commerce Cloud and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then Salesforce Commerce Cloud's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as [WAF](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), [Waiting Room](https://developers.cloudflare.com/waiting-room/), and more — on the traffic destined for your Salesforce Commerce Cloud environment.

## How it works

For additional detail about how traffic routes when O2O is enabled, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

To enable O2O requires the following:

1. You must configure your SFCC environment as an "SFCC Proxy Zone". If you currently have an "SFCC Legacy Zone", you cannot enable O2O.  
   * For more details on the different types of SFCC configurations, refer to the [Salesforce FAQ on SFCC Proxy Zones ↗](https://help.salesforce.com/s/articleView?id=cc.b2c%5Fecdn%5Fproxy%5Fzone%5Ffaq.htm&type=5).  
   * For instructions on how to migrate your SFCC environment to an "SFCC Proxy Zone", refer to the [SFCC Legacy Zone to SFCC Proxy Zone migration guide ↗](https://help.salesforce.com/s/articleView?id=cc.b2c%5Fmigrate%5Flegacy%5Fzone%5Fto%5Fproxy%5Fzone.htm&type=5).
2. Your own Cloudflare zone on an Enterprise plan.

If you meet the above requirements, O2O can then be enabled per hostname. To enable O2O for a specific hostname within your Cloudflare zone, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a Proxied CNAME DNS record with a target of the CNAME provided by SFCC Business Manager, which is the dashboard used by SFCC customers to configure their storefront environment.

The CNAME provided by SFCC Business Manager will resemble `commcloud.prod-abcd-example-com.cc-ecdn.net` and contains 3 distinct parts. For each hostname routing traffic to SFCC, be sure to update each part of the example CNAME to match your SFCC environment:

1. **Environment**: `prod` should be changed to `prod` or `dev` or `stg`.
2. **Realm**: `abcd` should be changed to the Realm ID assigned to you by SFCC.
3. **Domain Name**: `example-com` should be changed to match your domain name in a hyphenated format.

| Type  | Name             | Target                                      | Proxy status |
| ----- | ---------------- | ------------------------------------------- | ------------ |
| CNAME | <YOUR\_HOSTNAME> | commcloud.prod-abcd-example-com.cc-ecdn.net | Proxied      |

For O2O to be configured properly, make sure your Proxied DNS record targets your SFCC CNAME **directly**. Do not indirectly target the SFCC CNAME by targeting another Proxied DNS record in your Cloudflare zone which targets the SFCC CNAME.

Correct configuration

For example, if the hostnames routing traffic to SFCC are `www.example.com` and `preview.example.com`, the following is a **correct** configuration in your Cloudflare zone:

| Type  | Name                | Target                                      | Proxy status |
| ----- | ------------------- | ------------------------------------------- | ------------ |
| CNAME | www.example.com     | commcloud.prod-abcd-example-com.cc-ecdn.net | Proxied      |
| CNAME | preview.example.com | commcloud.prod-abcd-example-com.cc-ecdn.net | Proxied      |

Incorrect configuration

And, the following is an **incorrect** configuration because `preview.example.com` indirectly targets the SFCC CNAME via the `www.example.com` Proxied DNS record, which means O2O will not be properly enabled for hostname `preview.example.com`:

| Type  | Name                | Target                                      | Proxy status |
| ----- | ------------------- | ------------------------------------------- | ------------ |
| CNAME | www.example.com     | commcloud.prod-abcd-example-com.cc-ecdn.net | Proxied      |
| CNAME | preview.example.com | www.example.com                             | Proxied      |

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to Salesforce Commerce Cloud. Salesforce Commerce Cloud would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on Salesforce Commerce Cloud, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to Salesforce Commerce Cloud, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow Salesforce Commerce Cloud's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a Salesforce Commerce Cloud customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult Salesforce Commerce Cloud if there are technical issues that Cloudflare cannot resolve.

### Resolving SSL errors using Cloudflare Managed Certificates

If you encounter SSL errors when attempting to activate a Cloudflare Managed Certificate, verify if you have a `CAA` record on your domain name with command `dig +short example.com CAA`.

If you do have a `CAA` record, verify that it permits SSL certificates to be issued by the [certificate authorities supported by Cloudflare](https://developers.cloudflare.com/ssl/reference/certificate-authorities/).

### Best practice Zone-level configuration

1. Set **Minimum TLS version** to **TLS 1.2**  
   1. Go to the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page, scroll down to find **Minimum TLS Version**, and set it to _TLS 1.2_. This setting applies to every Proxied DNS record in your Zone.
2. Match the **Security Level** set in **SFCC Business Manager**  
   1. _Option 1: Zone-level_ \- Go to the [**Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings) page under Security, find **Security Level** and set **Security Level** to match what is configured in **SFCC Business Manager**. This setting applies to every Proxied DNS record in your Cloudflare zone.  
   2. _Option 2: Per Proxied DNS record_ \- If the **Security Level** differs between the Proxied DNS records targeting your SFCC environment and other Proxied DNS records in your Cloudflare zone, use a **Configuration Rule** to set the **Security Level** specifically for the Proxied DNS records targeting your SFCC environment. For example:  
         1. Create a new **Configuration Rule** on the [**Rules Overview** ↗](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview) page by selecting **Create rule** next to **Configuration Rules**:  
                  1. **Rule name:** `Match Security Level on SFCC hostnames`  
                  2. **Field:** _Hostname_  
                  3. **Operator:** _is in_ (this will match against multiple hostnames specified in the **Value** field)  
                  4. **Value:** `www.example.com` `dev.example.com`  
                  5. Scroll down to **Security Level** and click **\+ Add**  
                              1. **Select Security Level:** _Medium_ (this should match the **Security Level** set in **SFCC Business Manager**)  
                  6. Scroll to the bottom of the page and click **Deploy**
3. Disable **Browser Integrity Check**  
   1. _Option 1: Zone-level_ \- Go to the [**Settings** ↗](https://dash.cloudflare.com/?to=/:account/:zone/security/settings) page under Security, find **Browser Integrity Check** and toggle it off to disable it. This setting applies to every Proxied DNS record in your Cloudflare zone.  
   2. _Option 2: Per Proxied DNS record_ \- If you want to keep **Browser Integrity Check** enabled for other Proxied DNS records in your Cloudflare zone but want to disable it on Proxied DNS records targeting your SFCC environment, keep the Zone-level **Browser Integrity Check** feature enabled and use a **Configuration Rule** to disable **Browser Integrity Check** specifically for the hostnames targeting your SFCC environment. For example:  
         1. Create a new **Configuration Rule** on the [**Rules Overview** ↗](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview) page by selecting **Create rule** next to **Configuration Rules**:  
                  1. **Rule name:** `Disable Browser Integrity Check on SFCC hostnames`  
                  2. **Field:** _Hostname_  
                  3. **Operator:** _is in_ (this will match against multiple hostnames specified in the **Value** field)  
                  4. **Value:** `www.example.com` `dev.example.com`  
                  5. Scroll down to **Browser Integrity Check** and click the **\+ Add** button:  
                              1. Set the toggle to **Off** (a grey X will be displayed)  
                  6. Scroll to the bottom of the page and click **Deploy**
4. Bypass **Cache** on Proxied DNS records targeting your SFCC environment  
   1. Your SFCC environment, also called a **Realm**, will contain one to many SFCC Proxy Zones, which is where caching will always occur. In the corresponding SFCC Proxy Zone for your domain, SFCC performs their own cache optimization, so it is recommended to bypass the cache on the Proxied DNS records in your Cloudflare zone which target your SFCC environment to prevent a "double caching" scenario. This can be accomplished with a **Cache Rule**.  
   2. If the **Cache Rule** is not created, caching will occur in both your Cloudflare zone and your corresponding SFCC Proxy Zone, which can cause issues if and when the cache is invalidated or purged in your SFCC environment.  
         1. Additional information on caching in your SFCC environment can be found in [SFCC's Content Cache Documentation ↗](https://developer.salesforce.com/docs/commerce/b2c-commerce/guide/b2c-content-cache.html)  
   3. Create a new **Cache Rule** on the [**Rules Overview** ↗](https://dash.cloudflare.com/?to=/:account/:zone/rules/overview) page by selecting **Create rule** next to **Cache Rules**:  
         1. **Rule name:** `Bypass cache on SFCC hostnames`  
         2. **Field:** _Hostname_  
         3. **Operator:** _is in_ (this will match against multiple hostnames specified in the **Value** field)  
         4. **Value:** `www.example.com` `dev.example.com`  
         5. **Cache eligibility:** Select **Bypass cache**.  
         6. Scroll to the bottom of the page and select **Deploy**.
5. _Optional_ \- Upload your Custom Certificate from **SFCC Business Manager** to your Cloudflare zone:  
   1. The Custom Certificate you uploaded via **SFCC Business Manager** or **SFCC CDN-API**, which exists within your corresponding SFCC Proxy Zone, will terminate TLS connections for your SFCC storefront hostnames. Because of that, it is optional if you want to upload the same Custom Certificate to your own Cloudflare zone. Doing so will allow Cloudflare users with specific roles in your Cloudflare account to receive expiration notifications for your Custom Certificates. Please read [renew custom certificates](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/renewing/#renew-custom-certificates) for further details.  
   2. Additionally, since you now have your own Cloudflare zone, you have access to Cloudflare's various edge certificate products which means you could have more than one certificate covering the same SANs. In that scenario, a certificate priority process occurs to determine which certificate to serve at the Cloudflare edge. If you find your SFCC storefront hostnames are presenting a different certificate compared to what you uploaded via **SFCC Business Manager** or **SFCC CDN-API**, the certificate priority process is likely the reason. Please read [certificate priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#certificate-deployment) for further details.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/salesforce-commerce-cloud/","name":"Salesforce Commerce Cloud"}}]}
```

---

---
title: Shopify
description: Learn how to configure your zone with Shopify.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Shopify

Cloudflare partners with Shopify to provide Shopify customers’ websites with Cloudflare’s performance and security benefits.

If you use Shopify and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then Shopify's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O routing also enables you to take advantage of Cloudflare zones specifically customized for Shopify traffic.

## How it works

For more details about how O2O is different than other Cloudflare setups, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

When you [set up O2O routing for your Shopify website](#enable), Cloudflare enables specific configurations for this SaaS provider. Currently, this includes the following:

* Workers and Snippets are disabled on the `/checkout` URI path.

## Enable

You can enable O2O on any Cloudflare zone plan.

To enable O2O on your account, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a `CNAME` DNS record.

| Type  | Name                 | Target              | Proxy status |
| ----- | -------------------- | ------------------- | ------------ |
| CNAME | <YOUR\_SHOP\_DOMAIN> | shops.myshopify.com | Proxied      |

Once you save the new DNS record, the Cloudflare dashboard will show a Shopify icon next to the CNAME record value. For example:

![Cloudflare dashboard showing a CNAME DNS entry for Shopify with a specific Shopify icon](https://developers.cloudflare.com/_astro/shopify-dns-entry.BVBaRuE6_1CQPez.webp) 

Do not use Always Use HTTPS

Do not enable the [Always Use HTTPS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/) setting in an O2O scenario with Shopify.

This setting forces a redirect on all requests, including the `/.well-known/acme-challenge/*` URI path used for HTTP-01 domain validation. This prevents Shopify from automatically provisioning or renewing SSL certificates via Let's Encrypt for your domain.

Instead, create a [redirect rule](https://developers.cloudflare.com/rules/url-forwarding/single-redirects/create-dashboard/) to enforce HTTPS while excluding the validation path mentioned above (use a [wildcard pattern](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#wildcard-matching) like `/.well-known/acme-challenge/*`).

For questions about Shopify setup, refer to their [support guide ↗](https://help.shopify.com/en/manual/domains/add-a-domain/connecting-domains/connect-domain-manual).

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to Shopify. Shopify would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on Shopify, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to Shopify, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow Shopify's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a Shopify customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult Shopify if there are technical issues that Cloudflare cannot resolve.

### DNS CAA records

For details about CAA records refer to the [Shopify documentation ↗](https://help.shopify.com/manual/domains/add-a-domain/connecting-domains/considerations).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/shopify/","name":"Shopify"}}]}
```

---

---
title: Webflow
description: Learn how to configure your Cloudflare zone with Webflow.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Webflow

Cloudflare partners with Webflow to provide Webflow customers’ websites with Cloudflare’s performance and security benefits.

If you use Webflow and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then Webflow's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as WAF, Bot Management, Waiting Room, and more — on the traffic destined for your Webflow environment.

## How it works

For more details about how O2O is different than other Cloudflare setups, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

Webflow customers can enable O2O on any Cloudflare zone plan.

To enable O2O for a specific hostname within a Cloudflare Zone, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a Proxied `CNAME` DNS record with your Webflow site name as the target. Webflow's domain addition setup will walk you through other validation steps.

| Type  | Name           | Target          | Proxy status |
| ----- | -------------- | --------------- | ------------ |
| CNAME | <YOUR\_DOMAIN> | cdn.webflow.com | Proxied      |

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to Webflow. Webflow would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on Webflow, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to Webflow, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow Webflow's instructions to refresh the custom hostname and it should activate.

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Additional support

If you are a Webflow customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult Webflow if there are technical issues that Cloudflare cannot resolve.

### DNS CAA records

Webflow issues SSL/TLS certificates for merchant domains using Let’s Encrypt and Google Trust Services. If you add any DNS CAA records, you must select **Let’s Encrypt** or **Google Trust Services** as the Certificate Authority (CA) or HTTPS connections may fail.

For more details, refer to [CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/#caa-records-added-by-cloudflare).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/webflow/","name":"Webflow"}}]}
```

---

---
title: WP Engine
description: Learn how to configure your zone with WP Engine.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# WP Engine

Cloudflare partners with WP Engine to provide WP Engine customers’ websites with Cloudflare’s performance and security benefits.

If you use WP Engine and also have a Cloudflare plan, you can use your own Cloudflare zone to proxy web traffic to your zone first, then WP Engine's (the SaaS Provider) zone second. This configuration option is called [O2O](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Benefits

O2O's benefits include applying your own Cloudflare zone's services and settings — such as [WAF](https://developers.cloudflare.com/waf/), [Bot Management](https://developers.cloudflare.com/bots/plans/bm-subscription/), [Waiting Room](https://developers.cloudflare.com/waiting-room/), and more — on the traffic destined for your WP Engine environment.

## How it works

For more details about how O2O is different than other Cloudflare setups, refer to [How O2O works](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/).

## Enable

WP Engine customers can enable O2O on any Cloudflare zone plan.

To enable O2O for a specific hostname within a Cloudflare zone, [create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a Proxied `CNAME` DNS record with a target of one of the following WP Engine CNAMEs. Which WP Engine CNAME is used will depend on your current [WP Engine network type ↗](https://wpengine.com/support/network/).

| Type  | Name             | Target                                                                          | Proxy status |
| ----- | ---------------- | ------------------------------------------------------------------------------- | ------------ |
| CNAME | <YOUR\_HOSTNAME> | wp.wpewaf.com (Global Edge Security)orwp.wpenginepowered.com (Advanced Network) | Proxied      |

Note

For questions about WP Engine setup, refer to their [support guide ↗](https://wpengine.com/support/wordpress-best-practice-configuring-dns-for-wp-engine/#Point%5FDNS%5FUsing%5FCNAME%5FFlattening).

If you cannot activate your domain using [proxied DNS records](https://developers.cloudflare.com/dns/proxy-status/), reach out to your account team.

## Product compatibility

When a hostname within your Cloudflare zone has O2O enabled, you assume additional responsibility for the traffic on that hostname because you can now configure various Cloudflare products to affect that traffic. Some of the Cloudflare products compatible with O2O are:

* [Caching](https://developers.cloudflare.com/cache/)
* [Workers](https://developers.cloudflare.com/workers/)
* [Rules](https://developers.cloudflare.com/rules/)

For a full list of compatible products and potential limitations, refer to [Product compatibility](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/product-compatibility/).

## Zone hold

If your own Cloudflare zone is on the Enterprise plan, you have access to the [zone hold feature](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/), which is a toggle that prevents your domain name from being created as a zone in a different Cloudflare account. Additionally, if the zone hold is enabled, it prevents the activation of custom hostnames onboarded to WP Engine. WP Engine would receive the following error message for your custom hostname: `The hostname is associated with a held zone. Please contact the owner of this domain to have the hold removed.`

To successfully activate the custom hostname on WP Engine, the owner of the zone needs to [temporarily release the hold](https://developers.cloudflare.com/fundamentals/account/account-security/zone-holds/#release-zone-holds). If you are only onboarding a subdomain as a custom hostname to WP Engine, only the subfeature titled **Also prevent Subdomains** needs to be temporarily disabled.

Once the zone hold is temporarily disabled, follow WP Engine's instructions to refresh the custom hostname and it should activate.

## Additional support

If you are a WP Engine customer and have set up your own Cloudflare zone with O2O enabled on specific hostnames, contact your Cloudflare Account Team or [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) for help resolving issues in your own zone.

Cloudflare will consult WP Engine if there are technical issues that Cloudflare cannot resolve.

### Resolving SSL errors

If you encounter SSL errors, check if you have a `CAA` record.

If you do have a `CAA` record, check that it permits SSL certificates to be issued by `letsencrypt.org`.

For more details, refer to [Add CAA records](https://developers.cloudflare.com/ssl/edge-certificates/caa-records/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/","name":"Provider guides"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/provider-guides/wpengine/","name":"WP Engine"}}]}
```

---

---
title: Remove domain
description: Remove your domain from a SaaS provider O2O configuration.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Remove domain

If your SaaS domain is also a [domain using Cloudflare](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/), you can use your Cloudflare DNS to remove your domain from your SaaS provider.

This means that - if you [remove the DNS records](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#delete-dns-records) pointing to your SaaS provider - Cloudflare will stop routing domain traffic through your SaaS provider and the associated custom hostname will enter a **Moved** state.

This also means that you need to keep DNS records pointing to your SaaS provider for as long as you are a customer. Otherwise, you could accidentally remove your domain from their services.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/","name":"SaaS customers"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/remove-domain/","name":"Remove domain"}}]}
```

---

---
title: Security
description: Manage certificates, TLS settings, WAF rules, and access controls for custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Security

Cloudflare for SaaS provides increased security per custom hostname through:

* [Certificate management](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/)  
   * [Issue certificates through Cloudflare](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/)  
   * [Upload your own certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/)
* Control your traffic's level of encryption with [TLS settings](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/)
* Create and deploy WAF custom rules, rate limiting rules, and managed rulesets using [WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}}]}
```

---

---
title: Certificate management
description: Issue, validate, renew, and upload TLS certificates for custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate management

Cloudflare for SaaS takes away the burden of certificate issuance and management from you, as the SaaS provider, by proxying traffic through Cloudflare's edge. You can choose between Cloudflare managing all the certificate issuance and renewals on your behalf, or maintain control over your TLS private keys by uploading your customers' own certificates.

## Resources

* [ Certificate statuses ](https://developers.cloudflare.com/ssl/reference/certificate-statuses/)
* [ Issue and validate certificates ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/)
* [ TLS Management ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/)
* [ Custom certificates ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/)
* [ Webhook definitions ](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/webhook-definitions/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}}]}
```

---

---
title: Certificate statuses
description: Understand certificate statuses in Cloudflare SSL/TLS, including stages like Initializing, Pending Validation, and Active. Monitor via dashboard or command line.
image: https://developers.cloudflare.com/core-services-preview.png
---

> 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.

[Skip to content](#%5Ftop) 

# Certificate statuses

Certificates statuses show which stage of the issuance process each certificate is in.

## New certificates

When you order a new certificate, either an [edge certificate](https://developers.cloudflare.com/ssl/edge-certificates/) or a certificate used for a [custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/), its status will move through various stages as it progresses to Cloudflare's global network:

1. Initializing
2. Pending Validation
3. Pending Issuance
4. Pending Deployment
5. Active

Once you issue a certificate, it should be in **Pending Validation**, but change to **Active** after the validation is completed. If you see any errors, you or your customer may need to take additional actions to validate the certificate.

If you deactivate a certificate, it will become a **Deactivating** and then an **Inactive** status.

### Certificate replacement

When replacing a certificate, you may note a **Pending Cleanup** status. Old certificates are not deleted until the replacement has been successfully issued. This ensures TLS will not break for the hostname while the certificate is being replaced.

When the new certificate is successfully issued and activated, the status for the old certificate will transition from **Pending Cleanup**, and the certificate will be deleted.

## Custom certificates

If you are using a [custom certificate](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/) and your [zone status](https://developers.cloudflare.com/dns/zone-setups/reference/domain-status/) is **Pending** or **Moved**, your certificate may have a status of **Holding Deployment**.

When your zone becomes active, your custom certificate will deploy automatically (also moving to an **Active** status).

If your zone is already active when you upload a custom certificate, you will not see this status.

## Staging certificates

When you create certificates in your [staging environment](https://developers.cloudflare.com/ssl/edge-certificates/staging-environment/), those staging certificates have their own set of statuses:

* **Staging deployment**: Similar to **Pending Deployment**, but for staging certificates.
* **Staging active**: Similar to **Active**, but for staging certificates.
* **Deactivating**: Your staging certificate is in the process of becoming **Inactive**.
* **Inactive**: Your staging certificate is not at the edge, but you can deploy it if needed.

## Client certificates

When you use [client certificates](https://developers.cloudflare.com/ssl/client-certificates/), those client certificates have their own set of statuses:

* **Active**: The client certificate is active.
* **Revoked**: The client certificate is revoked.
* **Pending Reactivation**: The client certificate was revoked, but it is being restored.
* **Pending Revocation**: The client certificate was active, but it is being revoked.

---

## Monitor certificate statuses

### SSL/TLS

Monitor a certificate's status on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page or by using the [Get Certificate Pack endpoint](https://developers.cloudflare.com/api/resources/ssl/subresources/certificate%5Fpacks/methods/get/).

For more details on certificate validation, refer to [Domain Control Validation](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/).

### SSL for SaaS

Monitor a certificate's status on the [**Custom Hostnames** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames) page or by using the [Custom Hostname Details endpoint](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/).

For more details on certificate validation, refer to [Issue and validate certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/).

### Via the command line

To view certificates, use `openssl` or your browser. The command below can be used in advance of your customer pointing the `app.example.com` hostname to the edge ([provided validation was completed](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/)).

Terminal window

```

openssl s_client -servername app.example.com -connect $CNAME_TARGET:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep app.example.com


```

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/ssl/","name":"SSL/TLS"}},{"@type":"ListItem","position":3,"item":{"@id":"/ssl/reference/","name":"Reference"}},{"@type":"ListItem","position":4,"item":{"@id":"/ssl/reference/certificate-statuses/","name":"Certificate statuses"}}]}
```

---

---
title: Custom certificates
description: Upload your own TLS certificates for custom hostnames that require custom key material.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Custom certificates

If your customers need to provide their own key material, you may want to [upload a custom certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/). Cloudflare will automatically bundle the certificate with a certificate chain [optimized for maximum browser compatibility](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/#compatible).

As part of this process, you may also want to [generate a Certificate Signing Request (CSR)](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/certificate-signing-requests/) for your customer so they do not have to manage the private key on their own.

Note

Only certain customers have access to this feature. For more details, see the [Plans page](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

## Use cases

This situation commonly occurs when your customers use Extended Validation (EV) certificates (the “green bar”) or when their information security policy prohibits third parties from generating private keys on their behalf.

## Limitations

If you use custom certificates, you are responsible for the entire certificate lifecycle (initial upload, renewal, subsequent upload).

Cloudflare also only accepts publicly trusted certificates of these types:

* `SHA256WithRSA`
* `SHA1WithRSA`
* `ECDSAWithSHA256`

If you attempt to upload another type of certificate or a certificate that has been self-signed, it will be rejected.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/","name":"Custom certificates"}}]}
```

---

---
title: Certificate signing requests (CSRs)
description: Cloudflare for SaaS allows you to generate a Certificate Signing Request (CSR) A CSR contains information about your domain, common name, and Subject Alternative Names.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Certificate signing requests (CSRs)

**Last reviewed:**  over 5 years ago 

Generate a Certificate Signing Request (CSR) to get a custom certificate from the Certificate Authority (CA) of your choice while maintaining control of the private key on Cloudflare. The private key associated with the CSR will be generated by Cloudflare and will never leave our network.

A CSR contains information about your domain: your organization name and address, the common name (domain name), and Subject Alternative Names (SANs).

Once the CSR has been generated, provide it to your customer. Your customer will then pass it along to their preferred CA to obtain a certificate and return it to you. After you receive the certificate, you should upload it to Cloudflare and reference the unique CSR ID that was provided to you during CSR creation.

Note

Only certain customers have access to this feature. For more details, see the [Plans page](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

---

## Generate the private key and CSR

### 1\. Build the CSR payload

All fields except for organizational\_unit and key\_type are required. If you do not specify a `key_type`, the default of `rsa2048` (RSA 2048 bit) will be used; the other option is `p256v1` (NIST P-256).

Common names are restricted to 64 characters and subject alternative names (SANs) are limited to 255 characters, [per RFC 5280 ↗](https://tools.ietf.org/html/rfc5280). You must specify at least one SAN, and the list of SANs should include the common name.

Terminal window

```

request_body=$(< <(cat <<EOF

{

  "country": "US",

  "state": "MA",

  "locality": "Boston",

  "organization": "City of Boston",

  "organizational_unit": "Championship Parade Detail",

  "common_name": "app.example.com",

  "sans": [

    "app.example.com",

    "www.example.com",

    "blog.example.com",

    "example.com"

  ],

  "key_type": "p256v1"

}

EOF

))


```

### 2\. Generate a CSR

Now, you want to generate a CSR that you can provide to your customer.

Terminal window

```

curl https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_csrs \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data "$request_body"


# Response:

{

  "result": {

    "id": "7b163417-1d2b-4c84-a38a-2fb7a0cd7752",

    "country": "US",

    "state": "MA",

    "locality": "Boston",

    "organization": "City of Boston",

    "organizational_unit": "Championship Parade Detail",

    "common_name": "app.example.com",

    "sans": [

      "app.example.com",

      "www.example.com",

      "blog.example.com",

      "example.com",

    ],

    "key_type": "p256v1",

    "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIBSzCB8gIBADBiMQswaQYDVQQGEwJVUzELMAkGA1UECBMCTUExDzANBgNVBAcT\nBkJvc3RvbjEaMBgGA1UEChMRQ2l0eSBvZiBDaGFtcGlvbnMxGTAXBgNVBAMTEGNz\nci1wcm9kLnRscy5mdW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAaTKf70NYlwr\n20P6P8xj8/4mTN5q28dbZR/gM3u4m/RPs24+PxAfMZCNvkVKAPVWYfUAadZI4Ha/\ndxLh5Q6X5bhIoC4wLAYJKoZIhvcNAQkOMR8wHTAbBqNVHREEFDASghBjc3ItcHJv\nZC50bHMuZnVuMAoGCCqGSM49BAMCA0gAMEUCIQDgtFUZav466SbT2FGBsIBlahDI\nVkg4y+u+V/K5DlY1+gIgQ9xLfUSKnSnJYbM9TwWr4Z964+lBtB9af4O5pp7/PSA=\n-----END CERTIFICATE REQUEST-----\n"

  },

  "success": true


```

Replace the `\n` characters with actual newlines before passing to your customer. This can be accomplished by piping the output of the prior call to a tool like jq and perl, such as:

Terminal window

```

curl https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_csrs \

--header "X-Auth-Email: <EMAIL>" \

--header "X-Auth-Key: <API_KEY>" \

--header "Content-Type: application/json" \

--data "$request_body" | jq .result.csr | perl -npe s'/\\n/\n/g; s/"//g' > csr.txt


```

### 3\. Customer obtains certificate

Your customer will take the provided CSR and work with their CA to obtain a signed, publicly trusted certificate.

### 4\. Upload the certificate

Upload the certificate and reference the ID that was provided when you generated the CSR.

You should replace newlines in the certificate with literal `\n` characters, as illustrated above in the custom certificate upload example. After doing so, build the request body and provide the ID that was returned in a previous step.

Cloudflare only accepts publicly trusted certificates. If you attempt to upload a self-signed certificate, it will be rejected.

Terminal window

```

$ MYCERT="$(cat app_example_com.pem|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"


$ request_body=$(< <(cat <<EOF

{

  "hostname": "app.example.com",

  "ssl": {

    "custom_csr_id": "7b163417-1d2b-4c84-a38a-2fb7a0cd7752",

    "custom_certificate": "$MYCERT"

  }

}

EOF

))


```

With the request body built, [create the custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) with the supplied custom certificate. If you intend to use the certificate with multiple hostnames, make multiple API calls replacing the `hostname` field.

---

## Other actions

### List all CSRs

You can request the (paginated) collection of all previously generated custom CSRs by making a `GET` request to `https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_csrs`.

### Delete a CSR

Delete one or more of the CSRs to delete the underlying private key by making a `DELETE` request to `https://api.cloudflare.com/client/v4/zones/{zone_id}/custom_csrs/{csr_id}`.

You may delete a CSR provided there are no custom certificates using the private key that was generated for the CSR. If you attempt to delete a CSR whose private key is still in use, you will receive an error.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/certificate-signing-requests/","name":"Certificate signing requests (CSRs)"}}]}
```

---

---
title: Manage custom certificates
description: Learn how to manage custom certificates for your Cloudflare for SaaS custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Manage custom certificates

Learn how to manage custom certificates for your Cloudflare for SaaS custom hostnames. For use cases and limitations, refer to [custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/).

## Upload certificates

This section describes the general process for uploading a custom certificate corresponding to one of the [supported types](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/#limitations).

Note

If you must support both RSA and ECDSA refer to [certificate packs](#use-certificate-packs-rsa-and-ecdsa) below.

* [ Dashboard ](#tab-panel-4533)
* [ API ](#tab-panel-4534)

To upload a custom certificate in the dashboard, select **Custom certificate** while [creating your custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/).

For information about the **bundle method** options, refer to the [Cloudflare SSL/TLS documentation](https://developers.cloudflare.com/ssl/edge-certificates/custom-certificates/bundling-methodologies/).

The call below will upload a certificate for use with `app.example.com`.

Note that if you are using an ECC key generated by OpenSSL, you will need to first remove the `-----BEGIN EC PARAMETERS-----...-----END EC PARAMETERS-----` section of the file.

1. Update the file and build the payload

Terminal window

```

cat app_example_com.pem


```

```

-----BEGIN CERTIFICATE-----

MIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBN

MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E

...

SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/O

OeH8gMJ+FuwtXYEPa4hBf38M5eU5xWG7

-----END CERTIFICATE-----


```

Terminal window

```

MYCERT="$(cat app_example_com.pem|perl -pe 's/\r?\n/\\n/'|sed -e 's/..$//')"

MYKEY="$(cat app_example_com.key|perl -pe 's/\r?\n/\\n/'|sed -e's/..$//')"


```

With the certificate and key saved to environment variables (using escaped newlines), build the payload:

Terminal window

```

$ echo $MYCERT

-----BEGIN CERTIFICATE-----\nMIIFJDCCBAygAwIBAgIQD0ifmj/Yi5NP/2gdUySbfzANBgkqhkiG9w0BAQsFADBN\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E...SzSHfXp5lnu/3V08I72q1QNzOCgY1XeL4GKVcj4or6cT6tX6oJH7ePPmfrBfqI/O\nOeH8gMJ+FuwtXYEPa4hBf38M5eU5xWG7\n-----END CERTIFICATE-----\n


$ request_body=$(< <(cat <<EOF

{

  "hostname": "app.example.com",

  "ssl": {

    "custom_certificate": "$MYCERT",

    "custom_key": "$MYKEY"

  }

}

EOF

))


```

1. Use a [POST request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) to upload your certificate and key.

Note

The serial number returned is unique to the issuer, but not globally unique. Additionally, it is returned as a string, not an integer.

## Use certificate packs: RSA and ECDSA

A certificate pack allows you to upload up to one RSA and one ECDSA custom certificates to a custom hostname. This process is currently only supported via API.

To upload an RSA and ECDSA certificate to a custom hostname, set the `bundle_method` to `force` and define the `custom_cert_bundle` property when [creating a custom hostname via API](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/).

You can also use `"bundle_method": "force"` and `custom_cert_bundle` with a `PATCH` request to the [Edit Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) endpoint.

### Delete a custom certificate and private key

Use the [Delete Single Certificate And Key For Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/certificate%5Fpack/subresources/certificates/methods/delete/) endpoint to remove one of the custom certificates and corresponding key from a certificate pack.

You cannot delete a certificate if it is the only remaining certificate in the pack.

### Replace a custom certificate and private key

To replace a single custom certificate within a certificate pack that contains two bundled certificates, use the [Replace Custom Certificate And Custom Key In Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/certificate%5Fpack/subresources/certificates/methods/update/) endpoint.

You can only replace an RSA certificate with another RSA certificate, or an ECDSA certificate with another ECDSA certificate.

---

## Move to a Cloudflare certificate

If you want to switch from maintaining a custom certificate to using one issued by Cloudflare, you can migrate that certificate with zero downtime.

Send a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) to your custom hostname with a value for the DCV `method`. As soon as the [certificate is validated](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/) and the [hostname is validated](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/), Cloudflare will remove the old custom certificate and begin serving the new one.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/","name":"Custom certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/","name":"Manage custom certificates"}}]}
```

---

---
title: TLS Management
description: Configure mTLS enforcement and minimum TLS version per custom hostname.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ mTLS ](https://developers.cloudflare.com/search/?tags=mTLS)[ TLS ](https://developers.cloudflare.com/search/?tags=TLS) 

# TLS Management

[Mutual TLS (mTLS) ↗](https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/) adds an extra layer of protection to application connections by validating certificates on the server and the client. When building a SaaS application, you may want to enforce mTLS to protect sensitive endpoints related to payment processing, database updates, and more.

[Minimum TLS Version](#minimum-tls-version) only allows HTTPS connections from visitors that support the selected TLS protocol version or newer. Cloudflare recommends TLS 1.2 to comply with the Payment Card Industry (PCI) Security Standards Council. As a SaaS provider, you can control the Minimum TLS version for your zone as a whole, as well as for individual custom hostnames.

[Cipher suites](#cipher-suites) are a combination of ciphers used to negotiate security settings during the [SSL/TLS handshake ↗](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/). As a SaaS provider, you can specify configurations for cipher suites on your zone as a whole and cipher suites on individual custom hostnames via the API.

Warning

When you [issue a custom hostname certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/) with wildcards enabled, any cipher suites or Minimum TLS settings applied to that hostname will only apply to the direct hostname.

However, if you want to update the Minimum TLS settings for all wildcard hostnames, you can change Minimum TLS version at the [zone level](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/).

## Enable mTLS

Once you have [added a custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/), you can enable mTLS by using Cloudflare Access. Go to [Cloudflare Zero Trust ↗](https://one.dash.cloudflare.com/) and [add mTLS authentication](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/) with a few clicks.

Note

Currently, you cannot add mTLS policies for custom hostnames using [API Shield](https://developers.cloudflare.com/api-shield/security/mtls/).

Also make sure to enforce mTLS on the specific custom hostname where it should be checked. It is not enough to have it set on the CNAME target.

## Minimum TLS Version

Note

While TLS 1.3 is the most recent and secure version, it is not supported by some older devices. Refer to Cloudflare's recommendations when [deciding what version to use](https://developers.cloudflare.com/ssl/reference/protocols/#decide-which-version-to-use).

### Scope

Minimum TLS version exists both as a [zone-level setting](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/) (on the [**Edge Certificates** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/edge-certificates) page under **Minimum TLS Version**) and as a custom hostname setting. What this implies is:

* For custom hostnames created via API, it is possible not to explicitly define a value for `min_tls_version`. When that is the case, whatever value is defined as your zone's minimum TLS version will be applied. To confirm whether a given custom hostname has a specific minimum TLS version set, use the following API call.

Check custom hostname TLS settings

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

Custom Hostname Details

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Response example

```

  "success": true,

  "result": {

    "id": "<CUSTOM_HOSTNAME_ID>",

    "ssl": {

12 collapsed lines

      "id": "<CERTIFICATE_ID>",

      "bundle_method": "ubiquitous",

      "certificate_authority": "<CERTIFICATE_AUTHORITY>",

      "custom_certificate": "",

      "custom_csr_id": "",

      "custom_key": "",

      "expires_on": "",

      "hosts": [

        "app.example.com",

        "*.app.example.com"

      ],

      "issuer": "",

      "method": "http",

      "settings": {},

      "signature": "SHA256WithRSA",

      "type": "dv",

20 collapsed lines

      "uploaded_on": "2020-02-06T18:11:23.531995Z",

      "validation_errors": [

        {

          "message": "SERVFAIL looking up CAA for app.example.com"

        }

      ],

      "validation_records": [

        {

          "emails": [

            "administrator@example.com",

            "webmaster@example.com"

          ],

          "http_body": "ca3-574923932a82475cb8592200f1a2a23d",

          "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt",

          "txt_name": "_acme-challenge.app.example.com",

          "txt_value": "810b7d5f01154524b961ba0cd578acc2"

        }

      ],

      "wildcard": false

    },

  }


```

* Whenever you make changes to a custom hostname via dashboard, the value that is set for Minimum TLS version will apply. If you have a scenario as explained in the bullet above, the dashboard change will override the zone-level configuration that was being applied.
* For custom hostnames with wildcards enabled, the direct custom hostname you create (for example, `saas-customer.test`) will use the hostname-specific setting, while the others (`sub1.saas-customer.test`, `sub2.saas-customer.test`, etc) will default to the zone-level setting.

### Setup

Minimum TLS version for your zone

Refer to [Minimum TLS version - SSL/TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/minimum-tls/#zone-level).

Minimum TLS version for custom hostname

* [ Dashboard ](#tab-panel-4535)
* [ API ](#tab-panel-4536)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Find the hostname to which you want to apply Minimum TLS Version. Select **Edit**.
3. Choose the desired TLS version under **Minimum TLS Version** and select **Save**.

In the API documentation, refer to [SSL properties of a custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/). Besides the `settings` specifications, you must include `type` and `method` within the `ssl` object, as explained below.

1. Make a `GET` request to the [Custom Hostname Details](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/) endpoint to check what are the current values for `ssl.type` and `ssl.method`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

Custom Hostname Details

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Response example

```

  "success": true,

  "result": {

    "id": "<CUSTOM_HOSTNAME_ID>",

    "ssl": {

12 collapsed lines

      "id": "<CERTIFICATE_ID>",

      "bundle_method": "ubiquitous",

      "certificate_authority": "<CERTIFICATE_AUTHORITY>",

      "custom_certificate": "",

      "custom_csr_id": "",

      "custom_key": "",

      "expires_on": "",

      "hosts": [

        "app.example.com",

        "*.app.example.com"

      ],

      "issuer": "",

      "method": "http",

      "settings": {},

      "signature": "SHA256WithRSA",

      "type": "dv",

20 collapsed lines

      "uploaded_on": "2020-02-06T18:11:23.531995Z",

      "validation_errors": [

        {

          "message": "SERVFAIL looking up CAA for app.example.com"

        }

      ],

      "validation_records": [

        {

          "emails": [

            "administrator@example.com",

            "webmaster@example.com"

          ],

          "http_body": "ca3-574923932a82475cb8592200f1a2a23d",

          "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt",

          "txt_name": "_acme-challenge.app.example.com",

          "txt_value": "810b7d5f01154524b961ba0cd578acc2"

        }

      ],

      "wildcard": false

    },

  }


```

1. After you take note of these values, make a `PATCH` request to the [Edit Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) endpoint, providing both the minimum TLS version you want to define and the same `type` and `method` values that you obtained from the previous step.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "ssl": {

        "method": "http",

        "type": "dv",

        "settings": {

            "min_tls_version:": "1.2"

        }

    }

  }'


```

## Cipher suites

For security and regulatory reasons, you may want to only allow connections from certain cipher suites. Cloudflare provides recommended values and full cipher suite reference in our [Cipher suites documentation](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/#resources).

Restrict cipher suites for your zone

Refer to [Customize cipher suites - SSL/TLS](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/cipher-suites/customize-cipher-suites/).

Restrict cipher suites for custom hostname

In the API documentation, refer to [SSL properties of a custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/). Besides the `settings` specifications, you must include `type` and `method` within the `ssl` object, as explained below.

1. Make a `GET` request to the [Custom Hostname Details](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/) endpoint to check what are the current values for `ssl.type` and `ssl.method`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

Custom Hostname Details

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Response example

```

  "success": true,

  "result": {

    "id": "<CUSTOM_HOSTNAME_ID>",

    "ssl": {

12 collapsed lines

      "id": "<CERTIFICATE_ID>",

      "bundle_method": "ubiquitous",

      "certificate_authority": "<CERTIFICATE_AUTHORITY>",

      "custom_certificate": "",

      "custom_csr_id": "",

      "custom_key": "",

      "expires_on": "",

      "hosts": [

        "app.example.com",

        "*.app.example.com"

      ],

      "issuer": "",

      "method": "http",

      "settings": {},

      "signature": "SHA256WithRSA",

      "type": "dv",

20 collapsed lines

      "uploaded_on": "2020-02-06T18:11:23.531995Z",

      "validation_errors": [

        {

          "message": "SERVFAIL looking up CAA for app.example.com"

        }

      ],

      "validation_records": [

        {

          "emails": [

            "administrator@example.com",

            "webmaster@example.com"

          ],

          "http_body": "ca3-574923932a82475cb8592200f1a2a23d",

          "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt",

          "txt_name": "_acme-challenge.app.example.com",

          "txt_value": "810b7d5f01154524b961ba0cd578acc2"

        }

      ],

      "wildcard": false

    },

  }


```

1. After you take note of these values, make a `PATCH` request to the [Edit Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) endpoint, providing both the list of authorized cipher suites and the same `type` and `method` values that you obtained from the previous step.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "ssl": {

        "method": "http",

        "type": "dv",

        "settings": {

            "ciphers": [

                "ECDHE-ECDSA-AES128-GCM-SHA256",

                "ECDHE-RSA-AES128-GCM-SHA256"

            ]

        }

    }

  }'


```

Restrict cipher suites for custom hostname with custom certificate

In the API documentation, refer to [SSL properties of a custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/). In the case of a custom hostname with custom certificate, you must include the custom certificate in the [Edit Custom Hostname PATCH call](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/), with the `settings` specifications where you must include `type` and `method` within the `ssl` object, as explained below.

1. Make a `GET` request to the [Custom Hostname Details](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/) endpoint to check what are the current values for `ssl.type` and `ssl.method`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

Custom Hostname Details

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

Response example

```

  "success": true,

  "result": {

    "id": "<CUSTOM_HOSTNAME_ID>",

    "ssl": {

12 collapsed lines

      "id": "<CERTIFICATE_ID>",

      "bundle_method": "ubiquitous",

      "certificate_authority": "<CERTIFICATE_AUTHORITY>",

      "custom_certificate": "",

      "custom_csr_id": "",

      "custom_key": "",

      "expires_on": "",

      "hosts": [

        "app.example.com",

        "*.app.example.com"

      ],

      "issuer": "",

      "method": "http",

      "settings": {},

      "signature": "SHA256WithRSA",

      "type": "dv",

20 collapsed lines

      "uploaded_on": "2020-02-06T18:11:23.531995Z",

      "validation_errors": [

        {

          "message": "SERVFAIL looking up CAA for app.example.com"

        }

      ],

      "validation_records": [

        {

          "emails": [

            "administrator@example.com",

            "webmaster@example.com"

          ],

          "http_body": "ca3-574923932a82475cb8592200f1a2a23d",

          "http_url": "http://app.example.com/.well-known/pki-validation/ca3-da12a1c25e7b48cf80408c6c1763b8a2.txt",

          "txt_name": "_acme-challenge.app.example.com",

          "txt_value": "810b7d5f01154524b961ba0cd578acc2"

        }

      ],

      "wildcard": false

    },

  }


```

1. After you take note of these values, make a `PATCH` request to the [Edit Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) endpoint, providing both the list of authorized cipher suites and the same `type` and `method` values that you obtained from the previous step, but also the `custom_certificate` and `custom_key`.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "ssl": {

        "method": "http",

        "type": "dv",

        "custom_certificate": "<CERTIFICATE_STRING>",

        "custom_key": "<CERTIFICATE_PRIVATE_KEY>",

        "settings": {

            "ciphers": [

                "ECDHE-ECDSA-AES128-GCM-SHA256",

                "ECDHE-RSA-AES128-GCM-SHA256"

            ],

            "min_tls_version": "1.2"

        }

    }

  }'


```

## Alerts for mutual TLS certificates

You can configure alerts to receive notifications before your mutual TLS certificates expire.

Access mTLS Certificate Expiration Alert

**Who is it for?**

[Access](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/) customers that use client certificates for mutual TLS authentication. This notification will be sent 30 and 14 days before the expiration of the certificate.

**Other options / filters**

None.

**Included with**

Purchase of [Access](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/) and/or [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/).

**What should you do if you receive one?**

Upload a [renewed certificate](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/mutual-tls-authentication/#add-mtls-authentication-to-your-access-configuration).

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/","name":"TLS Management"}}]}
```

---

---
title: Issue
description: Cloudflare automatically issues certificates when you create a custom hostname.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Issue

Cloudflare automatically issues certificates when you [create a custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/).

Note

There are several required steps before a custom hostname and its certificate can become active. For more details, refer to our [Get started guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/).

## Certificate authorities

If you create the custom hostname via API, you can leave the `certificate_authority` parameter empty to set it to “default CA”. With this option, Cloudflare checks the CAA records before requesting the certificates, which helps ensure the certificates can be issued from the CA.

Refer to [this certificate authorities reference page](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) to learn more about the CAs that Cloudflare uses to issue SSL/TLS certificates.

## Certificate details and compatibility

For each custom hostname, Cloudflare issues two certificates bundled in chains that maximize browser compatibility (unless you [upload custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/)).

The primary certificate uses a `P-256` key, is `SHA-2/ECDSA` signed, and will be presented to browsers that support elliptic curve cryptography (ECC). The secondary or fallback certificate uses an `RSA 2048-bit` key, is `SHA-2/RSA` signed, and will be presented to browsers that do not support ECC.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/issue-certificates/","name":"Issue"}}]}
```

---

---
title: Renew
description: Renew custom hostname certificates before their 90-day expiration.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Renew

The exact method for certificate renewal depends on whether that hostname is active[1](#user-content-fn-1) and whether it is a wildcard certificate.

Custom hostname certificates have a 90-day validity period and are available for renewal 30 days before their expiration.

## Non-wildcard hostnames

If all of the following are true, Cloudflare will try to perform DCV automatically on the hostname's behalf by serving the [HTTP token](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/).

* You are using a non-wildcard hostname.
* The hostname is active.
* You are not using [Delegated DCV](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/).

If the custom hostname is not active, then the custom hostname domain owner will need to add the TXT or HTTP DCV token for the new certificate to validate and issue. As the SaaS provider, you will be responsible for sharing this token with the custom hostname domain owner.

If you are using Delegated DCV, Cloudflare will continue to add TXT DCV tokens on your behalf as explained in [Issue and validate certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/).

## Wildcard hostnames

With wildcard hostnames, you cannot use HTTP. In this case, you will have to use TXT DCV tokens.

These tokens can be fetched through the API or the dashboard when the certificates are in a [pending validation](https://developers.cloudflare.com/ssl/reference/certificate-statuses/#new-certificates) state during custom hostname creation or during certificate renewals.

If your hostname is using another validation method, you will need to [update](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) the `"method"` field in the SSL object to be `"txt"`.

After this step, follow the normal steps for [TXT validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/).

Note

To allow Cloudflare to auto-renew all future certificate orders, consider [DCV delegation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/).

## Footnotes

1. Meaning Cloudflare could verify your customer's ownership of the hostname and the [hostname status](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/validation-status/) is active. [↩](#user-content-fnref-1)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/renew-certificates/","name":"Renew"}}]}
```

---

---
title: Validate
description: Learn which methods you should use to validate Cloudflare for SaaS certificates.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Validate

Before a certificate authority (CA) will issue a certificate for a domain, the requester must prove they have control over that domain. This process is known as domain control validation (DCV).

  
## DCV situations

### Non-wildcard certificates

Specific (non-wildcard) custom hostnames can use [HTTP based DCV](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/) for certificate renewals, as long as:

* The hostname is pointing to the SaaS provider.
* The hostname's traffic is proxying through the Cloudflare network.

If your custom hostnames do not meet these requirements, use another validation method.

### Wildcard certificates

Wildcard custom hostnames require TXT-based validation. As the SaaS provider, you have two options for wildcard custom hostname certificate renewals:

  
* [DCV Delegation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/) (auto-issuance)
* [Manual](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/)

### Minimize downtime

If you want to minimize downtime, explore one of the following methods to issue and deploy the certificate before onboarding your customers:

* [Delegated DCV](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/): Place a one-time record at your authoritative DNS that allows Cloudflare to auto-renew all future certificate orders.
* [TXT validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/): Have your customers add a `TXT` record to their authoritative DNS.
* [Manual HTTP validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/#http-manual): Add a `TXT` record at your origin.

### Minimize customer effort

If you value simplicity and your customers can handle a few minutes of downtime, you can rely on Cloudflare [automatic HTTP validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/#http-automatic).

## Potential issues

To avoid or solve potential issues, refer to our [troubleshooting guide](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/troubleshooting/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/","name":"Validate"}}]}
```

---

---
title: Delegated
description: Delegate domain control validation to Cloudflare for automated certificate issuance.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Delegated

Delegated DCV allows SaaS providers to delegate the DCV process to Cloudflare.

DCV Delegation requires your customers to place a one-time record at their authoritative DNS that allows Cloudflare to auto-renew all future certificate orders, so that there is no manual intervention from you or your customers at the time of the renewal.

---

## Setup

To set up Delegated DCV:

1. Add a [custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/create-custom-hostnames/) for your zone, choosing `TXT` as the **Certificate validation method**.
2. On the [**Custom Hostnames** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames) page, go to **DCV Delegation for Custom Hostnames**.
3. Copy the hostname value.
4. For each hostname, the domain owner needs to place a `CNAME` record at their authoritative DNS. In this example, the SaaS zone is `example.com`.  
```  
_acme-challenge.example.com CNAME example.com.<COPIED_HOSTNAME>.  
```

Once this is complete, Cloudflare will place two TXT DCV records - one for `example.com` and one for `*.example.com` \- at the `example.com.<COPIED_HOSTNAME>` hostname. The CNAME record will need to stay in place in order to allow Cloudflare to continue placing the records for the renewals.

If desired, you could also manually fetch the DCV tokens and share them with your customers.

Remove previous TXT records

Existing TXT records for `_acme-challenge` will conflict with the delegated DCV CNAME record. Make sure to check and remove records such as the following:

```

_acme-challenge.example.com TXT <CERTIFICATE_VALIDATION_VALUE>


```

## Moved domains

If you [move your SaaS zone to another account](https://developers.cloudflare.com/fundamentals/manage-domains/move-domain/), you will need to update the `CNAME` record with a new hostname value.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/","name":"Validate"}},{"@type":"ListItem","position":8,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/","name":"Delegated"}}]}
```

---

---
title: HTTP
description: Validate domain ownership by placing a DCV token on your customer origin.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# HTTP

HTTP validation involves adding a DCV token to your customer's origin.

---

## Non-wildcard custom hostnames

If your custom hostname does not include a wildcard, Cloudflare will always and automatically attempt to complete DCV through [HTTP validation](#http-automatic), even if you have selected **TXT** for your validation method.

This HTTP validation should succeed as long as your customer is pointing to your custom hostname and they do not have any [CAA records](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/troubleshooting/#certificate-authority-authorization-caa-records) blocking your chosen certificate authority.

## Wildcard custom hostnames

HTTP DCV validation is not allowed for wildcard certificates. You must use [TXT validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/) instead.

---

## Validation methods

### HTTP (automatic)

If you value simplicity and your customers can handle a few minutes of downtime, you can rely on Cloudflare automatic HTTP validation.

Once you [create a new hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/issue-certificates/) and choose the `http` validation method, all your customers have to do is add a CNAME to your `$CNAME_TARGET` and Cloudflare will take care of the rest.

What happens after you create the custom hostname

Cloudflare contacts one of our certificate authority (CA) providers and asks them to issue certificates for the specified hostname. The CA will then inform Cloudflare that we need to demonstrate control of this hostname by returning a `$DCV_TOKEN` at a specified `$DCV_FILENAME`; both the token and the filename are randomly generated by the CA and not known to Cloudflare ahead of time.

For example, if you create a new custom hostname for `site.example.com`, the CA might ask us to return the value `ca3-38734555d85e4421beb4a3e6d1645fe6` for a request to `http://site.example.com/.well-known/pki-validation/ca3-39f423f095be4983922ca0365308612d.txt"`. As soon as we receive that value from the CA we make it accessible at our edge and ask the CA to confirm it is there so that they can complete validation and the certificate order.

Note

Cloudflare is able to serve a random token from our edge due to the fact that `site.example.com` has a CNAME in place to `$CNAME_TARGET`, which ultimately resolves to Cloudflare IPs. If your customer has not yet added the CNAME, the CA will not be able to retrieve the token and the process will not complete.

We will attempt to retry this validation check for a finite period before timing out. Refer to [Validation Retry Schedule](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/) for more details.

If you would like to complete the issuance process before asking your customer to update their CNAME (or before changing the resolution of your target CNAME to be proxied by Cloudflare), choose another validation method.

### HTTP (manual)

Once you [create a new hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/issue-certificates/) and choose this validation method, you will see the following values after a few seconds:

  
* [**API**](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/): Within the `ssl` object, store the values present in the `validation_records` array (specifically `http_url` and `http_body`).
* **Dashboard**: When viewing an individual certificate on the [**Custom Hostnames** ↗](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames) page, refer to the values for **Certificate validation request** and **Certificate validation response**.

At your origin, make the `http_body` available in a TXT record at the path specified in `http_url`. This path should also be publicly accessible to anyone on the Internet so your CA can access it.

Here is an example NGINX configuration that would return a token:

```

location "/.well-known/pki-validation/ca3-0052344e54074d9693e89e27486692d6.txt" {

       return 200 "ca3-be794c5f757b468eba805d1a705e44f6\n";

}


```

Once your configuration is live, test that the DCV text file is in place with `curl`:

Terminal window

```

$ curl "http://http-preval.example.com/.well-known/pki-validation/ca3-0052344e54074d9693e89e27486692d6.txt"

ca3-be794c5f757b468eba805d1a705e44f6


```

The token is valid for one check cycle. On the next check cycle, Cloudflare will ask the CA to recheck the URL, complete validation, and issue the certificate.

If you would like to request an immediate recheck, [rather than wait for the next retry](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/), send a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) with the same values as your initial `POST` request.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/","name":"Validate"}},{"@type":"ListItem","position":8,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/","name":"HTTP"}}]}
```

---

---
title: Troubleshooting
description: Resolve certificate validation issues including high-risk domains and CA errors.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Troubleshooting

## High-risk domains

Occasionally, a domain will be flagged as “high risk” by Cloudflare’s CA partners. Typically this is done only for domains with an Alexa ranking of 1-1,000 and domains that have been flagged for phishing or malware by Google’s Safe Browsing service.

If a domain is flagged by the CA, you need to contact Support before validation can finish. The API call will return indicating the failure, along with a link to where the ticket can be filed.

---

## Certificate Authority Authorization (CAA) records

CAA is a DNS resource record type defined in [RFC 6844 ↗](https://datatracker.ietf.org/doc/html/rfc6844) that allows a domain owner to indicate which CAs are allowed to issue certificates for them.

### For SaaS providers

If your customer has CAA records set on their domain, they will either need to add the following or remove CAA entirely:

```

example.com. IN CAA 0 issue "pki.goog"

example.com. IN CAA 0 issue "letsencrypt.org"

example.com. IN CAA 0 issue "ssl.com"


```

While it is possible for CAA records to be set on the subdomain your customer wishes to use with your service, it will usually be set on the domain apex. If they have CAA records on the subdomain, those will also have to be removed.

### For SaaS customers

In some cases, the validation may be prevented because your hostname points to a CNAME target where CAA records are defined.

In this case you would need to either select a Certificate Authority whose CAA records are present at the target, or review the configuration with the service provider that owns the target.

---

## Time outs

If a certificate issuance times out, the error message will indicate where the timeout occurred:

* Timed Out (Initializing)
* Timed Out (Validation)
* Timed Out (Issuance)
* Timed Out (Deployment)
* Timed Out (Deletion)

To fix this error, send a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) through the API or select **Refresh** for the specific custom hostname in the dashboard. If using the API, make sure that the `--data` field contains an `ssl` object with the same `method` and `type` as the original request.

If these return an error, delete and recreate the custom hostname.

---

## Immediate validation checks

You can send a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) to request an immediate validation check on any certificate. The PATCH data should include the same `ssl` object as the original request.

---

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/","name":"Validate"}},{"@type":"ListItem","position":8,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/troubleshooting/","name":"Troubleshooting"}}]}
```

---

---
title: TXT
description: Validate domain ownership with a TXT DNS record for certificate issuance.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# TXT

TXT record validation requires the creation of a TXT record in the hostname's authoritative DNS.

  
## When to use

Generally, you should use TXT-based DCV when you cannot use [HTTP validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/) or [Delegated DCV](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/).

### Non-wildcard custom hostnames

If your custom hostname does not include a wildcard, Cloudflare will always and automatically attempt to complete DCV through [HTTP validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/#http-automatic), even if you have selected **TXT** for your validation method.

This HTTP validation should succeed as long as your customer is pointing to your custom hostname and they do not have any [CAA records](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/troubleshooting/#certificate-authority-authorization-caa-records) blocking your chosen certificate authority.

### Wildcard custom hostnames

To validate a certificate on a wildcard custom hostname, you should either set up [Delegated DCV](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/delegated-dcv/) or [TXT-based DCV](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/).

Cloudflare recommends Delegated DCV as it is much simpler for you and your customers.

If you choose TXT-based DCV, Cloudflare requires two TXT DCV tokens - one for the apex and one for the wildcard - to be placed at your customer’s authoritative DNS provider in order for the wildcard certificate to issue or renew.

These two tokens are required because Let’s Encrypt and Google Trust Services follow the [ACME Protocol ↗](https://datatracker.ietf.org/doc/html/rfc8555), which requires one DCV token to be placed for every hostname on the certificate.

This means that - if you choose to use wildcard custom hostnames - you will need a way to share these DCV tokens with your customer.

---

### 1\. Get TXT tokens

Once you [create a new hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/issue-certificates/) and choose this validation method, your tokens will be ready after a few seconds.

These tokens can be fetched through the API or the dashboard when the certificates are in a [pending validation](https://developers.cloudflare.com/ssl/reference/certificate-statuses/#new-certificates) state during custom hostname creation or during certificate renewals.

* [ API ](#tab-panel-4537)
* [ Dashboard ](#tab-panel-4538)

You can access these tokens using the API with the [GET custom hostnames endpoint](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/list/).

For example, here are two tokens highlighted in the API response for a **wildcard** custom hostname.

Response

```

{

  "result": [

    {

      "id": "<HOSTNAME_ID>",

      "hostname": "<HOSTNAME>",

      "ssl": {

        "id": "<CERTIFICATE_ID>",

        "type": "dv",

        "method": "txt",

        "status": "pending_validation",

        "validation_records": [

          {

            "status": "pending",

            "txt_name": "_acme-challenge.<HOSTNAME>",

            "txt_value": "gESljTB8fBT1mIuoEASU0qcK-oTd46baarnU_ZGjJIY"

          },

          {

            "status": "pending",

            "txt_name": "_acme-challenge.<HOSTNAME>",

            "txt_value": "Pd8ViwX8KuA78kLbQHGmdEh4tQSpHBRxiNuJOYStEC0"

          }

        ],

        "settings": {

          "min_tls_version": "1.0"

        },

        "bundle_method": "ubiquitous",

        "wildcard": true,

        "certificate_authority": "google"

      },

      "status": "pending",

      "ownership_verification": {

        "type": "txt",

        "name": "_cf-custom-hostname.<HOSTNAME>",

        "value": "ac4a9a9d-5469-44cb-9d76-cea7541c9ff8"

      },

      "ownership_verification_http": {

        "http_url": "http://<HOSTNAME>/.well-known/cf-custom-hostname-challenge/fabdf93c-a4ce-4075-9f3f-c553a5f93bed",

        "http_body": "ac4a9a9d-5469-44cb-9d76-cea7541c9ff8"

      },

      "created_at": "2022-10-06T19:35:33.143257Z"

    }

  ]

}


```

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Select a hostname.
3. Copy the values for **Certificate validation TXT name** and **Certificate validation TXT value**.

If you had previously created a **wildcard** custom hostname, you would need to copy the values for two different validation TXT records.

### 2\. Share with your customer

You will then need to share these TXT tokens with your customers.

### 3\. Add DNS records (customer)

Your customers should place these at their authoritative DNS provider under the `"_acme-challenge"` DNS label. Once these TXT records are in place, validation and certificate issuance will automatically complete.

Note

These tokens are different than the hostname validation tokens.

If you would like to request an immediate recheck, [rather than wait for the next retry](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/), send a [PATCH request](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/) with the same values as your initial `POST` request.

### 4\. (Optional) Fetch new tokens

Your DCV tokens expire after a [certain amount of time](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/reference/token-validity-periods/), depending on your certificate authority.

This means that, if your customers take too long to place their tokens at their authoritative DNS provider, you may need to [get new tokens](#1-get-txt-tokens) and re-share them with your customer.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/","name":"Issue and validate certificates"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/","name":"Validate"}},{"@type":"ListItem","position":8,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/txt/","name":"TXT"}}]}
```

---

---
title: Webhook definitions
description: Webhook event data for certificate issuance, validation, and custom hostname changes.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ JSON ](https://developers.cloudflare.com/search/?tags=JSON) 

# Webhook definitions

When you [create a webhook notification](https://developers.cloudflare.com/notifications/get-started/configure-webhooks/) for **SSL for SaaS Custom Hostnames**, you may want to automate responses to specific events (certificate issuance, failed validation, etc.).

The following section details the data Cloudflare sends to a webhook destination.

## Certificate validation

Before a Certificate Authority will issue a certificate for a domain, the requester must prove they have control over that domain. This process is known as [domain control validation (DCV)](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/).

### Validation succeeded

Cloudflare sends this alert when certificates move from a status of `pending_validation` to `pending_issuance`.

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.validation.succeeded",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_issuance",

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

### Validation failed

Cloudflare sends this alert each time a certificate remains in a `pending_validation` status during [DCV retries](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/).

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.validation.failed",

      "created_at": "2018-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_validation",

      "cname": "_ca3-64ce913ebfe74edeb2e8813e3928e359.app.example2.com",

      "cname_target": "dcv.digicert.com",

      "validation_errors": [

        {

          "message": "blog.example.com reported as potential risk: google_safe_browsing"

        }

      ],

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

---

## Certificate issuance

Once validated, certificates are issued by Cloudflare in conjunction with your chosen [certificate authority](https://developers.cloudflare.com/ssl/reference/certificate-authorities/).

### Issuance succeeded

Cloudflare sends this alert when certificates move from a status of `pending_validation` or `pending_issuance` to `pending_deployment`.

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.issuance.succeeded",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_deployment",

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

### Issuance failed

Cloudflare sends this alert each time a certificate remains in a status of `pending_issuance` during [DCV retries](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/).

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.issuance.failed",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_issuance",

      "cname": "_ca3-64ce913ebfe74edeb2e8813e3928e359.app.example2.com",

      "cname_target": "dcv.digicert.com",

      "validation_errors": [

        {

          "message": "caa_error: blog.example.com"

        }

      ],

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

---

## Certificate deployment

Once issued, certificates are deployed to Cloudflare's global edge network.

### Deployment succeeded

Cloudflare sends this alert when certificates move from a status of `pending_deployment` to `active`.

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.deployment.succeeded",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "active",

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

### Deployment failed

Cloudflare sends this alert each time a certificate remains in a status of `pending_deployment` during [DCV retries](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/).

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.deployment.failed",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_deployment",

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

---

## Certificate deletion

### Deletion succeeded

Cloudflare sends this alert when certificates move from a status of `pending_deletion` to `deleted`.

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.deletion.succeeded",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "deleted"

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

### Deletion failed

Cloudflare sends this alert each time a certificate remains in status of `pending_deletion` during [DCV retries](https://developers.cloudflare.com/ssl/edge-certificates/changing-dcv-method/validation-backoff-schedule/).

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.deletion.failed",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_deletion"

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

---

## Certificate renewal

Once issued, certificates are valid for a period of time depending on the [certificate authority](https://developers.cloudflare.com/ssl/reference/certificate-validity-periods/).

The actions that you need to perform to renew certificates depend on your [validation method](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/renew-certificates/).

### Upcoming renewal

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.renewal.upcoming_certificate_expiration_notification",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "status": "active",

      "hosts": ["blog.example.com"],

      "issuer": "DigiCertInc",

      "serial_number": "1001172778337169491",

      "signature": "ECDSAWithSHA256",

      "uploaded_on": "2021-11-17T04:33:54.561747Z",

      "expires_on": "2022-11-21T12:00:00Z",

      "custom_csr_id": "7b163417-1d2b-4c84-a38a-2fb7a0cd7752",

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

### Renewal succeeded

Cloudflare sends this alert when certificates move from a status of `active` to `pending_deployment`.

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.renewal.succeeded",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_deployment",

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

### Renewal failed

Cloudflare sends this alert when certificates move from a status of `active` to `pending_issuance`.

```

{

  "metadata": {

    "event": {

      "id": "<<WEBHOOK_ID>",

      "type": "ssl.custom_hostname_certificate.renewal.failed",

      "created_at": "2022-02-09T00:03:28.385080Z"

    },

    "account": {

      "id": "<<ACCOUNT_ID>"

    },

    "zone": {

      "id": "<<ZONE_ID>"

    }

  },

  "data": {

    "id": "<<CUSTOM_HOSTNAME_ID>",

    "hostname": "blog.com",

    "ssl": {

      "id": "<<CERTIFICATE_ID>",

      "type": "dv",

      "method": "cname",

      "status": "pending_issuance",

      "cname": "_ca3-64ce913ebfe74edeb2e8813e3928e359.app.example2.com",

      "cname_target": "dcv.digicert.com",

      "validation_errors": [

        {

          "message": "caa_error: blog.example.com"

        }

      ],

      "settings": {

        "min_tls_version": "1.2",

        "http2": "on"

      }

    },

    "custom_metadata": {

      "key1": "value1",

      "key2": "value2"

    },

    "custom_origin_server": "0001.blog.com"

  }

}


```

## Troubleshooting

Occasionally, you may see webhook notifications that do not include a corresponding `<<CUSTOM_HOSTNAME_ID>>` and `hostname` values.

This behavior is because each custom hostname can only have one certificate attached to it. Previously attached certificates can still emit webhook events but will not include the associated hostname and ID values.

## Alerts

You can configure alerts to receive notifications for changes in your custom hostname certificates.

SSL for SaaS Custom Hostnames Alert

**Who is it for?**

Customers with custom hostname certificates who want to receive a notification on validation, issuance, renewal, and expiration of certificates. For more details around data formatting for webhooks, refer to the [Cloudflare for SaaS docs](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/webhook-definitions/).

**Other options / filters**

None.

**Included with**

Purchase of [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/).

**What should you do if you receive one?**

You only need to take action if you are notified that you have a certificate that failed. You can find the reasons why a certificate is not being issued in [Troubleshooting SSL errors](https://developers.cloudflare.com/ssl/troubleshooting/general-ssl-errors/).

Refer to [Cloudflare Notifications](https://developers.cloudflare.com/notifications/get-started/) for more information on how to set up an alert.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/","name":"Certificate management"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/webhook-definitions/","name":"Webhook definitions"}}]}
```

---

---
title: Secure with Cloudflare Access
description: Control access to custom hostnames using Cloudflare Access identity and device policies.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Secure with Cloudflare Access

Cloudflare Access provides visibility and control over who has access to your [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/). You can allow or block users based on identity, device posture, and other [Access rules](https://developers.cloudflare.com/cloudflare-one/access-controls/policies/).

## Prerequisites

* You must have an active custom hostname. For setup instructions, refer to [Configuring Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/).
* You must have a Cloudflare Zero Trust plan in your SaaS provider account. Learn more about [getting started with Zero Trust](https://developers.cloudflare.com/cloudflare-one/setup/).
* You can only run Access on custom hostnames if they are managed externally to Cloudflare or in a separate Cloudflare account. If the custom hostname zone is in the same account as the SaaS zone, the Access application will not be applied.

## Setup

1. At your SaaS provider account, select [Zero Trust ↗](https://one.dash.cloudflare.com).
2. Go to **Access** \> **Applications**.
3. Select **Add an application** and, for type of application, select **Self-hosted**.
4. Enter a name for your Access application and, in **Session Duration**, choose how often the user's [application token](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/application-token/) should expire.
5. Select **Add public hostname**.
6. For **Input method**, select _Custom_.
7. In **Hostname**, enter your custom hostname (for example, `mycustomhostname.com`).
8. Follow the remaining [self-hosted application creation steps](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/) to publish the application.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/secure-with-access/","name":"Secure with Cloudflare Access"}}]}
```

---

---
title: WAF for SaaS
description: Apply custom rules, rate limiting, and managed rulesets per custom hostname.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# WAF for SaaS

[Web Application Firewall (WAF)](https://developers.cloudflare.com/waf/) allows you to create additional security measures through Cloudflare. As a SaaS provider, you can link custom rules, rate limiting rules, and managed rules to your custom hostnames. This provides more control to keep your domains safe from malicious traffic.

As a SaaS provider, you may want to apply different security measures to different custom hostnames. With WAF for SaaS, you can create multiple WAF configuration that you can apply to different sets of custom hostnames. This added flexibility and security leads to optimal protection across the domains of your end customers.

---

## Prerequisites

Before you can use WAF for SaaS, you need to create a custom hostname. Review [Get started with Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) if you have not already done so.

You can also create a custom hostname through the API:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Create Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames" \

  --request POST \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "hostname": "<CUSTOM_HOSTNAME>",

    "ssl": {

        "wildcard": false

    }

  }'


```

## 1\. Associate custom metadata to a custom hostname

To apply WAF to your custom hostname, you need to create an association between your customer's domain and the WAF configuration that you would like to attach to it. Cloudflare's product, [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) allows you to do this via the API.

1. [Locate your zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/), available in the Cloudflare dashboard.
2. Locate your Authentication Key on the [**API Tokens** ↗](https://dash.cloudflare.com/?to=/:account/profile/api-tokens) page, under **Global API Key**.
3. Locate your custom hostname ID by making a `GET` call in the API:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`
* `SSL and Certificates Read`

List Custom Hostnames

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames" \

  --request GET \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"


```

1. Plan your [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/). It is fully customizable. In the example below, we have chosen the tag `"security_level"` to which we expect to assign three values (low, medium, and high).

Note

One instance of low, medium, and high rules could be rate limiting. You can specify three different thresholds: low - 100 requests/minute, medium - 85 requests/minute, high - 50 requests/minute, for example. Another possibility is a WAF custom rule in which low challenges requests and high blocks them.

1. Make an API call in the format below using your Cloudflare email and the IDs gathered above:

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `SSL and Certificates Write`

Edit Custom Hostname

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/custom_hostnames/$CUSTOM_HOSTNAME_ID" \

  --request PATCH \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "custom_metadata": {

        "customer_id": "12345",

        "security_level": "low"

    }

  }'


```

This assigns custom metadata to your custom hostname so that it has a security tag associated with its ID.

## 2\. Trigger security products based on tags

1. Locate the custom metadata field in the Ruleset Engine where the WAF runs. This can be used to trigger different configurations of products such as [WAF custom rules](https://developers.cloudflare.com/waf/custom-rules/), [rate limiting rules](https://developers.cloudflare.com/waf/rate-limiting-rules/), and [Transform Rules](https://developers.cloudflare.com/rules/transform/).
2. Build your rules either [through the dashboard](https://developers.cloudflare.com/waf/custom-rules/create-dashboard/) or via the API. An example rate limiting rule, corresponding to `"security_level"` low, is shown below as an API call.

Required API token permissions

At least one of the following [token permissions](https://developers.cloudflare.com/fundamentals/api/reference/permissions/)is required:
* `Response Compression Write`
* `Config Settings Write`
* `Dynamic URL Redirects Write`
* `Cache Settings Write`
* `Custom Errors Write`
* `Origin Write`
* `Managed headers Write`
* `Zone Transform Rules Write`
* `Mass URL Redirects Write`
* `Magic Firewall Write`
* `L4 DDoS Managed Ruleset Write`
* `HTTP DDoS Managed Ruleset Write`
* `Sanitize Write`
* `Transform Rules Write`
* `Select Configuration Write`
* `Bot Management Write`
* `Zone WAF Write`
* `Account WAF Write`
* `Account Rulesets Write`
* `Logs Write`
* `Logs Write`

Update a zone entry point ruleset

```

curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/phases/http_ratelimit/entrypoint" \

  --request PUT \

  --header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \

  --json '{

    "rules": [

        {

            "action": "block",

            "ratelimit": {

                "characteristics": [

                    "cf.colo.id",

                    "ip.src"

                ],

                "period": 10,

                "requests_per_period": 2,

                "mitigation_timeout": 60

            },

            "expression": "lookup_json_string(cf.hostname.metadata, \"security_level\") eq \"low\" and http.request.uri contains \"login\""

        }

    ]

  }'


```

To build rules through the dashboard:

1. In the Cloudflare dashboard, go to the **WAF** page.  
[ Go to **WAF** ](https://dash.cloudflare.com/?to=/:account/application-security/waf)
2. Follow the instructions on the dashboard specific to custom rules, rate limiting rules, or managed rules, depending on your security goal.
3. Once the rule is active, you should see it under the applicable tab (custom rules, rate limiting, or managed rules).  
Warning  
This API call will replace any existing rate limiting rules in the zone.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/","name":"WAF for SaaS"}}]}
```

---

---
title: Managed rulesets
description: Deploy WAF managed rulesets per custom hostname using WAF for SaaS.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Managed rulesets

If you are interested in [WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/) but unsure of where to start, Cloudflare recommends using WAF Managed Rules. The Cloudflare security team creates and manages a variety of rules designed to detect common attack vectors and protect applications from vulnerabilities. These rules are offered in [managed rulesets](https://developers.cloudflare.com/waf/managed-rules/), like Cloudflare Managed and OWASP, which can be deployed with different settings and sensitivity levels.

---

## Prerequisites

WAF for SaaS is available for customers on an Enterprise plan.

If you would like to deploy a managed ruleset at the account level, refer to the [WAF documentation](https://developers.cloudflare.com/waf/account/managed-rulesets/deploy-dashboard/).

Ensure you have reviewed [Get Started with Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) and familiarize yourself with [WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/).

Customers can automate the [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) tagging by adding it to the custom hostnames at creation. For more information on tagging a custom hostname with custom metadata, refer to the [API documentation](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/).

---

## 1\. Choose security tagging system

1. Outline `security_tag` buckets. These are fully customizable with no strict limit on quantity. For example, you can set `security_tag` to `low`,`medium`, and `high` as a default, with one tag per custom hostname.
2. If you have not already done so, [associate your custom metadata to custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/#1-associate-custom-metadata-to-a-custom-hostname) by including the `security_tag`in the custom metadata associated with the custom hostname. The JSON blob associated with the custom hostname is fully customizable.

After the association is complete, the JSON blob is added to the defined custom hostname. This blob is then associated to every incoming request and exposed in the WAF through the [cf.hostname.metadata](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/cf.hostname.metadata/) field. In the rule, you can access `cf.hostname.metadata` and get the data you need from that blob.

---

## 2\. Deploy rulesets

Note

Account-level WAF requires an Enterprise plan with a paid add-on.

1. In the Cloudflare dashboard, go to the **WAF** page.  
[ Go to **WAF** ](https://dash.cloudflare.com/?to=/:account/application-security/waf)
2. Go to the **Managed rulesets** tab.
3. Select **Deploy** \> **Deploy managed ruleset**.
4. Next to **Cloudflare Managed Ruleset**, choose **Select ruleset**.
5. Give a name to the rule deploying the ruleset in **Execution name**.
6. Select **Edit scope** to execute the managed ruleset for a subset of incoming requests.
7. Select **Custom filter expression**.
8. Select **Edit expression** to switch to the [Expression Editor](https://developers.cloudflare.com/ruleset-engine/rules-language/expressions/edit-expressions/#expression-editor).
9. The basic expression should look like this, plus any logic you would like to add (like filtering by a specific custom hostname with `http.host eq "<HOSTNAME>"`):  
```  
(lookup_json_string(cf.hostname.metadata, "security_tag") eq "low") and (cf.zone.plan eq "ENT")  
```  
Note  
Rulesets deployed at the account level will only apply to incoming traffic of Enterprise domains on your account. When you define a custom expression using the Expression Editor, use parentheses to enclose any custom conditions and end your expression with `and (cf.zone.plan eq "ENT")` so that the rule only applies to domains on an Enterprise plan.
10. Select **Next**.
11. (Optional) You can modify the ruleset configuration by changing, for example, what rules are enabled or what action should be the default.
12. Select **Deploy**.

## Next steps

While this guide uses the Cloudflare Managed Ruleset, you can also create a custom ruleset and deploy on your custom hostnames. To do this, go to the **Custom rulesets** tab and select **Create ruleset**. For examples of a low/medium/high ruleset, refer to [WAF for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/","name":"Security"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/","name":"WAF for SaaS"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/security/waf-for-saas/managed-rulesets/","name":"Managed rulesets"}}]}
```

---

---
title: Apex proxying
description: Allow your customers to use apex domains with your SaaS application.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ DNS ](https://developers.cloudflare.com/search/?tags=DNS) 

# Apex proxying

Apex proxying allows your customers to use their apex domains (`example.com`) with your SaaS application.

Note

Only certain customers have access to this feature. For more details, see the [Plans page](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

## Benefits

In a normal Cloudflare for SaaS [setup](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/), your customers route traffic to your hostname by creating a `CNAME` record pointing to your CNAME target.

However, most DNS providers do not allow `CNAME` records at the zone's root[1](#user-content-fn-1). This means that your customers have to use a subdomain as a vanity domain (`shop.example.com`) instead of their domain apex (`example.com`).

This limitation does not apply with apex proxying. Cloudflare assigns a set of IP prefixes - cost associated, reach out to your account team - to your account (or uses your own if you have [BYOIP](https://developers.cloudflare.com/byoip/)). This means that customers can create a standard `A` record to route traffic to your domain, which can support the domain apex.

## Setup

* [Set up Apex Proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/setup/)

## Footnotes

1. Cloudflare offers this functionality through [CNAME flattening](https://developers.cloudflare.com/dns/cname-flattening/). [↩](#user-content-fnref-1)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/","name":"Advanced Settings"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/","name":"Apex proxying"}}]}
```

---

---
title: Setup
description: Configure Cloudflare for SaaS to support apex domain custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Setup

To set up Cloudflare for SaaS for [apex proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/) \- as opposed to the [normal setup](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) \- perform the following steps.

---

## Before you begin

Before you start creating custom hostnames:

1. [Add](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) your zone to Cloudflare (this should be within the account associated with your IP prefixes).
2. [Enable](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/enable/) Cloudflare for SaaS for your zone.
3. Review the [Hostname prioritization guidelines](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority). Wildcard custom hostnames behave differently than an exact hostname match.
4. (optional) Review the following documentation:
* [API documentation](https://developers.cloudflare.com/fundamentals/api/) (if you have not worked with the Cloudflare API before).
* [Certificate validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/).

---

## Initial setup

When you first [enable](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/enable/) Cloudflare for SaaS, you need to perform a few steps prior to creating any custom hostnames.

  
### 1\. Get IP range

With apex proxying, you can either [bring your own IP range](https://developers.cloudflare.com/byoip/) or use a set of IP addresses provided by Cloudflare.

For more details on this step, reach out to your account team.

Warning

These IP addresses are different than those associated with your Cloudflare zone.

### 2\. Create fallback origin

The fallback origin is where Cloudflare will route traffic sent to your custom hostnames (must be proxied).

Note

To route custom hostnames to distinct origins, refer to [custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/).

To create your fallback origin:

1. [Create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a proxied `A`, `AAAA`, or `CNAME` record pointing to the IP address of your fallback origin (where Cloudflare will send custom hostname traffic).

| **Type** | **Name**       | **IPv4 address** | **Proxy status** |
| -------- | -------------- | ---------------- | ---------------- |
| A        | proxy-fallback | 192.0.2.1        | Proxied          |

1. Designate that record as your fallback origin.

* [ Dashboard ](#tab-panel-4539)
* [ API ](#tab-panel-4540)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. For **Fallback Origin**, enter the hostname for your fallback origin.
3. Select **Add Fallback Origin**.

Using the hostname of the record you just created, [update the fallback origin value](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/fallback%5Forigin/methods/update/).

1. Once you have added the fallback origin, confirm that its status is **Active**.

Note

When Cloudflare marks your fallback origin as **Active**, that only reflects that we are ready to send traffic to that DNS record.

You need to make sure your DNS record is sending traffic to the correct origin location.

---

## Per-hostname setup

You need to perform the following steps for each custom hostname.

### 1\. Plan for validation

Before you create a hostname, you need to plan for:

1. [Certificate validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/): Upon successful validation, the certificates are deployed to Cloudflare’s global network.
2. [Hostname validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/): Upon successful validation, Cloudflare proxies traffic for this hostname.

You must complete both these steps for the hostname to work as expected.

Note

Depending on which method you select for each of these options, additional steps might be required for you and your customers.

### 2\. Create custom hostname

After planning for certification and hostname validation, you can create the custom hostname.

Zone name restriction

Do not configure a custom hostname which matches the zone name. For example, if your SaaS zone is `example.com`, do not create a custom hostname named `example.com`.

To create a custom hostname:

* [ Dashboard ](#tab-panel-4541)
* [ API ](#tab-panel-4542)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Select **Add Custom Hostname**.
3. Add your customer's hostname `app.customer.com` and set the relevant options, including:  
   * The [minimum TLS version](https://developers.cloudflare.com/ssl/reference/protocols/).  
   * Defining whether you want to use a certificate provided by Cloudflare or [upload a custom certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/).  
   * Selecting the [certificate authority (CA)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) that will issue the certificate.  
   * Choosing the [validation method](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/).  
   * Whether you want to **Enable wildcard**, which adds a `*.<custom-hostname>` SAN to the custom hostname certificate. For more details, refer to [Hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority).  
   * Choosing a value for [Custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/).
4. Select **Add Custom Hostname**.

Default behavior

When you create a custom hostname:

* If you issue a custom hostname certificate with wildcards enabled, you cannot customize TLS settings for these wildcard hostnames.
* If you do not specify the **Minimum TLS Version**, it defaults to the zone's Minimum TLS Version. You can still [edit this setting](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version) after creation.

1. To create a custom hostname using the API, use the [Create Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) endpoint.  
   * You can leave the `certificate_authority` parameter empty to set it to "default CA". With this option, Cloudflare checks the CAA records before requesting the certificates, which helps ensure the certificates can be issued from the CA.
2. For the newly created custom hostname, the `POST` response may not return the DCV validation token `validation_records`. It is recommended to make a second [GET command](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/list/) (with a delay) to retrieve these details.

The response contains the complete definition of the new custom hostname.

Default behavior

When you create a custom hostname:

* If you issue a custom hostname certificate with wildcards enabled, you cannot customize TLS settings for these wildcard hostnames.
* If you do not specify the **Minimum TLS Version**, it defaults to the zone's Minimum TLS Version. You can still [edit this setting](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version) after creation.

Note

For each custom hostname, Cloudflare issues two certificates bundled in chains that maximize browser compatibility (unless you [upload custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/)).

The primary certificate uses a `P-256` key, is `SHA-2/ECDSA` signed, and will be presented to browsers that support elliptic curve cryptography (ECC). The secondary or fallback certificate uses an `RSA 2048-bit` key, is `SHA-2/RSA` signed, and will be presented to browsers that do not support ECC.

### 3\. Have customer create DNS record

To finish the custom hostname setup, your customer can set up either an A or CNAME record at their authoritative DNS provider.

Note

If you want your customers to be able to use CNAME records, you will need to complete the [normal setup process](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/) as well.

#### A record

If your customer uses an A record at their authoritative DNS provider, they need to point their hostname to the IP prefix allocated for your account. You should also make sure that they point to the specific IPs that you want to use for apex proxying - if you have Static IPs or BYOIP, and your customer points to any of the IPs associated to your account, validation will run.

Warning

Before your customer does this step, confirm that the hostname's **Certificate status** and **Hostname status** are both **Active**.

If not, confirm that you are using a method of [certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/#http-automatic) or [hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/) validation that occurs after your customer adds their DNS record.

Your customer's A record might look like the following:

```

example.com.  60  IN  A   192.0.2.1


```

#### CNAME record

If your customer uses a CNAME record at their authoritative DNS, they need to point their hostname to your [CNAME target](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#2-optional-create-cname-target) [1](#user-content-fn-1).

Warning

Before your customer does this step, confirm that the hostname's **Certificate status** and **Hostname status** are both **Active**.

If not, confirm that you are using a method of [certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/#http-automatic) or [hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/) validation that occurs after your customer adds their DNS record.

Your customer's CNAME record might look like the following:

```

mystore.com CNAME customers.saasprovider.com


```

#### Service continuation

If your customer is also using Cloudflare for their domain, they should keep their DNS record pointing to your SaaS provider in place for as long as they want to use your service.

For more details, refer to [Remove custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/remove-custom-hostnames/).

## Footnotes

1. If you have [regional services](https://developers.cloudflare.com/data-localization/regional-services/) set up for your custom hostnames, Cloudflare always uses the processing region associated with your DNS target record (instead of the processing region of any [custom origins](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/)).  
[↩](#user-content-fnref-1)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/","name":"Advanced Settings"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/","name":"Apex proxying"}},{"@type":"ListItem","position":7,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/setup/","name":"Setup"}}]}
```

---

---
title: Custom origin server
description: Route custom hostname traffic to a different origin server per hostname.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ TLS ](https://developers.cloudflare.com/search/?tags=TLS) 

# Custom origin server

A **custom origin server** lets you send traffic from one or more custom hostnames to somewhere besides your default proxy fallback, such as:

* `soap.stores.com` goes to `origin1.com`
* `towel.stores.com` goes to `origin2.com`

## Requirements

To use a custom origin server, you need to meet the following requirements:

* Each custom origin needs to be a valid hostname with a proxied (orange-clouded) A, AAAA, or CNAME record in your account's DNS. You cannot use an IP address.
* The DNS record for the custom origin server does not currently support wildcard values.

## Use a custom origin

To use a custom origin, select that option when [creating a new custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/) in the dashboard or include the `"custom_origin_server": your_custom_origin_server` parameter when using the API [POST command](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/).

## SNI rewrites

Note

Only certain customers have access to this feature. For more details, see the [Plans page](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

When Cloudflare establishes a connection to your default origin server, the `Host` header and SNI will both be the value of the original custom hostname.

However, if you configure that custom hostname with a custom origin, the value of the SNI will be that of the custom origin and the `Host` header will be the original custom hostname. Since these values will not match, you will not be able to use the [Full (strict)](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/) on your origins.

To solve this problem, you can contact your account team to request an entitlement for **SNI rewrites**.

### SNI rewrite options

Choose how your custom hostname populates the SNI value with SNI rewrites:

* **Origin server name** (default): Set SNI to the custom origin  
   * If custom origin is `custom-origin.example.com`, then the SNI is `custom-origin.example.com`.
* **Host header**: Set SNI to the host header (or a host header override)  
   * If wildcards are not enabled and the hostname is `example.com`, then the SNI is `example.com`.  
   * If wildcards are enabled, the hostname is `example.com`, and a request comes to `www.example.com`, then the SNI is `www.example.com`.
* **Subdomain of zone**: Choose what to set as the SNI value (custom hostname or any subdomain)  
   * If wildcards are not enabled and a request comes to `example.com`, choose whether to set the SNI as `example.com` or `www.example.com`.  
   * If wildcards are enabled, you set the SNI to `example.com`, and a request comes to `www.example.com`, then the SNI is `example.com`.

Important

* Currently, SNI Rewrite is not supported for wildcard custom hostnames. Subdomains covered by a wildcard custom hostname send the custom origin server name as the SNI value.
* In the [O2O context](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/) (when requests are originating from a proxied hostname on a zone also on Cloudflare), changing the SNI value to use host header is currently not supported.
* SNI overrides defined in an [Origin Rule](https://developers.cloudflare.com/rules/origin-rules/) will take precedence over SNI rewrites.
* SNI Rewrite usage is subject to the [Service-Specific Terms ↗](https://www.cloudflare.com/service-specific-terms-application-services/#ssl-for-saas-terms).

### Set an SNI rewrite

To set an SNI rewrite in the dashboard, choose your preferred option from **Origin SNI value** when [creating a custom hostname](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/).

To set an SNI rewrite via the API, set the `custom_origin_sni` parameter when [creating a custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/):

* **Custom origin name** (default): Applies if you do not set the parameter
* **Host header**: Specify `":request_host_header:"`
* **Subdomain of zone**: Set to `"example.com"` or another subdomain of the custom hostname

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/","name":"Advanced Settings"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/","name":"Custom origin server"}}]}
```

---

---
title: Cloudflare for SaaS
description: Configure Cloudflare for SaaS with Regional Services and Customer Metadata Boundary.
image: https://developers.cloudflare.com/zt-preview.png
---

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

[Skip to content](#%5Ftop) 

# Cloudflare for SaaS

In the following sections, we will give you some details about how to configure Cloudflare for SaaS with Regional Services and Customer Metadata Boundary.

## Regional Services

To configure Regional Services for both hostnames [proxied](https://developers.cloudflare.com/dns/proxy-status/) through Cloudflare and the fallback origin, follow these steps for the dashboard or API configuration:

* [ Dashboard ](#tab-panel-5527)
* [ API ](#tab-panel-5528)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Follow these steps to [configure Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/).

1. Set the [fallback record](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/fallback%5Forigin/methods/update/).
2. Create a [Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/).
3. Run the [API POST](https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api) command on the Custom Hostname to create a `regional_hostnames` with a specific region.

The Regional Services functionality can be extended to Custom Hostnames and this is dependent on the target of the alias.

Consider the following example.

Note

As a SaaS provider, I might want all of my customers to connect to the nearest data center to them and for all the processing and Cloudflare features to be applied there; however, I might have a few exceptions where I want the processing to only be done in the US.

In this case, I can just keep my fallback record with `Earth` as the processing region and have all my Custom Hostnames create a CNAME record and use the fallback record as the CNAME target. For any Custom Hostnames that need to be processed in the US, I will create a DNS record for example, `us.saasprovider.com` and set the processing region to `United States of America`. In order for the US processing region to be applied, my customers must create a CNAME record and use the `us.saasprovider.com` as the CNAME target. The origin associated with the Custom Hostname is not used to set the processing region, but instead to route the traffic to the right server.

Below you can find a breakdown of the different ways that you might configure Cloudflare for SaaS and the corresponding processing regions:

* No processing region: `fallback.saasprovider.com`
* Processing region is the `US`: `us.saasprovider.com`
* User location: `UK` (closest datacenter: `LHR`)

| Test | Custom Hostname                        | Target                    | Origin                       | Location |
| ---- | -------------------------------------- | ------------------------- | ---------------------------- | -------- |
| 1    | ​​regionalservices-default.example.com | fallback.saasprovider.com | default (fallback)           | LHR      |
| 2    | regionalservices-default2.example.com  | us.saasprovider.com       | default (fallback)           | EWR      |
| 3    | regionalservices-custom.example.com    | fallback.saasprovider.com | us.saasprovider.com (custom) | LHR      |
| 4    | regionalservices-custom2.example.com   | us.saasprovider.com       | us.saasprovider.com (custom) | EWR      |

* In order to set a processing region for the fallback record to any of the available regions for Regional Services, create a new regional hostname entry for the fallback via a [POST](https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api) request.
* To update the existing region (for example, from `EU` to `US`), make a [PATCH](https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api) request for the fallback to update the processing region accordingly.
* To remove the regional services processing region and set it back to `Earth`, make a [DELETE](https://developers.cloudflare.com/data-localization/regional-services/get-started/#configure-regional-services-via-api) request to delete the region configuration.

## Customer Metadata Boundary

Cloudflare for SaaS [Analytics](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/hostname-analytics/) based on [HTTP requests](https://developers.cloudflare.com/logs/logpush/logpush-job/datasets/zone/http%5Frequests/) are fully supported by Customer Metadata Boundary.

Refer to [Cloudflare for SaaS documentation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/) for more information.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/data-localization/","name":"Data Localization Suite"}},{"@type":"ListItem","position":3,"item":{"@id":"/data-localization/how-to/","name":"Configuration guides"}},{"@type":"ListItem","position":4,"item":{"@id":"/data-localization/how-to/cloudflare-for-saas/","name":"Cloudflare for SaaS"}}]}
```

---

---
title: Workers as your fallback origin
description: Learn how to use a Worker as the fallback origin for your SaaS zone.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Workers as your fallback origin

If you are building your application on [Cloudflare Workers](https://developers.cloudflare.com/workers/), you can use a Worker as the origin for your SaaS zone (also known as your fallback origin).

## How custom hostname traffic reaches your Worker

When customers point their domains to your SaaS zone (for example, `mystore.customer.com` CNAMEs to `service.saasprovider.com`), their traffic enters your Cloudflare zone. Any Worker routes configured on your zone will match this incoming traffic.

For example, if you have:

* Your SaaS zone: `saasprovider.com`
* Your fallback origin: `service.saasprovider.com`
* Customer's custom hostname: `mystore.customer.com` (pointed to your zone via CNAME)
* Worker route: `*/*`

When a visitor requests `mystore.customer.com`, Cloudflare routes that request through your zone. The `*/*` route pattern matches all traffic entering your zone, including traffic from custom hostnames like `mystore.customer.com`.

Note

You do not need to add individual Worker routes for each custom hostname. The wildcard route pattern (`*/*`) automatically captures all traffic entering your zone, including traffic from customer vanity domains.

## Set up a Worker as your fallback origin

1. In your SaaS zone, [create and set a fallback origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin). Ensure the fallback origin only has an [originless DNS record](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#originless-setups):  
   * **Example**: `service.example.com AAAA 100::`
2. In that same zone, navigate to **Workers Routes**.
3. Click **Add route**.
4. Configure a route to send traffic to your Worker. Choose one of the following options based on your needs:  
   * **Route all traffic to the Worker** (recommended for most SaaS applications):  
         * **Route**: `*/*`  
         * **Worker**: Select the Worker used for your SaaS application.  
   This pattern routes all traffic entering your zone to the Worker, including requests from custom hostnames (for example, `mystore.customer.com`) and requests to your own subdomains (for example, `app.saasprovider.com`).  
   * **Route all but specific routes to worker**:  
         * **Route**: `*/*`  
         * **Worker**: Select the Worker used for your SaaS application.  
         * Add a second route for your zone's own hostnames with **Worker** set to **None** to exclude them.  
   For example, if your zone is `saasprovider.com` and you want `api.saasprovider.com` to bypass the Worker, create an additional route `api.saasprovider.com/*` with no Worker assigned. More specific routes take precedence over wildcard routes.  
   * **Route only custom hostname traffic to the Worker**:  
   * **Route**: `vanity.customer.com`  
   * **Worker**: Select the Worker used for your SaaS application.
5. Click **Save**.

---

Zone name restriction

Do not configure a custom hostname which matches the zone name. For example, if your SaaS zone is `example.com`, do not create a custom hostname named `example.com`.

## Related resources

* [Hostname routing](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/hostname-routing/) \- Learn about advanced routing patterns, including dispatch Workers and O2O behavior.
* [Workers routes](https://developers.cloudflare.com/workers/configuration/routing/routes/) \- Learn more about route pattern matching and validity rules.

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/","name":"Advanced Settings"}},{"@type":"ListItem","position":6,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/worker-as-origin/","name":"Workers as your fallback origin"}}]}
```

---

---
title: Common API Calls
description: API endpoints for managing custom hostnames and fallback origins.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

### Tags

[ REST API ](https://developers.cloudflare.com/search/?tags=REST%20API) 

# Common API Calls

As a SaaS provider, you may want to configure and manage Cloudflare for SaaS [via the API](https://developers.cloudflare.com/api/) rather than the [Cloudflare dashboard ↗](https://dash.cloudflare.com/). Below are relevant API calls for creating, editing, and deleting custom hostnames, as well as monitoring, updating, and deleting fallback origins. Further details can be found in the [Cloudflare API documentation](https://developers.cloudflare.com/api/).

---

## Custom hostnames

| Endpoint                                                                                                     | Notes                                                                                                                                 |
| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| [List custom hostnames](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/list/)    | Use the page parameter to pull additional pages. Add a hostname parameter to search for specific hostnames.                           |
| [Create custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) | In the validation\_records object of the response, use the txt\_name and txt\_record listed to validate the custom hostname.          |
| [Custom hostname details](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/get/)   |                                                                                                                                       |
| [Edit custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/edit/)     | When sent with an ssl object that matches the existing value, indicates that hostname should restart domain control validation (DCV). |
| [Delete custom hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/delete/) | Also deletes any associated SSL/TLS certificates.                                                                                     |

## Fallback origins

Our API includes the following endpoints related to the [fallback origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin) of a custom hostname:

* [Get fallback origin](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/fallback%5Forigin/methods/get/)
* [Update fallback origin](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/fallback%5Forigin/methods/update/)
* [Remove fallback origin](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/fallback%5Forigin/methods/delete/)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/common-api-calls/","name":"Common API Calls"}}]}
```

---

---
title: Enable
description: Enable Cloudflare for SaaS on your account to start creating custom hostnames.
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Enable

To enable Cloudflare for SaaS for your account:

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Select **Enable**.
3. The next step depends on the zone's plan:  
   * **Enterprise**: Eligible accounts 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. If you do not have access, contact your account team.  
   * **Non-enterprise**: Enter payment information.

Note

Different zone plan levels have access to different features. For more details, refer to [Plans](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/).

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/enable/","name":"Enable"}}]}
```

---

---
title: Configuring Cloudflare for SaaS
description: Get started with Cloudflare for SaaS
image: https://developers.cloudflare.com/dev-products-preview.png
---

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

[Skip to content](#%5Ftop) 

# Configuring Cloudflare for SaaS

---

## Before you begin

Before you start creating custom hostnames:

1. [Add](https://developers.cloudflare.com/fundamentals/manage-domains/add-site/) your zone to Cloudflare on a Free plan.
2. [Enable](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/enable/) Cloudflare for SaaS for your zone.
3. Review the [Hostname prioritization guidelines](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority). Wildcard custom hostnames behave differently than an exact hostname match.
4. (optional) Review the following documentation:
* [API documentation](https://developers.cloudflare.com/fundamentals/api/) (if you have not worked with the Cloudflare API before).
* [Certificate validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/).

---

## Initial setup

When you first [enable](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/enable/) Cloudflare for SaaS, you need to perform a few steps prior to creating any custom hostnames.

  
### 1\. Create fallback origin

The fallback origin is where Cloudflare will route traffic sent to your custom hostnames (must be proxied).

Note

To route custom hostnames to distinct origins, refer to [custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/).

To create your fallback origin:

1. [Create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a proxied `A`, `AAAA`, or `CNAME` record pointing to the IP address of your fallback origin (where Cloudflare will send custom hostname traffic).

| **Type** | **Name**       | **IPv4 address** | **Proxy status** |
| -------- | -------------- | ---------------- | ---------------- |
| A        | proxy-fallback | 192.0.2.1        | Proxied          |

1. Designate that record as your fallback origin.

* [ Dashboard ](#tab-panel-4543)
* [ API ](#tab-panel-4544)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. For **Fallback Origin**, enter the hostname for your fallback origin.
3. Select **Add Fallback Origin**.

Using the hostname of the record you just created, [update the fallback origin value](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/subresources/fallback%5Forigin/methods/update/).

1. Once you have added the fallback origin, confirm that its status is **Active**.

Note

When Cloudflare marks your fallback origin as **Active**, that only reflects that we are ready to send traffic to that DNS record.

You need to make sure your DNS record is sending traffic to the correct origin location.

### 2\. (Optional) Create CNAME target

The CNAME target — optional, but highly encouraged — provides a friendly and more flexible place for customers to [route their traffic](#3-have-customer-create-cname-record). You may want to use a subdomain such as `customers.<SAAS_PROVIDER>.com`.

[Create](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/#create-dns-records) a proxied CNAME that points your CNAME target to your fallback origin (can be a wildcard such as `*.customers.saasprovider.com`).

| **Type** | **Name**   | **Target**                      | **Proxy status** |
| -------- | ---------- | ------------------------------- | ---------------- |
| CNAME    | .customers | proxy-fallback.saasprovider.com | Proxied          |

---

## Per-hostname setup

You need to perform the following steps for each custom hostname.

### 1\. Plan for validation

Before you create a hostname, you need to plan for:

1. [Certificate validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/): Upon successful validation, the certificates are deployed to Cloudflare’s global network.
2. [Hostname validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/): Upon successful validation, Cloudflare proxies traffic for this hostname.

You must complete both these steps for the hostname to work as expected.

Note

Depending on which method you select for each of these options, additional steps might be required for you and your customers.

### 2\. Create custom hostname

After planning for certification and hostname validation, you can create the custom hostname.

Zone name restriction

Do not configure a custom hostname which matches the zone name. For example, if your SaaS zone is `example.com`, do not create a custom hostname named `example.com`.

To create a custom hostname:

* [ Dashboard ](#tab-panel-4545)
* [ API ](#tab-panel-4546)

1. In the Cloudflare dashboard, go to the **Custom Hostnames** page.  
[ Go to **Custom Hostnames** ](https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames)
2. Select **Add Custom Hostname**.
3. Add your customer's hostname `app.customer.com` and set the relevant options, including:  
   * The [minimum TLS version](https://developers.cloudflare.com/ssl/reference/protocols/).  
   * Defining whether you want to use a certificate provided by Cloudflare or [upload a custom certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/).  
   * Selecting the [certificate authority (CA)](https://developers.cloudflare.com/ssl/reference/certificate-authorities/) that will issue the certificate.  
   * Choosing the [validation method](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/).  
   * Whether you want to **Enable wildcard**, which adds a `*.<custom-hostname>` SAN to the custom hostname certificate. For more details, refer to [Hostname priority](https://developers.cloudflare.com/ssl/reference/certificate-and-hostname-priority/#hostname-priority).  
   * Choosing a value for [Custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/).
4. Select **Add Custom Hostname**.

Default behavior

When you create a custom hostname:

* If you issue a custom hostname certificate with wildcards enabled, you cannot customize TLS settings for these wildcard hostnames.
* If you do not specify the **Minimum TLS Version**, it defaults to the zone's Minimum TLS Version. You can still [edit this setting](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version) after creation.

1. To create a custom hostname using the API, use the [Create Custom Hostname](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/create/) endpoint.  
   * You can leave the `certificate_authority` parameter empty to set it to "default CA". With this option, Cloudflare checks the CAA records before requesting the certificates, which helps ensure the certificates can be issued from the CA.
2. For the newly created custom hostname, the `POST` response may not return the DCV validation token `validation_records`. It is recommended to make a second [GET command](https://developers.cloudflare.com/api/resources/custom%5Fhostnames/methods/list/) (with a delay) to retrieve these details.

The response contains the complete definition of the new custom hostname.

Default behavior

When you create a custom hostname:

* If you issue a custom hostname certificate with wildcards enabled, you cannot customize TLS settings for these wildcard hostnames.
* If you do not specify the **Minimum TLS Version**, it defaults to the zone's Minimum TLS Version. You can still [edit this setting](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/enforce-mtls/#minimum-tls-version) after creation.

Note

For each custom hostname, Cloudflare issues two certificates bundled in chains that maximize browser compatibility (unless you [upload custom certificates](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/custom-certificates/uploading-certificates/)).

The primary certificate uses a `P-256` key, is `SHA-2/ECDSA` signed, and will be presented to browsers that support elliptic curve cryptography (ECC). The secondary or fallback certificate uses an `RSA 2048-bit` key, is `SHA-2/RSA` signed, and will be presented to browsers that do not support ECC.

### 3\. Have customer create CNAME record

To finish the custom hostname setup, your customer needs to set up a CNAME record at their authoritative DNS that points to your [CNAME target](#2-optional-create-cname-target) [1](#user-content-fn-1).

Warning

Before your customer does this step, confirm that the hostname's **Certificate status** and **Hostname status** are both **Active**.

If not, confirm that you are using a method of [certificate](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/#http-automatic) or [hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/realtime-validation/) validation that occurs after your customer adds their DNS record.

Your customer's CNAME record might look like the following:

```

mystore.example.com CNAME customers.saasprovider.com


```

This record would route traffic in the following way:

flowchart TD
accTitle: How traffic routing works with a CNAME target
A[Request to <code>mystore.example.com</code>] --> B[<code>customers.saasprovider.com</code>]
B --> C[<code>proxy-fallback.saasprovider.com</code>]

  
Requests to `mystore.example.com` would go to your CNAME target (`customers.saasprovider.com`), which would then route to your fallback origin (`proxy-fallback.saasprovider.com`).

Warning

If your customer needs to use an A record to point to the SaaS target, you will need to get [apex proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/). By default, using an A record to point to the target is not a supported setup.

#### Service continuation

If your customer is also using Cloudflare for their domain, they should keep their DNS record pointing to your SaaS provider in place for as long as they want to use your service.

For more details, refer to [Remove custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/remove-custom-hostnames/).

## Footnotes

1. If you have [regional services](https://developers.cloudflare.com/data-localization/regional-services/) set up for your custom hostnames, Cloudflare always uses the processing region associated with your DNS target record (instead of the processing region of any [custom origins](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/)).  
[↩](#user-content-fnref-1)

```json
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/cloudflare-for-platforms/","name":"Cloudflare for Platforms"}},{"@type":"ListItem","position":3,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/","name":"Cloudflare for SaaS"}},{"@type":"ListItem","position":4,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/","name":"Get started"}},{"@type":"ListItem","position":5,"item":{"@id":"/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/","name":"Configuring Cloudflare for SaaS"}}]}
```
