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

# Request metadata

> Attach app name, identity, thread ID, and custom metadata to AI Gateway requests to segment cost, latency, and traces in observability.

**Use Cases**

<AccordionGroup>
  <Accordion title="Attribute requests to an app or service">
    Name each request so cost and performance slice by product, feature, or environment.
  </Accordion>

  <Accordion title="Group analytics by end user or tenant">
    Attach an **Identity** so spend, latency, and error rates attribute to a user, team, or client, with optional per-identity budgets.
  </Accordion>

  <Accordion title="Group multi-turn conversations">
    Tag each turn with a **Thread** ID so the full conversation groups together in observability.
  </Accordion>

  <Accordion title="Slice analytics by business context">
    Attach key-value metadata, such as tier, channel, or feature flag, and filter traces by those fields.
  </Accordion>
</AccordionGroup>

## Overview

Every **AI Gateway** request can carry context through several mechanisms:

* `name`: marks the app or service
* `identity`: marks the end user or tenant
* `thread`: groups a conversation
* `metadata`: carries business context

Each mechanism answers one question and surfaces through its own channel. Use the decision table below to pick the mechanism for a given question.

`variables` also travel with the request, but fill prompt templates instead of describing the request. The how-to for each mechanism lives in [App Tracking](/ai-gateway/app-tracking), [Identities](/ai-studio/observability/identities), and [Thread Management](/ai-gateway/thread-management); the span attribute reference is in [Metadata](/ai-studio/observability/span-attributes).

## Which mechanism to use

| Mechanism | Answers the question | Use when |
| - | - | - |
| `name` | Which app, service, or feature made this call? | Cost and performance per product line, with a fixed set of known surfaces |
| `identity` | Which end user, team, or client is this request for? | Per-user attribution, tenant billing, per-identity budgets |
| `thread` | Which conversation or workflow does this request belong to? | Multi-turn chats, multi-step agent workflows, support tickets |
| `metadata` | What business context applies to this request? | Key-value slicing by tier, channel, region, or feature flag |

## Quick Start

Send one request with all four mechanisms attached.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://my.orq.ai/v3/router/responses \
    -H "Authorization: Bearer $ORQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/gpt-5.4-mini",
      "input": "Refund my order",
      "name": "SupportAssistant-Production",
      "metadata": {
        "customer_tier": "premium",
        "channel": "email"
      },
      "thread": {
        "id": "conversation-abc123",
        "tags": ["user-123"]
      },
      "identity": {
        "id": "user_123"
      }
    }'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from "openai";

  const client = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: "https://my.orq.ai/v3/router",
  });

  const response = await client.responses.create({
    model: "openai/gpt-5.4-mini",
    input: "Refund my order",
    name: "SupportAssistant-Production",
    metadata: { customer_tier: "premium", channel: "email" },
    thread: { id: "conversation-abc123", tags: ["user-123"] },
    identity: { id: "user_123" },
  });

  console.log(response.output_text);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://my.orq.ai/v3/router",
  )

  response = client.responses.create(
      model="openai/gpt-5.4-mini",
      input="Refund my order",
      extra_body={
          "name": "SupportAssistant-Production",
          "metadata": {"customer_tier": "premium", "channel": "email"},
          "thread": {"id": "conversation-abc123", "tags": ["user-123"]},
          "identity": {"id": "user_123"},
      },
  )

  print(response.output_text)
  ```
</CodeGroup>

## Configuration

| Parameter | Type | Trace filter | Description |
| - | - | - | - |
| `name` | string | Name | Display name on the trace. Recommended: alphanumeric and hyphens only, under 50 characters, no timestamps or dynamic values. |
| `metadata` | object | `metadata.<key>` | Key-value pairs with string values. On the **Responses API**, non-string values are rejected with a 400. |
| `thread` | object | Thread ID | Groups related requests: `id` (required) plus optional `tags`. |
| `identity` | object | Identity | Attributes the request to an end user: `id` (required) plus optional `display_name`, `email`, `metadata`, and `tags`. |
| `variables` | object | — | Template variables for prompt substitution. Pass secrets as `{"secret": true, "value": "..."}` so they are redacted from traces. |

<Note>
  On `/v3/router/chat/completions`:

  * `metadata` is limited to 16 key-value pairs with keys up to 64 characters and values up to 512 characters
  * `thread` and `identity` are passed under the `orq` object (`orq.thread`, `orq.identity`)
  * `name` is passed at the top level
</Note>

## Headers

Clients that cannot modify the request body, such as coding agents, attach metadata, identity, and thread context through headers instead. `X-ORQ-IDENTITY-ID` and `X-ORQ-THREAD-ID` are read on every AI Gateway request. `X-ORQ-METADATA-<key>` and `X-ORQ-METADATA` are read on the inference endpoints: `/v3/router/responses`, `/v3/anthropic/v1/messages`, `/v3/google/v1beta/models/*` and `/v3/google/v1beta/interactions`, and the `/v3/router/*` completions, embeddings, image, audio, moderation, OCR, and rerank endpoints.

| Header | Sets | Example |
| - | - | - |
| `X-ORQ-METADATA-<key>` | One metadata key per header. The key is the lowercased header suffix. | `X-ORQ-METADATA-REPO: acme-api` sets `metadata.repo` to `acme-api`. |
| `X-ORQ-METADATA` | Several metadata keys in one header: a comma-separated `key=value` list, or a JSON object. | `X-ORQ-METADATA: repo=acme-api,ticket=PROJ-123` |
| `X-ORQ-IDENTITY-ID` | The identity ID. See [Identities](/ai-studio/observability/identities). | `X-ORQ-IDENTITY-ID: user_123` |
| `X-ORQ-THREAD-ID` | The thread ID. | `X-ORQ-THREAD-ID: conversation-abc123` |

When the `X-ORQ-METADATA` value starts with `{`, it is parsed as a JSON object instead of the comma-separated form. String, number, and boolean values are kept; object, array, and null values are skipped.

On the Anthropic Messages and Google endpoints only, a fixed allowlist of headers (`user-agent`, `originator`, `session-id`, `session_id`, `thread-id`, `x-app`, `x-claude-code-session-id`, `x-codex-beta-features`, `anthropic-beta`, `anthropic-version`, `anthropic-dangerous-direct-browser-access`) is captured into metadata automatically, when present, to identify the calling coding assistant. No other endpoint captures these headers automatically.

<Note>
  Precedence when the same metadata key is set more than once: the body `metadata` object wins, then `X-ORQ-METADATA-<key>` headers, then the `X-ORQ-METADATA` header, then, on the Anthropic Messages and Google endpoints only, the automatically-captured allowlist above.
</Note>

**Limits**: up to 20 metadata keys per request from `X-ORQ-METADATA` and `X-ORQ-METADATA-<key>` combined. On those endpoints, the automatically-captured allowlist headers do not count against this limit. Keys must be 64 characters or fewer and match `[a-z0-9._-]+`. Values longer than 256 characters are truncated. Entries that fail these rules are dropped silently; the request still succeeds.

Header-derived metadata reaches [Traces](/ai-studio/observability/traces) as `metadata.<key>` span attributes on every endpoint listed above, filterable the same way as body metadata. It is never forwarded to the model provider.

On endpoints that take a JSON body, `X-ORQ-METADATA` and `X-ORQ-METADATA-<key>` are also available to routing rules, guardrail rules, and budgets, so a caller able to set headers on a request can influence which of those rules match. Endpoints that take multipart uploads (transcription, translation, image edit, image variation) put header metadata on traces only. The automatically-captured allowlist above never reaches rule matching, on any endpoint.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://my.orq.ai/v3/router/responses \
    -H "Authorization: Bearer $ORQ_API_KEY" \
    -H "Content-Type: application/json" \
    -H "X-ORQ-METADATA-REPO: acme-api" \
    -H "X-ORQ-METADATA-TICKET: PROJ-123" \
    -H "X-ORQ-THREAD-ID: conversation-abc123" \
    -d '{
      "model": "openai/gpt-5.4-mini",
      "input": "Refund my order"
    }'
  ```
</CodeGroup>

## Best Practices

* **Keep app names low-cardinality**: Use a small fixed set of app names (around 50 per workspace) with consistent patterns such as `Service-Environment`. Avoid timestamps or dynamic values, which fragment analytics.
* **Use a fixed metadata key set**: Define a small set of keys (`customer_tier`, `channel`, `region`) and reuse them. High-cardinality keys, such as request IDs or timestamps, defeat filtering and increase storage.
* **Thread IDs**: Use UUIDs or composite keys such as `user-{userId}-{sessionId}` to avoid collisions across sessions.
* **Identity IDs**: Use predictable patterns such as `user-{userId}` or `tenant-{tenantId}` so identities stay consistent across requests.
* **One mechanism per question**: If the value describes the app, use `name`; if it describes the user, use `identity`; if it is business context, use `metadata`.

## What not to store in request metadata

* **PII**: Do not put emails, phone numbers, or personal data in `metadata`, `name`, or `thread.tags`; they persist on stored traces. To keep sensitive values out of stored traces, include `"metadata"` in [`security.mask`](/ai-gateway/features/security), or enable [PII Redaction](/ai-gateway/features/plugins/pii-redaction).
* **Secrets**: Pass tokens and keys as template variables with `{"secret": true, "value": "..."}` so they are redacted from traces. See [Run Agents](/ai-studio/ai-engineering/run-agents) for the variable reference.


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