AppAIGatewayDocs
Providers

Supported providers

The sixteen provider types, the native path each one expects, and which gateways can carry them.

Every provider you add has a type. The type fixes the upstream API, the authentication header the gateway sends, and the price catalog the model is looked up in. The path after the slug is always the provider's own, verbatim, without a leading slash:

/v1/apps/{app}/proxy/{slug}/{provider-path}

The OpenAI-compatible providers disagree about their prefix more than about anything else, so the exact chat-completions path is listed for each.

All provider types

TypeServiceChat completions pathThrough a gatewayNotes
openaiOpenAIv1/chat/completionsCloudflare, VercelAlso v1/responses, v1/audio/transcriptions, image generation.
anthropicAnthropicv1/messagesCloudflare, VercelAnthropic Messages, not chat completions.
xaixAI (Grok)v1/chat/completionsCloudflare, VercelAlso v1/responses, v1/stt, image generation. Reports its own cost.
geminiGoogle AI Studiov1beta/openai/chat/completionsCloudflare, VercelNative API at v1beta/models/{model}:generateContent.
perplexityPerplexitychat/completionsCloudflare, VercelSonar models. No test call.
deepseekDeepSeekchat/completionsVercelNo v1/ in the base URL.
moonshotMoonshot AI (Kimi)v1/chat/completionsVercelInternational api.moonshot.ai host.
groqGroqopenai/v1/chat/completionsDirect onlyOpenAI API namespaced under openai/.
mistralMistralv1/chat/completionsDirect only
togetherTogether AIv1/chat/completionsDirect onlyModels are namespaced, for example openai/gpt-oss-120b.
fireworksFireworks AIinference/v1/chat/completionsDirect onlyNo catalog; price your models. No test call.
cerebrasCerebrasv1/chat/completionsDirect only
huggingfaceHugging Face Inference Providersv1/chat/completionsDirect onlyNo catalog; pin the upstream in the model ID. No test call.
basetenBaseten Model APIsv1/chat/completionsDirect only
bytedanceBytePlus ModelArkchat/completionsDirect onlyVersion segment is already in the base URL. No test call.
openrouterOpenRouterv1/chat/completionsDirect onlyThe only path it accepts. Reports its own cost.

The console shows these labels in the Provider picker: OpenAI, Anthropic, xAI, Gemini, Perplexity, DeepSeek, Groq, Mistral, Together AI, Fireworks AI, Cerebras, Moonshot AI, Hugging Face, Baseten, ByteDance Ark, OpenRouter.

"Direct only" is the default, not a limitation of the type. A provider type is offered on a gateway once that pairing has been verified against the gateway's live catalog, because a provider slug or model namespace guessed from documentation is a guess about a URL and about which keys the gateway holds. Connect these types with their own API key.

The paths in the table are for providers that call the provider's own API. A provider routed through a gateway uses the gateway's paths instead. See Gateways.

Using an SDK

For the OpenAI SDK, set the base URL to https://api.appaigateway.com/v1/apps/YOUR-APP/proxy/openai/v1. The SDK then appends standard paths such as responses or chat/completions. The same works for any OpenAI-compatible provider: point the base URL at that provider's slug and its prefix, for example /proxy/groq/openai/v1. Request bodies and responses keep the provider's native format. See Calling the proxy.

Caveats by provider

A few types carry caveats worth knowing before you add a key.

ByteDance is the international BytePlus ModelArk endpoint in ap-southeast-1, and /api/v3 is already part of the base URL, so the path is chat/completions with no version segment of your own. Keys and model catalogs are region-isolated, and models must be activated in your ModelArk console before they answer. The China Volcengine edition is a separate service and is not reachable here. For another region, set a custom base URL.

Moonshot is the international api.moonshot.ai host. A key issued on the China platform will not work.

Fireworks names models per account (accounts/{account}/models/{id}), so no shipped catalog could be right for your account. Price the models you use under the provider's Pricing action. See Model pricing.

Hugging Face routes each request to whichever upstream it picks, and the same model costs up to ten times more on one upstream than another. Pin the upstream in the model ID (author/model:provider) and price that ID, or the recorded cost is a guess.

Gemini has two APIs. The OpenAI-compatible one lives at v1beta/openai/chat/completions; the native one at v1beta/models/{model}:generateContent. Both work on a direct or Cloudflare-routed Gemini provider. Only the OpenAI-compatible one works through Vercel.

Groq namespaces its OpenAI API under openai/, DeepSeek and ByteDance have no prefix at all, and Fireworks separates its inference plane from its control plane. Copy the path from the table rather than assuming v1/.

xAI and OpenRouter report what each request cost, and the gateway records that figure rather than a locally computed one. Each has a section of its own below: xAI and OpenRouter.

What Test provider calls

Test provider in the Add provider dialog, and POST /v1/admin/providers/test behind it, run the cheapest authenticated call the provider offers. A provider is missing from this table only when it has no call that can prove a key. That is deliberate: a test against a URL that answers 200 regardless of the credential would report every key as good.

ProviderTest call
OpenAIGET v1/models
xAIGET v1/models
AnthropicGET v1/models
GeminiGET v1beta/models
DeepSeekGET models
GroqGET openai/v1/models
MistralGET v1/models
Together AIGET v1/models
CerebrasGET v1/models
Moonshot AIGET v1/models
BasetenGET v1/models
OpenRouterGET v1/key, its key-status call. Its model list is public and would pass any key.
PerplexityNone. Accepted unchecked.
Fireworks AINone. Its model list needs an account ID the key does not carry.
Hugging FaceNone. Its model list answers 200 to any token.
ByteDanceNone. ModelArk publishes no list-models call.

The verdicts are explained in Add a provider key.

Image generation

Image endpoints are among an app's default inference endpoints, so an app that lists no paths can call them. Whether an image model proxies depends on how its provider charges for it:

ProviderImage modelsHow the gateway bills them
OpenAIgpt-image-* on v1/images/generations and v1/images/editsFrom the catalog, per token. Prompt text, input images and generated images each bill at their own rate.
GeminiGemini image models (Nano Banana) on v1beta/models/{model}:generateContentFrom the catalog, per token. Generated image tokens bill at the image rate.
xAIgrok-imagine-image and its siblings on v1/images/generations and v1/images/editsFrom the cost xAI reports. See xAI.
ByteDanceSeedream 5.0 flash, 5.0 lite, 4.5 and 4.0 on images/generationsFrom the catalog, per image: each model's price times the usage.generated_images the response reports.
Together AI, ByteDance (Seedream 5.0 pro) and othersBilled by size, quality or steps, or at an estimated priceNot supported: refused with pricing_not_configured.

If you list an app's endpoints yourself, include the image paths, with "clamp": "none". A list replaces the defaults. For OpenAI, for example:

"openai": {
  "allowed_paths": [
    "v1/responses",
    { "path": "v1/images/generations", "clamp": "none" },
    { "path": "v1/images/edits", "clamp": "none" }
  ],
  "allowed_models": ["gpt-image-2"]
}

Call Gemini image models on the native generateContent path. Its responses say how many output tokens were images. The OpenAI-compatible endpoint does not, so there every output token, text included, bills at the image rate.

Image generation inside another model's request is not covered: OpenAI's Responses API image_generation tool and Mistral's image_generation tool. In both, the usage counts only the calling model's tokens, so the recorded cost leaves out the generated images. To meter images, call the image endpoint directly.

xAI

Cost is reported, not computed. xAI's Chat Completions, Responses and image generation answers carry usage.cost_in_usd_ticks, what xAI actually billed for that request after any discount. The gateway records it as the event's cost with cost_source: "reported", ahead of any catalog price. So on those APIs an xAI model proxies with no local price, which is what makes image models such as grok-imagine-image work at all: xAI bills images per image and reports no token counts for them. Streaming works the same way; the figure arrives in the final chunk.

Two exceptions bill on local prices, like any other provider type:

  • xAI's Anthropic Messages API and v1/stt. xAI does not document a cost on them, so a model used there needs a price in the catalog or under the provider's Pricing action.
  • The Vercel route. Vercel answers through its own APIs rather than passing xAI's answer back, so the reported figure does not survive it. A Cloudflare AI Gateway route passes it through unchanged.

If a reporting API ever answers without a cost, a local price for the model is used if there is one (computed), and otherwise the event is marked unresolved.

xAI's image endpoints are among an app's default inference endpoints. An app that lists its endpoints itself includes them with "clamp": "none", because an image has no output tokens to cap. Video generation is not a default: xAI returns a job ID, and its result and cost arrive on a later poll the gateway cannot serve.

"xai": {
  "allowed_paths": [
    "v1/chat/completions",
    "v1/responses",
    { "path": "v1/images/generations", "clamp": "none" }
  ],
  "allowed_models": []
}

OpenRouter

OpenRouter is treated as a provider type, not as a gateway. It is the counterparty that charges you, and its catalog includes models with no direct provider at all. Two things follow.

Its slugs are the model IDs. google/gemini-3.6-flash and meta-llama/llama-4-maverick are the model IDs here. They are what you send, what an app's allowed models and fixed models match, and what a usage event records. They are not translated: an OpenRouter provider and a direct Gemini provider name the same model differently, so moving an app between them means renaming the model. The leading namespace is also where the model's author comes from, so usage groups by Google or Meta the same way it does on a direct route.

Cost is reported, not computed. Every OpenRouter chat-completions response carries usage.cost, what OpenRouter actually charged for that request. The gateway records it as the event's cost with cost_source: "reported". So OpenRouter models proxy with no local price: the pricing rule is satisfied by the route reporting its own cost, which is why no OpenRouter section ships in the catalog. Streaming works the same way; the figure arrives in the final chunk.

If a response ever comes back without a cost, the event is not recorded at zero. A custom price for that model is used if you have entered one (computed), and otherwise the event is marked unresolved.

Bring your own key: two figures, both yours. When a request runs on your own upstream provider key, OpenRouter's usage.cost is only its own fee (5% of what the request would have cost on OpenRouter), while the provider charges your key directly for the inference and OpenRouter reports that separately as usage.cost_details.upstream_inference_cost. The two are disjoint, so the gateway records their sum: both numbers left your accounts.

Aborted streams are not reconciled

The cost arrives in the final chunk of a stream, so a client that disconnects before it leaves the request unresolved at $0 in your usage, even though OpenRouter charged for the tokens generated up to the disconnect. Watch the unresolved count on OpenRouter providers, and set per-user limits on the apps that route through them. Those bound how much can go unmeasured before you notice.

OpenRouter providers accept chat completions only, at v1/chat/completions. OpenRouter does serve other APIs, but only its chat-completions response reports a cost, and a request the gateway could not account for is refused with 403 api_style_not_supported rather than served for free.

One request-shaping detail, invisible to your client's SDK: the gateway asks OpenRouter, with a header, to name the endpoint it routed to. Your request body is forwarded byte for byte. That answer is stored as served_provider (shown as Served by in the app's usage view), along with served_model, and credential_source: "byok" when the response says the inference was paid for with your own upstream key. All three are absent when OpenRouter does not say. See Usage.

On this page