# Response headers

DirectInference returns one header that lets you observe how a request was handled — without ever exposing the model behind it.

## X-DI-Request-Type

Every response on the DI surface carries an `X-DI-Request-Type` header naming the request type the call was classified as — `pro`, `code`, `vision`, `document`, `long`, `json`, `reason`, or `flash`. It is a fact about your own request (a PDF makes it a `document` request), so it is safe to surface; the model that served it stays private.

```python
# The OpenAI SDK exposes raw response headers via with_raw_response.
raw = client.chat.completions.with_raw_response.create(
    model="gpt-5.5-mini",
    messages=[{"role": "user", "content": "Refactor this function."}],
)

print(raw.headers.get("x-di-request-type"))   # -> "code"

resp = raw.parse()                             # the usual typed completion
print(resp.choices[0].message.content)
```

```typescript
// .withResponse() hands back the raw Response alongside the parsed data.
const { data, response } = await client.chat.completions
  .create({
    model: "gpt-5.5-mini",
    messages: [{ role: "user", content: "Refactor this function." }],
  })
  .withResponse();

console.log(response.headers.get("x-di-request-type")); // -> "code"
console.log(data.choices[0].message.content);
```

```bash
# -D - dumps response headers to stdout; the body still streams as normal.
curl -sS -D - -o /dev/null https://app.directinference.com/di/v1/chat/completions \
  -H "Authorization: Bearer llm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5-mini",
    "messages": [{ "role": "user", "content": "Refactor this function." }]
  }' | grep -i "x-di-request-type"

# x-di-request-type: code
```

```go
var raw *http.Response

resp, err := client.Chat.Completions.New(
	context.TODO(),
	openai.ChatCompletionNewParams{
		Model: "gpt-5.5-mini",
		Messages: []openai.ChatCompletionMessageParamUnion{
			openai.UserMessage("Refactor this function."),
		},
	},
	option.WithResponseInto(&raw), // capture the underlying *http.Response
)
if err != nil {
	panic(err)
}

fmt.Println(raw.Header.Get("X-DI-Request-Type")) // -> "code"
fmt.Println(resp.Choices[0].Message.Content)
```

:::note[Where it appears]
The header is set on the DI surface (`…/di` and `…/di/v1`), not on `/v1`. It is allow-listed in `Access-Control-Expose-Headers`, so a browser client can read it cross-origin. The value matches the names in [Request types](https://docs.directinference.com/request-types/); the same vocabulary rolls up in [Usage & analytics](https://docs.directinference.com/usage/).
:::

## What DirectInference never returns

There is no resolved-model header. Other services hand back the model they picked; DirectInference does not — not in a header, not in the body, not in a trailer. The response echoes the `model` id you sent and nothing about the candidate, provider, version, cost, or trace that produced it.

:::note[Opacity is the contract]
Because no backend identity is ever returned, your logs, dashboards, and eval pipelines cannot accidentally capture — or come to depend on — a specific model. That is what lets DirectInference move traffic to a better or cheaper model at any time with zero changes to your code. The only classification signal you get back is the request type above.
:::