> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anyfast.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# x-safety-id

> Identify your application's end users with a stable Safety ID and handle anti-distillation restrictions.

Applications calling AnyFast from a backend can send `x-safety-id` to identify their end users. Where anti-distillation controls are enabled, the platform can count refusals and temporarily restrict an individual end user, reducing the impact on others.

Your AnyFast account is the **platform account**; users of your application are **end users**. Generate and maintain Safety IDs in your backend. No preregistration or separate sub-user ID is required. API key authentication remains unchanged.

<Info>
  Confirm that your model and route support and enable this capability. Adding the header does not enable controls automatically or imply support across all models, protocols, or endpoints.
</Info>

## Quick integration

1. Generate a stable, unique Safety ID per end user and retain its mapping to your internal user ID.
2. Send one `x-safety-id` header on every relevant backend request, including streaming requests and retries.
3. Log the ID and handle HTTP status, error identifiers, and `Retry-After`.

```http theme={null}
x-safety-id: 641218f96a549a57c1a3f997cda033a1ff43b28fa494b6cdd01dba105eb08d50
```

Cover every relevant request entry point. Missing or empty IDs use the platform-account scope; restrictions at that scope can affect other end users of the account.

## Header definition

| Property | Contract |
| - | - |
| Name | `x-safety-id`; header names are case-insensitive. |
| Type | String. |
| Length | 1–64 ASCII characters after trimming leading and trailing whitespace, for nonempty values. |
| Characters | Letters, digits, `.`, `_`, `:`, `@`, `-`. |
| Validation | `^[A-Za-z0-9._:@-]{1,64}$`. |
| Case | Values are case-sensitive: `Customer-A` differs from `customer-a`. |
| Stability | Use the same ID for the same end user and different IDs for different end users. |
| Missing or empty | Missing, empty, and whitespace-only values use the platform-account scope. |
| Multiple values | Only one value is allowed; duplicate headers and comma-separated values are rejected. |
| Invalid values | HTTP `400`; the request is not sent upstream and does not fall back to account scope. |

Send normalized values without surrounding whitespace. Chinese characters, internal spaces, `/`, `+`, `=`, and `,` are not allowed. This header is used for platform anti-distillation identification and is not forwarded to upstream model providers.

## Generate and maintain IDs

You do not need to disclose real user IDs, usernames, emails, or tenant identifiers. Use a private backend key with HMAC-SHA256 to produce a stable pseudonymous ID. Keep the key, original identity, and mapping in your own systems.

The hexadecimal HMAC-SHA256 output is 64 characters. Generate a dedicated secure random 32-byte key and store it in backend secret management. Fix the identity input format and UTF-8 encoding. Do not regenerate the key per request or expose it in a browser or app.

This Python example uses the standard library. The key and identity are demonstration values; replace both for production.

```python theme={null}
import hashlib
import hmac

# Example only; load a dedicated random key from backend secret management.
secret_key = b"example-only-do-not-use-in-production"
identity = "tenant-a:user-10001"
safety_id = hmac.new(secret_key, identity.encode("utf-8"), hashlib.sha256).hexdigest()
print(safety_id)
```

```text theme={null}
641218f96a549a57c1a3f997cda033a1ff43b28fa494b6cdd01dba105eb08d50
```

If user IDs are unique only within a tenant, include tenant identity in an unambiguous input format. Tenant identity need not be sent in plain text. IDs need not be globally unique across platform accounts.

Derive or retrieve the ID from the authenticated user in your backend and overwrite client-supplied headers. Safety IDs are not authentication credentials; retain API keys in the backend.

Keep IDs unchanged across sessions, devices, API keys, and retries. Do not use random values, timestamps, or request IDs. When rotating the key or changing the generation rule, continue using stored IDs for existing users; recomputing them would identify those users as new end users.

Maintain an internal lookup from Safety ID to user. The platform reports the received ID and cannot reverse its hash input. Treat hash values as user-associated data.

## Request examples

These Bash examples use the international API host. Replace `YOUR_API_KEY`, `YOUR_ENABLED_MODEL`, and the example Safety ID with values for the current end user and a supported, enabled model.

### Claude Messages

```bash theme={null}
curl --include 'https://www.anyfast.ai/v1/messages' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header 'anthropic-version: 2023-06-01' \
  --header 'x-safety-id: 641218f96a549a57c1a3f997cda033a1ff43b28fa494b6cdd01dba105eb08d50' \
  --data '{
    "model": "YOUR_ENABLED_MODEL",
    "max_tokens": 128,
    "stream": false,
    "messages": [{"role": "user", "content": "Describe how you can help in one sentence."}]
  }'
```

### OpenAI Chat Completions compatible format

For supported models with anti-distillation detection enabled, use the same header:

```bash theme={null}
curl --include 'https://www.anyfast.ai/v1/chat/completions' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --header 'x-safety-id: 641218f96a549a57c1a3f997cda033a1ff43b28fa494b6cdd01dba105eb08d50' \
  --data '{
    "model": "YOUR_ENABLED_MODEL",
    "max_tokens": 128,
    "stream": false,
    "messages": [{"role": "user", "content": "Describe how you can help in one sentence."}]
  }'
```

For streaming, set `stream` to `true` and keep the header unchanged. Check HTTP status and Content-Type before parsing SSE: a blocked request can return error JSON before streaming begins.

With an SDK, use its custom-header option for each call. When a shared client serves multiple end users, do not fix one user's ID on the client or mutate shared headers concurrently.

## Restriction scope

End users are associated with **platform account + Safety ID**. Controls are also scoped to the route and actual upstream model. Account-wide restrictions affect all end users for that route and model, rather than every interface and model on the account.

| Scenario | Behavior |
| - | - |
| Valid Safety ID triggers a restriction | Restricts that end user on the route and actual model. |
| Missing or empty ID triggers a restriction | Restricts all end users of the account on that route and model. |
| Multiple IDs meet account escalation conditions | All end users enter account-level cooldown on that route and model. |
| Same account and Safety ID, different API keys | Share refusal counts and restrictions. |
| Same account, different IDs | Separate end-user counters, still subject to shared account-level restrictions. |
| Different accounts, same ID | Independently associated with each account. |
| Add a valid ID during account-level restriction | The account restriction remains active. |

If end user A is restricted individually, end user B is not counted in A's restriction and can continue calling unless account-level or other restrictions apply.

## Account escalation across end users

Two configurable conditions can escalate to account scope within a rolling window: a threshold of distinct IDs receiving matching anti-distillation refusals, or a threshold of distinct IDs entering end-user restrictions because of matching refusals. Either condition can place all end users of the account into cooldown for that route and actual model.

New-policy defaults are 20 distinct IDs receiving matching refusals, or 5 distinct IDs triggering end-user restrictions, within 600 seconds. Confirm actual enablement and thresholds with the platform. Each ID counts once per condition. Successful responses do not clear existing entries; entries expire as they leave the window. API keys belonging to the same account share these statistics.

Stable IDs help isolate individual users but do not guarantee other users remain unaffected. Once account-level restrictions apply, changing IDs, removing the header, or switching API keys within the account does not bypass them. Other routes and actual models are handled separately.

## Errors and recovery

Read `error.code` for OpenAI-compatible errors and `error.type` for Claude Messages errors. Do not identify errors solely by message wording.

| HTTP | Error or condition | Client action |
| - | - | - |
| `400` | Invalid, overlong, or repeated Safety ID | Correct the header. Do not remove it to downgrade retries automatically. |
| `503` | `user_model_circuit_open` | Wait for `Retry-After` before retrying; the applicable scope is cooling down. |
| `503` | `user_model_probe_busy` | Wait for `Retry-After`; a recovery probe is already running. Avoid concurrent retries. |
| `503` | `user_model_circuit_state_unavailable` | Use bounded retries with backoff. Contact the platform if this persists. |

For validation errors, OpenAI-compatible responses have `error.code: "invalid_request"` and `error.type: "anyfast_api_error"`. Claude Messages responses have `error.type: "anyfast_api_error"` without `error.code`. These values also cover other parameter errors, so inspect HTTP `400` and the message to locate the invalid input. The three `503` identifiers use each protocol's corresponding error field.

`Retry-After` is a suggested delay in seconds. `Retry-After: 120` means wait at least 120 seconds; it does not guarantee full recovery then. Without the header, use bounded backoff and avoid frequent requests.

After cooldown, controlled probes precede gradual recovery based on complete call results. If both account and end user are restricted, both layers must recover in sequence. Effective platform policy determines thresholds, cooldown, and recovery conditions.

Reuse the original ID for retries. Do not immediately disable every user after a `503`, and do not rotate IDs, switch API keys, or remove headers to bypass restrictions. Confirm the affected scope and control retries accordingly.

The upstream call reaching a trigger threshold can still return HTTP `200` with refusal content; subsequent calls are then restricted. Handle model refusals according to the protocol instead of treating every `200` as business success. `user_model_circuit_state_unavailable` does not establish that an end user violated policy.

## Locate end users from platform feedback

Use the platform account and reported Safety ID to look up the user and request records internally. Notifications require separate agreement; adding a header does not subscribe you automatically. Account-scope records may be labeled “所有终端客户” (all end users), which is not an individual Safety ID. For escalation events, the window, distinct-ID count, and threshold describe the trigger, rather than consecutive refusal counts.

Log Safety ID, request time, model, HTTP status, error identifier, and any response request ID. Standard error responses do not echo Safety ID, so retain request-side associations.

When asking for help, provide:

* Platform account ID.
* Exact, case-preserved Safety ID, or state that it was missing or empty.
* Request time with timezone and requested model.
* HTTP status, error identifier, and `Retry-After`, if present.
* Request ID and any platform-provided restriction record or event ID.

Do not provide API keys or passwords. For help lifting a restriction, include the affected scope for platform review.

## Launch checklist

* IDs remain consistent across normal calls, streaming, retries, and different API keys.
* Different end users and tenants do not accidentally share IDs.
* Backend and proxies send one header without dropping or appending values.
* Concurrent SDK calls do not mix users' IDs.
* Clients handle `400`, `503`, `Retry-After`, and error JSON before streams.
* Reported IDs can be mapped to internal users and requests.

<script src="/public/feedback.js" />


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.