Custom Reporting
The Custom Reporting API gives you detailed visibility into your AI Gateway usage. You can break down costs and token consumption by model, user, tag, provider, or credential type to understand exactly where your AI spend is going.
Use it to:
- Track costs by model: See how much you're spending on each model and compare cost efficiency across providers
- Monitor per-user usage: Identify which users are driving the most spend and token consumption
- Analyze by tags: Tag requests by feature, environment, or team to attribute costs and track usage across your organization
- Compare providers: Understand cost and usage differences between providers serving the same models
- Audit BYOK vs system credentials: Break down usage by credential type to see the impact of bring-your-own-key requests
| Charge type | Cost |
|---|---|
| Tag/User ID | $0.075 per 1,000 unique tag or user ID values written per request |
| Query | $5 per 1,000 queries to the reporting endpoint |
To use reporting, attach a user and/or tags to your AI Gateway requests. You can do this through the AI SDK, Chat Completions API, Responses API, OpenResponses API, or Anthropic Messages API.
The AI SDK supports user and tag submission through the gateway provider. See the AI SDK docs on usage tracking with user and tags for details.
import { gateway } from '@ai-sdk/gateway';
import { generateText } from 'ai';
const { text } = await generateText({
model: gateway('anthropic/claude-sonnet-4.6'),
prompt: 'Tell me about San Francisco.',
providerOptions: {
gateway: {
user: 'user-123',
tags: ['a', 'b'],
},
},
});You have two options when using the Chat Completions API:
- User only: Pass
userin the standard chat completionsuserfield - User and tags: Pass
userand/ortagsthrough provider options
const completion = await openai.chat.completions.create({
model: 'anthropic/claude-sonnet-4.6',
messages: [
{
role: 'user',
content: 'Tell me about San Francisco.',
},
],
providerOptions: {
gateway: {
user: 'user-123',
tags: ['a', 'b'],
},
},
});completion = client.chat.completions.create(
model='anthropic/claude-sonnet-4.6',
messages=[
{
'role': 'user',
'content': 'Tell me about San Francisco.',
},
],
extra_body={
'providerOptions': {
'gateway': {
'user': 'user-123',
'tags': ['a', 'b'],
},
},
},
)Pass user and/or tags through provider options on the Responses API:
const response = await openai.responses.create({
model: 'anthropic/claude-sonnet-4.6',
input: [
{
type: 'message',
role: 'user',
content: 'Tell me about San Francisco.',
},
],
providerOptions: {
gateway: {
user: 'user-123',
tags: ['a', 'b'],
},
},
});response = client.responses.create(
model='anthropic/claude-sonnet-4.6',
input=[
{
'type': 'message',
'role': 'user',
'content': 'Tell me about San Francisco.',
},
],
extra_body={
'providerOptions': {
'gateway': {
'user': 'user-123',
'tags': ['a', 'b'],
},
},
},
)Pass user and/or tags through provider options on the OpenResponses API:
const response = await fetch('https://ai-gateway.vercel.sh/v1/responses', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.AI_GATEWAY_API_KEY}`,
},
body: JSON.stringify({
model: 'anthropic/claude-sonnet-4.6',
input: [
{
type: 'message',
role: 'user',
content: 'Tell me about San Francisco.',
},
],
providerOptions: {
gateway: {
user: 'user-123',
tags: ['a', 'b'],
},
},
}),
});response = client.responses.create(
model='anthropic/claude-sonnet-4.6',
input=[
{
'type': 'message',
'role': 'user',
'content': 'Tell me about San Francisco.',
},
],
extra_body={
'providerOptions': {
'gateway': {
'user': 'user-123',
'tags': ['a', 'b'],
},
},
},
)Pass user and/or tags through provider options on the Anthropic Messages API:
const message = await anthropic.messages.create({
model: 'anthropic/claude-sonnet-4.6',
max_tokens: 1024,
messages: [
{
role: 'user',
content: 'Tell me about San Francisco.',
},
],
providerOptions: {
gateway: {
user: 'user-123',
tags: ['a', 'b'],
},
},
});message = client.messages.create(
model='anthropic/claude-sonnet-4.6',
max_tokens=1024,
messages=[
{
'role': 'user',
'content': 'Tell me about San Francisco.',
},
],
extra_body={
'providerOptions': {
'gateway': {
'user': 'user-123',
'tags': ['a', 'b'],
},
},
},
)The reporting endpoint is available on Pro and Enterprise plans.
GET https://ai-gateway.vercel.sh/v1/report
All requests require a Bearer token in the Authorization header:
Authorization: Bearer YOUR_API_KEY| Parameter | Type | Description |
|---|---|---|
start_date | string | Start date in YYYY-MM-DD format |
end_date | string | End date in YYYY-MM-DD format |
Dates are inclusive (both start_date and end_date are included) and in UTC.
| Parameter | Type | Options | Description |
|---|---|---|---|
group_by | string | model, user, tag, provider, credential_type | How to group the results |
date_part | string | hour, day | Time period to group results into (UTC) |
| Parameter | Type | Description | Example |
|---|---|---|---|
user_id | string | Filter by a specific user ID | user_123 |
model | string | Filter by a specific model in creator/model-name format | anthropic/claude-sonnet-4.6 |
tags | string | Filter by tags (comma-separated). Uses boolean OR, so any matching tag on a request counts as a match. | production or production,api |
credential_type | string | Filter by credential type | byok or system |
provider | string | Filter by provider | openai |
The API returns a JSON object with a results array. Each result only contains the grouping field relevant to the group_by parameter you used. It can take a few minutes for requests to appear in the reporting endpoint.
{
"results": [
{
"day": "2026-01-01",
"model": "anthropic/claude-sonnet-4.6",
"provider": "anthropic",
"user": "user_123",
"tag": "production",
"total_cost": 10.5,
"market_cost": 12.0,
"input_tokens": 1000,
"output_tokens": 500,
"cached_input_tokens": 200,
"cache_creation_input_tokens": 50,
"reasoning_tokens": 100,
"request_count": 25
}
]
}| Field | Description |
|---|---|
day | The date for this result group in UTC (YYYY-MM-DD) |
model | Present when group_by=model |
provider | Present when group_by=provider |
user | Present when group_by=user |
tag | Present when group_by=tag |
total_cost | Charged price in USD. Returns 0.00 for BYOK requests. |
market_cost | Market price of the request at the time it ran |
input_tokens | Input tokens used |
output_tokens | Output tokens used |
cached_input_tokens | Cached input tokens |
cache_creation_input_tokens | Cache creation tokens |
reasoning_tokens | Reasoning tokens |
request_count | Number of requests |
All cost values are in USD and aggregated based on the grouping parameter.
curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&date_part=day" \
-H "Authorization: Bearer YOUR_API_KEY"curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&date_part=hour&group_by=model" \
-H "Authorization: Bearer YOUR_API_KEY"curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&group_by=user" \
-H "Authorization: Bearer YOUR_API_KEY"curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&group_by=tag" \
-H "Authorization: Bearer YOUR_API_KEY"curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&group_by=credential_type" \
-H "Authorization: Bearer YOUR_API_KEY"You can combine filters to narrow results:
curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&date_part=day&user_id=user_123&model=anthropic/claude-sonnet-4.6&tags=production,api" \
-H "Authorization: Bearer YOUR_API_KEY"Was this helpful?