Cloudflare AI Gateway
Cloudflare AI Gateway can proxy https://api.aiand.com as a custom provider. You get Gateway logs, analytics, cache, and rate limits; ai& still bills the sk- key.
ai& is not a native Gateway provider. The URL uses custom-{slug}, not /openai or /aiand.
Create an API key first.
-
In the Cloudflare dashboard, open AI → AI Gateway → Custom Providers and add a provider:
- Slug:
aiand - Base URL:
https://api.aiand.com(no trailing slash, no/v1) - Enable it
- Slug:
-
Create a gateway (any name; examples below use
aiand-gateway). -
Send the ai& key as
Authorization: Bearer sk-…. Authenticated Gateway is optional on this path. If it is on, also sendcf-aig-authorizationwith a Cloudflare token that has AI Gateway Run. -
Or store the key under Provider Keys (BYOK) and omit
Authorization. BYOK needs Authenticated Gateway on, and every request must sendcf-aig-authorization. That Cloudflare token is not thesk-key.
The custom-provider form has no key field. That is expected.
Call through the gateway
Section titled “Call through the gateway”Replace ACCOUNT_ID with your Cloudflare account id.
curl https://gateway.ai.cloudflare.com/v1/ACCOUNT_ID/aiand-gateway/custom-aiand/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $AIAND_API_KEY" \ -H "cf-aig-authorization: Bearer $CF_AIG_TOKEN" \ -d '{ "model": "openai/gpt-oss-120b", "messages": [{"role": "user", "content": "Hello"}] }'The examples include both headers. Drop cf-aig-authorization only when you send the sk- yourself and Authenticated Gateway is off. Drop Authorization only for BYOK, and keep cf-aig-authorization in that case.
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.AIAND_API_KEY, baseURL: "https://gateway.ai.cloudflare.com/v1/ACCOUNT_ID/aiand-gateway/custom-aiand/v1", defaultHeaders: { "cf-aig-authorization": `Bearer ${process.env.CF_AIG_TOKEN}`, },});
const response = await client.chat.completions.create({ model: "openai/gpt-oss-120b", messages: [{ role: "user", content: "Hello" }],});The SDK appends /chat/completions. The gateway then calls https://api.aiand.com/v1/chat/completions. The same baseURL works for /v1/responses, /v1/messages, /v1/models, and /v1/completions.
Unified /compat (optional)
Section titled “Unified /compat (optional)”curl https://gateway.ai.cloudflare.com/v1/ACCOUNT_ID/aiand-gateway/compat/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $AIAND_API_KEY" \ -H "cf-aig-authorization: Bearer $CF_AIG_TOKEN" \ -d '{ "model": "custom-aiand/openai/gpt-oss-120b", "messages": [{"role": "user", "content": "Hello"}] }'/compat is chat completions only. Prefer the provider-specific /custom-aiand/v1 path for Responses, Messages, and the catalog.
Caching
Section titled “Caching”Turn on Cache Responses in the gateway settings. Identical requests return cf-aig-cache-status: HIT and do not reach ai& (and are not billed). A cache miss is MISS.
The default cache key is an exact match of provider, path, model, auth, and the full JSON body. Bypass with cf-aig-skip-cache: true.
Streaming is not cached by default. Cache Responses covers identical non-streaming text and image requests only. A stream: true call still reaches ai& and is billed.
Errors
Section titled “Errors”- Missing or bad
cf-aig-authorization(when auth is on): Cloudflare401(AiGatewayError), not an OpenAI error body. - Wrong custom slug: Cloudflare
502(The provider did not return a valid response), not ai&’s404. - Unknown model, bad JSON, empty
messages, invalidreasoning_effort, vision on a text-only model: ai&’s usual OpenAI-shaped errors, passed through.
What this is not
Section titled “What this is not”Calling env.AI.run("@cf/…") is Workers AI, a different product. A Worker can call ai& with the OpenAI SDK and baseURL: "https://api.aiand.com/v1" without AI Gateway at all.