Skip to content
Docs

AI Gateway REST API Reference

For sending inference requests, the AI SDK lets you interact with AI Gateway from TypeScript or Python. You can also send requests through the chat completions, responses, Anthropic Messages, or OpenResponses APIs.

AI Gateway exposes a REST API for looking up usage and generations, querying spend reports, and discovering models. This page is the canonical reference for those endpoints. The AI SDK AI Gateway provider also exposes TypeScript APIs for the same data, which you can use as an alternative to calling the REST endpoints directly.

Base URL
https://ai-gateway.vercel.sh/v1

Most endpoints require authentication. The exceptions are noted on each endpoint.

Pass an AI Gateway API key in the Authorization header. AI Gateway infers the team from the key.

HTTP header
Authorization: Bearer <api_key>

On Vercel deployments, you can pass the Vercel OIDC token in the Authorization header instead. The token is generated automatically per project.

EndpointDescription
GET /v1/modelsList all available models
GET /v1/models/{creator}/{model}/endpointsGet every provider endpoint serving a model
GET /v1/creditsCheck the team's AI Gateway Credits balance and total spend
GET /v1/generationLook up cost, latency, and token usage for a specific generation
GET /v1/reportQuery aggregated spend reports for the team
Endpoint
GET /v1/models

Lists every model available through AI Gateway, including reasoning controls, supported parameters, pricing, and modalities. Follows the OpenAI models API format. No authentication required.

For the AI SDK equivalent, see Dynamic Model Discovery.

list-models.ts
const response = await fetch('https://ai-gateway.vercel.sh/v1/models');
const { data: models }: { data: Array<{ id: string; name: string }> } =
  await response.json();
 
models.forEach((model) => {
  console.log(`${model.id}: ${model.name}`);
});

For TypeScript, Python, and cURL examples that filter reasoning models and inspect their controls, see Discover model reasoning support.

Response
{
  "object": "list",
  "data": [
    {
      "id": "google/gemini-3.1-pro-preview",
      "object": "model",
      "created": 1755815280,
      "released": 1763424000,
      "owned_by": "google",
      "name": "Gemini 3.1 Pro Preview",
      "description": "This model improves upon Gemini 2.5 Pro and is catered towards challenging tasks, especially those involving complex reasoning or agentic workflows.",
      "context_window": 1000000,
      "max_tokens": 64000,
      "type": "language",
      "tags": ["file-input", "tool-use", "reasoning", "vision"],
      "pricing": {
        "input": "0.000002",
        "output": "0.000012",
        "input_cache_read": "0.0000002",
        "input_cache_write": "0.000002"
      }
    }
  ]
}
FieldTypeDescription
objectstringAlways "list"
dataarrayArray of available models
data[].idstringModel identifier (for example, openai/gpt-6-astra)
data[].objectstringAlways "model"
data[].createdintegerUnix timestamp when the model was added
data[].releasedintegerUnix timestamp when the model was released
data[].owned_bystringModel provider or owner
data[].namestringHuman-readable model name
data[].descriptionstringModel description
data[].context_windowintegerMaximum context length in tokens
data[].max_tokensintegerMaximum output tokens
data[].typestringModel type: language, embedding, reranking, image, or video
data[].tagsstring[]Capability tags (for example, reasoning, tool-use, vision)
data[].supported_parametersstring[]Broad parameter support, such as reasoning and include_reasoning. Optional.
data[].reasoning_optionsarrayKnown reasoning controls. Optional; omission means the controls aren't specified.
data[].reasoning_options[].typestringeffort, budget_tokens, or toggle. A model can support several controls.
data[].reasoning_options[].valuesstring[]Allowed model effort values; present on an effort entry. Check client and format support before using a value.
data[].reasoning_options[].minnumberOptional minimum thinking-token budget, on a budget_tokens entry.
data[].reasoning_options[].maxnumberOptional maximum thinking-token budget, on a budget_tokens entry.
data[].pricingobjectPricing information (structure varies by model type)
data[].pricing.inputstringBase cost per input token
data[].pricing.input_tiersarrayTiered pricing for input tokens (see Tiered pricing)
data[].pricing.outputstringBase cost per output token (language models only)
data[].pricing.output_tiersarrayTiered pricing for output tokens
data[].pricing.input_cache_readstringCost per cached input token (read)
data[].pricing.input_cache_writestringCost per input token (cache write)
data[].pricing.imagestringCost per generated image (image models only)
data[].pricing.web_searchstringCost per web search request

The catalog doesn't expose a structured reasoning default. Missing controls or budget bounds mean unspecified metadata, not unsupported reasoning or an unlimited budget. The controls describe model capabilities; each request format has its own fields and accepted values.

Pass include_availability with an authenticated request to annotate the catalog with each model's eligibility under your team's configuration:

Endpoint
GET /v1/models?include_availability

Eligibility reflects your team's stored defaults: model and provider allowlists, routing rules, stored BYOK credentials, virtual model configuration, plan restrictions, and rate-limit configuration. It does not evaluate request-supplied credentials, request-selected providers, live provider health, or account state beyond the request-level result below.

list-model-availability.ts
const response = await fetch(
  'https://ai-gateway.vercel.sh/v1/models?include_availability',
  { headers: { Authorization: `Bearer ${process.env.AI_GATEWAY_API_KEY}` } },
);
const { data: models } = await response.json();
 
const eligible = models.filter(
  (model) => model.model_eligibility?.status === 'eligible',
);

Each model row gains a model_eligibility field, and the response adds request-level fields:

FieldTypeDescription
data[].model_eligibility.statusstringeligible, ineligible, or unknown
data[].model_eligibility.evaluated_runtimestringThe runtime the verdict applies to: http or realtime_websocket
data[].model_eligibility.categorystringFor ineligible rows: configuration, policy, or transient
data[].model_eligibility.reasonstringStable machine-readable reason for ineligible and unknown rows
request_context_availabilityobjectAccount admission per runtime (available, unavailable, or unknown): team blocking, verification, funds, quota
availability_statusstringcomplete, or partial when any row is unknown
catalog_statusstringcomplete, or partial when private model or virtual model resolution was incomplete
evaluation_contextobjectThe evaluation scope: credential_mode: "runtime_default" and request_constraints: "default_only"

A model can serve a request when its status is eligible and the matching request_context_availability runtime is available. Treat unknown as neither approval nor denial; it means a dependency could not be resolved.

RequestResponse
No query parameterPublic catalog, edge-cached. Authenticated requests also include the team's private models and virtual models. No annotations.
include_availability with authenticationThe same catalog with annotations. Cache-Control: private, no-store.
include_availability without authentication401

Annotated requests share a per-team rate limit. A blocked request returns 429 with Retry-After: 60.

Endpoint
GET /v1/models/{creator}/{model}/endpoints

Returns every provider endpoint serving a specific model, along with per-endpoint pricing, capabilities, and supported parameters. No authentication required.

get-model-endpoints.ts
const response = await fetch(
  'https://ai-gateway.vercel.sh/v1/models/google/gemini-3.1-pro-preview/endpoints',
);
const {
  data,
}: {
  data: {
    name: string;
    endpoints: Array<{ provider_name: string; context_length: number }>;
  };
} = await response.json();
 
console.log(`Model: ${data.name}`);
data.endpoints.forEach((endpoint) => {
  console.log(`  ${endpoint.provider_name}: ${endpoint.context_length} tokens`);
});
Response
{
  "data": {
    "id": "google/gemini-3.1-pro-preview",
    "name": "Gemini 3.1 Pro Preview",
    "created": 1755815280,
    "released": 1763424000,
    "description": "This model improves upon Gemini 2.5 Pro and is catered towards challenging tasks, especially those involving complex reasoning or agentic workflows.",
    "architecture": {
      "tokenizer": null,
      "instruct_type": null,
      "modality": "text+image+file→text",
      "input_modalities": ["text", "image", "file"],
      "output_modalities": ["text"]
    },
    "endpoints": [
      {
        "name": "google | google/gemini-3.1-pro-preview",
        "model_name": "Gemini 3.1 Pro Preview",
        "context_length": 1000000,
        "pricing": {
          "prompt": "0.000002",
          "completion": "0.000012",
          "input_cache_read": "0.0000002",
          "input_cache_write": "0.000002"
        },
        "provider_name": "google",
        "max_completion_tokens": 64000,
        "supported_parameters": ["max_tokens", "temperature", "tools", "reasoning"],
        "status": 0,
        "uptime_last_15m": 100,
        "uptime_last_1h": 99.8,
        "uptime_last_1d": 99.6,
        "throughput_last_1h": { "p50": 67, "p95": 69.85 },
        "latency_last_1h": { "p50": 2292, "p95": 2685 },
        "supports_implicit_caching": false
      }
    ]
  }
}
FieldTypeDescription
data.idstringModel identifier
data.namestringHuman-readable model name
data.createdintegerUnix timestamp when the model was added
data.releasedintegerUnix timestamp when the model was released
data.descriptionstringModel description
data.architectureobjectModel architecture details
data.architecture.modalitystringInput/output modality string
data.architecture.input_modalitiesstring[]Supported input types
data.architecture.output_modalitiesstring[]Supported output types
data.endpointsarrayArray of provider endpoints
data.endpoints[].provider_namestringProvider name (for example, google, anthropic)
data.endpoints[].context_lengthintegerMaximum context window in tokens
data.endpoints[].max_completion_tokensintegerMaximum output tokens
data.endpoints[].pricing.promptstringCost per prompt token
data.endpoints[].pricing.completionstringCost per completion token
data.endpoints[].pricing.input_cache_readstringCost per cached input token (read)
data.endpoints[].pricing.input_cache_writestringCost per input token (cache write)
data.endpoints[].supported_parametersstring[]API parameters supported by this endpoint
data.endpoints[].supports_implicit_cachingbooleanWhether the provider supports automatic caching
data.endpoints[].statusintegerEndpoint status: 0 is active
data.endpoints[].uptime_last_15mnumberUptime percentage over the last 15 minutes
data.endpoints[].uptime_last_1hnumberUptime percentage over the last hour
data.endpoints[].uptime_last_1dnumberUptime percentage over the last day
data.endpoints[].throughput_last_1hobjectp50 and p95 throughput (tokens/sec) over the last hour
data.endpoints[].latency_last_1hobjectp50 and p95 time to first token (ms) over the last hour

For more on the uptime and metrics fields, see Uptime and Status and Metrics.

Some models have tiered pricing based on context size. When tiered pricing applies, the *_tiers arrays contain pricing tiers:

FieldTypeDescription
coststringCost per token for this tier
minnumberMinimum token count (inclusive)
maxnumberMaximum token count (exclusive), omitted for the highest tier
Endpoint
GET /v1/credits

Returns the team's current AI Gateway Credits balance and lifetime spend.

For the AI SDK equivalent, see Credit Usage.

credits.ts
const apiKey = process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN;
 
const response = await fetch('https://ai-gateway.vercel.sh/v1/credits', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
});
 
const credits = await response.json();
console.log(credits);
credits.py
import os
import requests
 
api_key = os.getenv("AI_GATEWAY_API_KEY") or os.getenv("VERCEL_OIDC_TOKEN")
 
response = requests.get(
    "https://ai-gateway.vercel.sh/v1/credits",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    },
)
 
credits = response.json()
print(credits)
credits.sh
curl -X GET "https://ai-gateway.vercel.sh/v1/credits" \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY"
Response
{
  "balance": "95.50",
  "total_used": "4.50"
}
  • balance: Remaining credit balance, in USD
  • total_used: Total credits used to date, in USD
Endpoint
GET /v1/generation?id={generation_id}

Returns detailed information about a specific generation, including cost, latency, and token usage. Much of this data is also returned in providerMetadata on the chat completion response.

For a complete request-and-lookup example with the AI SDK, see Look up a generation with the AI SDK.

Usage events are ingested asynchronously, so a lookup issued immediately after the generation completes returns Usage event not found rather than the record. Allow a few seconds, and treat that response as "not yet" rather than "never" when polling.

For the AI SDK equivalent, see Generation Lookup.

  • id (required): The generation ID to look up. Format: gen_<ulid>.
generation-lookup.ts
const generationId = 'gen_01ARZ3NDEKTSV4RRFFQ69G5FAV';
 
const response = await fetch(
  `https://ai-gateway.vercel.sh/v1/generation?id=${generationId}`,
  {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${process.env.AI_GATEWAY_API_KEY}`,
      'Content-Type': 'application/json',
    },
  },
);
 
const generation = await response.json();
console.log(generation);
generation-lookup.py
import os
import requests
 
generation_id = 'gen_01ARZ3NDEKTSV4RRFFQ69G5FAV'
 
response = requests.get(
    f"https://ai-gateway.vercel.sh/v1/generation?id={generation_id}",
    headers={
        "Authorization": f"Bearer {os.getenv('AI_GATEWAY_API_KEY')}",
        "Content-Type": "application/json",
    },
)
 
generation = response.json()
print(generation)
generation.sh
curl -X GET "https://ai-gateway.vercel.sh/v1/generation?id=gen_01ARZ3NDEKTSV4RRFFQ69G5FAV" \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY"
Response
{
  "data": {
    "id": "gen_01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "total_cost": 0.00123,
    "market_cost": 0.0011,
    "surcharge_cost": 0.00013,
    "gateway_cost": 0.00123,
    "upstream_inference_cost": 0,
    "usage": 0.00123,
    "created_at": "2026-05-22T00:00:00.000Z",
    "model": "anthropic/claude-opus-5",
    "is_byok": false,
    "provider_name": "anthropic",
    "streamed": true,
    "finish_reason": "stop",
    "latency": 200,
    "generation_time": 1500,
    "tokens_prompt": 100,
    "tokens_completion": 50,
    "native_tokens_prompt": 100,
    "native_tokens_completion": 50,
    "native_tokens_reasoning": 0,
    "native_tokens_cached": 0,
    "native_tokens_cache_creation": 0,
    "billable_web_search_calls": 0
  }
}
  • id: The generation ID
  • total_cost: Total cost in USD for this generation debited from your gateway balance, including any surcharges (for example, Zero Data Retention or Custom Reporting writes). Does not include cost of BYOK requests.
  • market_cost: Cost of this generation at market list inference rates. Omitted when not recorded for the generation.
  • surcharge_cost: Total surcharges applied to this generation (for example, Zero Data Retention or Custom Reporting writes)
  • gateway_cost: Total amount debited from your AI Gateway balance for this generation. Same as total_cost.
  • upstream_inference_cost: Market list price for BYOK that the provider would have charged for the inference. Non-zero only for BYOK generations. 0 otherwise.
  • usage: Same as total_cost.
  • created_at: ISO 8601 timestamp when the generation was created
  • model: Model identifier used for this generation
  • is_byok: Whether this generation used Bring Your Own Key (BYOK) credentials
  • provider_name: The provider that served this generation
  • streamed: Whether this generation used streaming
  • finish_reason: Why the generation ended (for example, stop, length, content_filter, tool_calls)
  • latency: Time to first token in milliseconds
  • generation_time: Total generation time in milliseconds
  • tokens_prompt: Number of prompt tokens
  • tokens_completion: Number of completion tokens
  • native_tokens_prompt: Native prompt tokens (provider-specific)
  • native_tokens_completion: Native completion tokens (provider-specific)
  • native_tokens_reasoning: Reasoning tokens used
  • native_tokens_cached: Cached input tokens read
  • native_tokens_cache_creation: Cache creation tokens written
  • billable_web_search_calls: Number of billable web search calls performed during this generation

Generation IDs: Generation IDs are returned on every chat completion response as the id field, and on streaming responses are injected into the first content chunk so you can capture them before the stream completes. They are also surfaced via providerMetadata.gateway.generationId in the AI SDK.

Use the Custom Reporting API to break down spend and usage by model, user, tag, provider, or credential type. For concepts, how to attach tags and user IDs to requests, querying with the AI SDK, and the full response field reference, see the Custom Reporting page.

Endpoint
GET /v1/report

Returns aggregated spend over a date range. The team is inferred from the API key or OIDC token. Hobby and Pro-trial plans cannot use this endpoint.

For the AI SDK equivalent, see Querying Spend Reports.

ParameterTypeDescription
start_datestringStart date in YYYY-MM-DD format
end_datestringEnd date in YYYY-MM-DD format

Dates are inclusive (both start_date and end_date are included) and in UTC.

ParameterTypeDescription
group_bystringHow to aggregate results. One of day (default), user, model, tag, provider, credential_type, zero_data_retention, api_key_name.
date_partstringTime granularity when group_by=day. One of day (default) or hour.
api_key_idstringFilter by a stable API key ID. Use self for the AI Gateway API key that authenticated the report request. self requires AI Gateway API key authentication. The API returns a 400 response for self with OIDC tokens, personal access tokens, or app tokens. Omit this parameter to report across the team.
user_idstringFilter by a specific user ID.
modelstringFilter by a specific model in creator/model-name format.
providerstringFilter by provider.
credential_typestringFilter by credential type: byok or system.
zero_data_retentionbooleanFilter to ZDR-requested vs non-ZDR requests.
tagsstringFilter by one or more comma-separated tags. By default, requests match when they contain any listed tag.
tags_matchstringMatch mode for tags. Use any to match requests with any listed tag, or all to require every listed tag. Defaults to any.

API key names are not unique, so use api_key_id when filtering by API key.

terminal
curl "https://ai-gateway.vercel.sh/v1/report?start_date=2026-01-01&end_date=2026-01-31&group_by=model" \
  -H "Authorization: Bearer $AI_GATEWAY_API_KEY"

For the full response shape, sample JSON, and the per-field reference (which grouping fields appear with which group_by value, plus all metric fields), see Response format and Response fields on the Custom Reporting page.

Errors return a JSON body with an error field. Some endpoints additionally include a type discriminator on the error object.

Error response
{
  "error": {
    "message": "Invalid request body",
    "type": "invalid_request_error"
  }
}
StatusMeaning
400Invalid request body, missing required fields, or validation error.
401Authentication failed (invalid API key or OIDC token).
403Endpoint requires a paid plan (for example, Hobby and Pro-trial cannot query /v1/report).
404Resource not found (for example, a generation that doesn't exist).
500Internal server error.
503A backing service is misconfigured or unavailable.
Last updated September 11, 2026

Was this helpful?

supported.