A custom domain serves your public endpoint from a hostname that you own, such as search.example.com, instead of the default <PUBLIC_ENDPOINT_ID>.search.ai.cloudflare.com hostname.
The endpoints and request formats do not change. Only the hostname changes:
https://search.example.com/search
https://search.example.com/chat/completions
https://search.example.com/mcpCustom domains are also the foundation for restricting access with Cloudflare Access, which lets users authenticate with your identity provider before they can query your indexed content.
- The public endpoint must already be enabled on the instance or namespace. Adding a custom domain to an instance without an active public endpoint returns error
7093. - The hostname must belong to a zone that is added to the same Cloudflare account and in an active state. A hostname on another account returns error
7090. - Each instance or namespace supports one custom domain.
- A hostname can only be attached to one public endpoint at a time. Reusing a hostname returns error
7091. - The hostname must be a fully qualified domain name of up to 253 characters, such as
search.example.com. Wildcards are not supported. Hostnames are stored in lowercase.
Set public_endpoint_params.custom_domains when you create or update an instance.
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai-search/namespaces/default/instances/<INSTANCE_ID>" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"public_endpoint_params": {
"enabled": true,
"custom_domains": ["search.example.com"]
}
}'The same field is available on namespaces. Refer to Namespace public endpoints.
Cloudflare issues a certificate for the hostname and begins domain control validation.
Create a proxied CNAME record in the zone that owns your custom domain. The target is the default hostname of the public endpoint, which is <PUBLIC_ENDPOINT_ID>.search.ai.cloudflare.com.
| Type | Name | Target | Proxy status |
|---|---|---|---|
CNAME |
search |
<PUBLIC_ENDPOINT_ID>.search.ai.cloudflare.com |
Proxied |
curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/dns_records" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"type": "CNAME",
"name": "search",
"content": "<PUBLIC_ENDPOINT_ID>.search.ai.cloudflare.com",
"proxied": true
}'The custom domain starts serving traffic once domain control validation completes.
By default, a public endpoint answers on both the custom domain and the default <PUBLIC_ENDPOINT_ID>.search.ai.cloudflare.com hostname. Set default_domain_enabled to false to serve the custom domain only. The default hostname then returns a 404 with error 60018.
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai-search/namespaces/default/instances/<INSTANCE_ID>" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"public_endpoint_params": {
"enabled": true,
"custom_domains": ["search.example.com"],
"default_domain_enabled": false
}
}'Turn this off whenever you put security controls in front of the custom domain. Those controls run in your own zone, so any traffic that reaches the default hostname skips them. Refer to Cloudflare Access.
Three rules apply:
- You cannot turn off the default hostname without at least one custom domain. The request returns error
7096. - Because
public_endpoint_paramsis replaced in full, omittingdefault_domain_enabledon a later update resets it totrueand makes the default hostname reachable again. - Leave the
CNAMErecord pointing at the default hostname. AI Search routes on the hostname the client requested, not theCNAMEtarget, so the record keeps working after you turn the default hostname off.
Send custom_domains as an empty array. Cloudflare removes the certificate and stops routing the hostname.
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/ai-search/namespaces/default/instances/<INSTANCE_ID>" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"public_endpoint_params": {
"enabled": true,
"custom_domains": []
}
}'If default_domain_enabled is false, removing the last custom domain in the same request returns error 7096. Re-enable the default hostname first, then remove the domain.
Deleting the instance or namespace removes its custom domains and certificates.
| Code | Message | Cause |
|---|---|---|
7090 |
custom_domain_not_a_verified_zone_on_this_account |
The hostname does not belong to an active zone on this account. |
7091 |
custom_domain_already_in_use |
The hostname is already attached to another public endpoint. |
7092 |
custom_domain_provisioning_failed |
Certificate provisioning failed. Retry the request. |
7093 |
custom_domains_require_an_active_public_endpoint |
The instance or namespace has no active public endpoint. |
7096 |
disabling_the_default_domain_requires_at_least_one_custom_domain |
default_domain_enabled was set to false with no custom domain. |
60018 |
default domain disabled |
A request reached the default hostname while it is turned off. |