Custom domains let you send AI Gateway requests through a hostname that you own, such as ai.example.com, instead of the default gateway.ai.cloudflare.com endpoint.
The hostname identifies your account and gateway, so you can omit the account ID and gateway ID from request URLs. Requests go directly to AI Gateway provider-native routes and OpenAI-compatible compat routes.
Custom domains are also the foundation for identity-aware controls with Cloudflare Access, which let users authenticate with your identity provider before they can call your gateway.
For example, if your custom domain is ai.example.com, an OpenAI provider request uses:
https://ai.example.com/openai/v1/chat/completionsInstead of:
https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/openai/v1/chat/completionsThe same applies to the OpenAI-compatible endpoint. For example, https://ai.example.com/compat/chat/completions routes through the same gateway using the compat route.
To add a custom domain:
- In the Cloudflare dashboard ↗, go to AI > AI Gateway.
- Select the gateway you want to configure.
- Go to the Domains tab.
- Select Add Domain and enter the hostname you want to use. Optionally, choose a subdomain.
- AI Gateway automatically creates the DNS record in the dashboard.
After the domain is set up, you can send requests to it. To require users to authenticate before they can call the gateway, set up Cloudflare Access on the domain.
You can also create and manage custom domains through the Cloudflare API.
Unlike the dashboard, the API does not create the DNS record for you. After you create the custom domain, use the returned cname_target to create a proxied CNAME record for your hostname.
curl "https://api.cloudflare.com/client/v4/accounts/%7Baccount_id%7D/ai-gateway/gateways/%7Bgateway_id%7D/custom-domains" \
--request POST \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--json '{
"domain": "ai.example.com",
"zone_id": "395566f4c8a5b9d2a5fc0d457b007c44"
}'The response includes the custom domain status and the CNAME target:
{
"success": true,
"result": {
"hostname": "ai.example.com",
"gateway_id": "my-gateway",
"status": "pending_dcv",
"cname_target": "<cname-target>",
"created_at": 1782925200000,
"modified_at": 1782925200000
}
}Create a proxied CNAME record in the zone that owns your custom domain. Set content to the cname_target returned when you created the custom domain.
curl "https://api.cloudflare.com/client/v4/zones/%7Bzone_id%7D/dns_records" \
--request POST \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--json '{
"type": "CNAME",
"name": "ai",
"content": "<cname-target>",
"proxied": true
}'The custom domain remains in pending_dcv until domain control validation completes.
curl "https://api.cloudflare.com/client/v4/accounts/%7Baccount_id%7D/ai-gateway/gateways/%7Bgateway_id%7D/custom-domains" \
--request GET \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"curl "https://api.cloudflare.com/client/v4/accounts/%7Baccount_id%7D/ai-gateway/gateways/%7Bgateway_id%7D/custom-domains/%7Bhostname%7D" \
--request GET \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"curl "https://api.cloudflare.com/client/v4/accounts/%7Baccount_id%7D/ai-gateway/gateways/%7Bgateway_id%7D/custom-domains/%7Bhostname%7D" \
--request DELETE \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"Send requests to the custom domain without the account ID or gateway ID in the path:
curl -X POST "https://ai.example.com/openai/v1/chat/completions" \
--header "Content-Type: application/json" \
--data '{
"model": "gpt-4.1-mini",
"messages": [
{
"role": "user",
"content": "What is Cloudflare?"
}
]
}'If the domain is protected by Cloudflare Access, the request must also include a valid Access token. For details, refer to Cloudflare Access.
Custom domains are not yet supported on the newer AI Gateway endpoints served through the Cloudflare REST API (api.cloudflare.com).