---
title: "Safety identifiers"
subtitle: "Tag each request with your end user's ID for analytics, budgets, and abuse tracking."
---

When many of your users share one API key, the gateway and the provider can't tell them apart unless you say who sent each request. Two fields do that. `customer_identifier` is read by Respan: it attributes the request to a user so you can see their usage and cap their spend. `safety_identifier` is OpenAI's own request field, meant for the provider: it lets the provider track abuse per end user instead of flagging your whole account.

<Tabs>
<Tab title="cURL">
```bash
curl https://gateway.respan.ai/v1/chat/completions \
  -H "Authorization: Bearer $RESPAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "messages": [{"role": "user", "content": "Hello!"}],
    "customer_identifier": "user_8f3a",
    "safety_identifier": "user_8f3a"
  }'
```
</Tab>
<Tab title="Python">
```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://gateway.respan.ai/v1",
    api_key=os.environ["RESPAN_API_KEY"],
)

response = client.chat.completions.create(
    model="gpt-5.5",
    messages=[{"role": "user", "content": "Hello!"}],
    safety_identifier="user_8f3a",
    extra_body={"customer_identifier": "user_8f3a"},
)
```
</Tab>
<Tab title="TypeScript">
```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://gateway.respan.ai/v1",
  apiKey: process.env.RESPAN_API_KEY,
});

const response = await client.chat.completions.create({
  model: "gpt-5.5",
  messages: [{ role: "user", content: "Hello!" }],
  safety_identifier: "user_8f3a",
  // @ts-expect-error Respan parameter
  customer_identifier: "user_8f3a",
});
```
</Tab>
</Tabs>

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| [`customer_identifier`](#customer-identifier) | string | none | Your end user's ID. Read by Respan and removed before the request is sent to the provider. |
| [`customer_params`](#customer-identifier) | object | none | `customer_identifier` plus `name`, `email`, and `rate_limit` (requests per minute) for that user. |
| [`safety_identifier`](#safety-identifier) | string | none | OpenAI's end-user ID field, sent to the provider with the request. Not a Respan parameter. |

Use a stable ID that doesn't reveal who the user is, such as a hashed user ID, not an email address. The same value can go in both fields.

## customer_identifier

`customer_identifier` stays in Respan. With it you can:

- See each user's requests, tokens, and cost in **Observability** › **Users & identifiers**.
- Filter logs and usage reports by user.
- Cap a user's spend with a budget, or their requests per minute with `customer_params.rate_limit`. See [Budgets and limits](/docs/ai-gateway/spend/budgets-and-limits).

For realtime sessions, send it in the `X-Data-Respan-Params` header. See [Customers](/docs/ai-gateway/customers/customers).

## safety_identifier

`safety_identifier` is a field of OpenAI's request, not a Respan parameter. The gateway doesn't read it: it travels with the rest of your request body to the provider, like any other OpenAI field. If one of your users sends abusive content, a provider that reads it can act on that user instead of your whole account.

To find a user's requests in Respan, for example after a provider flags them, use `customer_identifier`, which Respan stores on every log.

{/* REVIEW: confirm the OSS gateway's request translation forwards safety_identifier to OpenAI (and what happens to it when the request is translated for another provider). */}

## Next steps

- [Customers](/docs/ai-gateway/customers/customers)
- [Budgets and limits](/docs/ai-gateway/spend/budgets-and-limits)
- [Data retention and ZDR](/docs/ai-gateway/security/zero-data-retention)
