Skip to content
Docs

AI Gateway Safety Identifiers

A safety identifier tells providers like OpenAI, Anthropic, and Meta which of your end users a request belongs to, without sending anything that identifies that person. It gives providers a way to detect abuse at the level of a single user, so when one is flagged for a policy violation, the action targets that identifier instead of all of your team's traffic.

Set safetyIdentifier in providerOptions.gateway to a unique, opaque ID for the end user on whose behalf the request is made, such as a UUID or a hash of your internal user ID. Hash a username or email address rather than sending it, and do not include personal information of any kind. For users who are not signed in, send a session ID instead. The value can be at most 64 characters.

The Messages and Responses examples use providerOptions.gateway, which isn't part of the upstream SDK types. Their TypeScript examples spread these extension fields into the request, and their Python examples use extra_body. Chat Completions accepts the typed safety_identifier field directly.

These examples use AI SDK 7 and the AI SDK for Python beta. Set AI_GATEWAY_API_KEY before running them. See API format differences for setup, request fields, and response handling.

safety-identifier.ts
import { generateText } from 'ai';
 
const { text } = await generateText({
  model: 'openai/gpt-6-astra',
  prompt: 'Explain quantum computing in two sentences.',
  providerOptions: {
    gateway: {
      safetyIdentifier: 'user_9f8e7d6c5b',
    },
  },
});
 
console.log(text);
safety-identifier_ai.py
import asyncio
import ai
 
async def main():
    model = ai.get_model("openai/gpt-6-astra")
    messages = [ai.user_message("Explain quantum computing in two sentences.")]
    params = ai.InferenceRequestParams(
        extra_body={"providerOptions": {"gateway": {"safetyIdentifier": "user_9f8e7d6c5b"}}}
    )
    async with ai.stream(model, messages, params=params) as stream:
        async for event in stream:
            if isinstance(event, ai.events.TextDelta):
                print(event.chunk, end="", flush=True)
    print()
 
asyncio.run(main())

Set safety_identifier at the top level of the Chat Completions request body. AI Gateway maps this field to providerOptions.gateway.safetyIdentifier, so it works across the supported providers. The value must be a non-empty string. AI Gateway truncates values longer than 64 characters.

safety-identifier-chat.ts
import OpenAI from 'openai';
 
const client = new OpenAI({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/v1',
});
 
const response = await client.chat.completions.create({
  model: 'openai/gpt-6-astra',
  messages: [
    {
      role: 'user',
      content: 'Explain quantum computing in two sentences.',
    },
  ],
  safety_identifier: 'user_9f8e7d6c5b',
});
 
console.log(response.choices[0]?.message.content);
safety-identifier_chat.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh/v1",
)
 
response = client.chat.completions.create(
    model="openai/gpt-6-astra",
    messages=[{"role": "user", "content": "Explain quantum computing in two sentences."}],
    safety_identifier="user_9f8e7d6c5b",
)
 
print(response.choices[0].message.content)
safety-identifier-chat.sh
curl --fail-with-body https://ai-gateway.vercel.sh/v1/chat/completions \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "openai/gpt-6-astra",
  "messages": [
    {
      "role": "user",
      "content": "Explain quantum computing in two sentences."
    }
  ],
  "safety_identifier": "user_9f8e7d6c5b"
}'
safety-identifier-messages.ts
import Anthropic from '@anthropic-ai/sdk';
 
const client = new Anthropic({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh',
});
 
const response = await client.messages.create({
  model: 'openai/gpt-6-astra',
  messages: [
    {
      role: 'user',
      content: 'Explain quantum computing in two sentences.',
    },
  ],
  max_tokens: 1024,
  ...{
    providerOptions: {
      gateway: {
        safetyIdentifier: 'user_9f8e7d6c5b',
      },
    },
  },
});
 
for (const block of response.content) {
  if (block.type === 'text') console.log(block.text);
}
safety-identifier_messages.py
import os
from anthropic import Anthropic
 
client = Anthropic(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh",
)
 
response = client.messages.create(
    model="openai/gpt-6-astra",
    messages=[{"role": "user", "content": "Explain quantum computing in two sentences."}],
    max_tokens=1024,
    extra_body={"providerOptions": {"gateway": {"safetyIdentifier": "user_9f8e7d6c5b"}}},
)
 
for block in response.content:
    if block.type == "text":
        print(block.text)
safety-identifier-messages.sh
curl --fail-with-body https://ai-gateway.vercel.sh/v1/messages \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
  "model": "openai/gpt-6-astra",
  "messages": [
    {
      "role": "user",
      "content": "Explain quantum computing in two sentences."
    }
  ],
  "max_tokens": 1024,
  "providerOptions": {
    "gateway": {
      "safetyIdentifier": "user_9f8e7d6c5b"
    }
  }
}'
safety-identifier-responses.ts
import OpenAI from 'openai';
 
const client = new OpenAI({
  apiKey: process.env.AI_GATEWAY_API_KEY,
  baseURL: 'https://ai-gateway.vercel.sh/v1',
});
 
const response = await client.responses.create({
  model: 'openai/gpt-6-astra',
  input: 'Explain quantum computing in two sentences.',
  ...{
    providerOptions: {
      gateway: {
        safetyIdentifier: 'user_9f8e7d6c5b',
      },
    },
  },
});
 
console.log(response.output_text);
safety-identifier_responses.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.environ["AI_GATEWAY_API_KEY"],
    base_url="https://ai-gateway.vercel.sh/v1",
)
 
response = client.responses.create(
    model="openai/gpt-6-astra",
    input="Explain quantum computing in two sentences.",
    extra_body={"providerOptions": {"gateway": {"safetyIdentifier": "user_9f8e7d6c5b"}}},
)
 
print(response.output_text)
safety-identifier-responses.sh
curl --fail-with-body https://ai-gateway.vercel.sh/v1/responses \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "openai/gpt-6-astra",
  "input": "Explain quantum computing in two sentences.",
  "providerOptions": {
    "gateway": {
      "safetyIdentifier": "user_9f8e7d6c5b"
    }
  }
}'
safety-identifier.ts
import OpenAI from 'openai';
 
const apiKey = process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN;
 
const openai = new OpenAI({
  apiKey,
  baseURL: 'https://ai-gateway.vercel.sh/v1',
});
 
const response = await openai.embeddings.create({
  model: 'openai/text-embedding-3-small',
  input: 'Sunny day at the beach',
 
  ...{
    providerOptions: {
      gateway: {
        safetyIdentifier: 'user_9f8e7d6c5b',
      },
    },
  },
});
safety-identifier.py
import os
from openai import OpenAI
 
client = OpenAI(
    api_key=os.getenv("AI_GATEWAY_API_KEY"),
    base_url="https://ai-gateway.vercel.sh/v1",
)
 
response = client.embeddings.create(
    model="openai/text-embedding-3-small",
    input="Sunny day at the beach",
    extra_body={
        "providerOptions": {
            "gateway": {"safetyIdentifier": "user_9f8e7d6c5b"}
        }
    },
)
safety-identifier.sh
curl -X POST "https://ai-gateway.vercel.sh/v1/embeddings" \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/text-embedding-3-small",
    "input": "Sunny day at the beach",
    "providerOptions": {
      "gateway": {
        "safetyIdentifier": "user_9f8e7d6c5b"
      }
    }
  }'

AI Gateway forwards the identifier to whichever provider serves the request, using that provider's field:

  • OpenAI models, including when served by Azure or Bedrock, receive it as OpenAI's safety_identifier
  • Models served by Meta receive it as safety_identifier
  • Anthropic models, including when served by Vertex or Claude Platform on AWS, receive it as Anthropic's metadata.user_id

The identifier follows the request across provider and model fallbacks, so the same value reaches whichever provider ultimately serves the request.

The providerOptions.gateway.safetyIdentifier option applies when you have not set a provider-specific identifier. If you set providerOptions.openai.safetyIdentifier or providerOptions.anthropic.metadata.userId directly, those values win for requests they apply to.

On the Chat Completions API, providerOptions.gateway.safetyIdentifier takes precedence over the top-level safety_identifier field. Both take precedence over the legacy user field, which also maps to a safety identifier for backwards compatibility.

Last updated September 8, 2026

Was this helpful?

supported.