Custom metadata in AI Gateway allows you to tag requests with user IDs or other identifiers, enabling better tracking and analysis of your requests. Metadata values can be strings, numbers, or booleans, and will appear in your logs, making it easy to search and filter through your data.
- Custom Tagging: Add user IDs, team names, test indicators, and other relevant information to your requests.
- Enhanced Logging: Metadata appears in your logs, allowing for detailed inspection and troubleshooting.
- Search and Filter: Use metadata to efficiently search and filter through logged requests.
- String
- Number
- Boolean
Metadata keys that begin with cf. are reserved for metadata added by Cloudflare. Do not send your own cf.* metadata keys. AI Gateway removes customer-supplied cf.* keys before saving request metadata.
When a request reaches AI Gateway through a custom domain protected by Cloudflare Access, AI Gateway adds the authenticated Access user ID to request metadata as cf.user_id. This value is the verified Access JWT sub claim, not the user's email address.
AI Gateway guarantees that cf.user_id is saved when a valid Access user ID is present. If the request already has five custom metadata entries, AI Gateway may remove the last custom entry so cf.user_id can be saved. Service-token requests and requests without a user subject do not receive cf.user_id metadata.
To include custom metadata in your request using cURL:
# Run `wrangler whoami` to get your account ID to replace $CLOUDFLARE_ACCOUNT_ID,
# and `wrangler auth token` to get an auth token to replace $CLOUDFLARE_API_TOKEN.
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/ai/v1/chat/completions" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--header 'cf-aig-metadata: {"team": "AI", "user": 12345, "test":true}' \
--data '{"model": "openai/gpt-4.1", "messages": [{"role": "user", "content": "What should I eat for lunch?"}]}'To include custom metadata in your request using the OpenAI SDK:
import OpenAI from "openai";
export default {
async fetch(request, env, ctx) {
const openai = new OpenAI({
apiKey: env.CLOUDFLARE_API_TOKEN,
baseURL: `https://api.cloudflare.com/client/v4/accounts/${env.CLOUDFLARE_ACCOUNT_ID}/ai/v1`,
});
try {
const chatCompletion = await openai.chat.completions.create(
{
model: "openai/gpt-4.1",
messages: [{ role: "user", content: "What should I eat for lunch?" }],
max_tokens: 50,
},
{
headers: {
"cf-aig-metadata": JSON.stringify({
user: "JaneDoe",
team: 12345,
test: true,
}),
},
},
);
const response = chatCompletion.choices[0].message;
return new Response(JSON.stringify(response));
} catch (e) {
console.log(e);
return new Response(e);
}
},
};import OpenAI from "openai";
export default {
async fetch(request, env, ctx) {
const openai = new OpenAI({
apiKey: env.CLOUDFLARE_API_TOKEN,
baseURL: `https://api.cloudflare.com/client/v4/accounts/${env.CLOUDFLARE_ACCOUNT_ID}/ai/v1`,
});
try {
const chatCompletion = await openai.chat.completions.create(
{
model: "openai/gpt-4.1",
messages: [{ role: "user", content: "What should I eat for lunch?" }],
max_tokens: 50,
},
{
headers: {
"cf-aig-metadata": JSON.stringify({
user: "JaneDoe",
team: 12345,
test: true,
}),
},
},
);
const response = chatCompletion.choices[0].message;
return new Response(JSON.stringify(response));
} catch (e) {
console.log(e);
return new Response(e);
}
},
};To include custom metadata in your request using Bindings:
export default {
async fetch(request, env, ctx) {
const aiResp = await env.AI.run(
"@cf/mistral/mistral-7b-instruct-v0.1",
{ prompt: "What should I eat for lunch?" },
{
gateway: {
id: "gateway_id",
metadata: { team: "AI", user: 12345, test: true },
},
},
);
return new Response(aiResp);
},
};