Using Azure AI
Azure AI serves models from your own Azure resource through one provider configuration—one resource endpoint and one resource key. Adding it gives your apps the models you have deployed, through the Universal API, on your Azure subscription and Azure billing.
One provider type covers both kinds of Azure resource:
- An Azure OpenAI resource deploys OpenAI models and serves them on an OpenAI-compatible API.
- A Microsoft Foundry resource serves that same API for every Foundry model family—Grok, DeepSeek, Llama, Mistral, Phi, Kimi and more—and serves Claude on the native Anthropic Messages API.
Apps reference models as providerName/model, where providerName is the name
you give the provider configuration. A provider named azureai serves
azureai/my-gpt.
Azure serves deployments, not model names
Of the ways Azure differs from other providers, this is the one that changes
what you put in the model field.
Other providers accept a published model ID. Azure resolves the model field
against the deployments in your resource, and you choose deployment names
when you create them. If you deploy gpt-4.1-mini under the name my-gpt, then
my-gpt is the only name Azure accepts for it.
The gateway forwards your deployment name to Azure unchanged, because it's the only address Azure answers to. What the gateway needs to know separately is which catalog model each deployment serves—that's what prices your usage.
An unmapped deployment is rejected
The gateway prices a request by looking up the model name in its catalog. A
deployment named after something outside the catalog, such as my-gpt, matches
nothing—so the gateway returns 400 rather than serving a request it can't
bill. Azure would have served it, and the usage would have recorded no cost.
Map every deployment whose name differs from the model it serves. You do this when you add or edit the provider. The error names the deployment and lists the names that do work.
Mapping is optional when it isn't needed. Deploy gpt-4.1-mini under the name
gpt-4.1-mini—the Azure portal's own default—and it already matches the
catalog.
Deployment name rules
Azure accepts 2 to 64 characters of letters, digits, hyphens, underscores and periods, and won't accept a name ending in a period. Leading hyphens and periods, doubled periods, trailing hyphens and uppercase letters are all fine.
Deployment names match case-insensitively, so a deployment named MyGpt answers
to mygpt, and one named my-gpt answers to MY-GPT. Map each deployment once
using whichever spelling you prefer; requests in any casing resolve to it.
How the gateway routes Azure AI models
A Foundry resource serves two API formats on the same host with the same resource key:
- An OpenAI-compatible API at
/openai/v1, serving every non-Claude model. - The native Anthropic Messages API at
/anthropic/v1/messages, serving the Claude models.
The gateway's model catalog records which API serves each model, and routes every request accordingly. Your clients always call your app's URL and never see the Azure endpoint.
Claude needs a Foundry resource, because an Azure OpenAI resource can't deploy Claude at all. Which endpoint host you configure doesn't affect this—a Foundry resource serves Claude on either host family the provider accepts.
Supported endpoints
| Endpoint | OpenAI-compatible models | Claude models |
|---|---|---|
/v1/chat/completions | ✅ Forwarded | ✅ Translated |
/v1/embeddings | ✅ Embedding models | ❌ |
/v1/messages | ❌ | ✅ Forwarded |
/v1/responses | ✅ Models that serve it | ❌ |
Forwarded means the gateway sends your request on in the shape you wrote it. Translated means it converts between two API shapes, which limits you to the parameters listed below.
Streaming (stream: true) works on chat completions, messages, and responses.
The catalog carries three embedding models—text-embedding-3-small,
text-embedding-3-large and text-embedding-ada-002—so /v1/embeddings works
once you deploy one of them and map your deployment to it.
/v1/responses serves the OpenAI Responses API, buffered and streaming. Support
is per deployed model, not per resource: Azure serves Responses for
particular model and version combinations, and a deployment outside that set
answers 400 with The requested operation is unsupported—which is what an
embedding deployment on this endpoint returns. Check Azure's own Responses API
model list for your model and version before relying on it.
The management operations on a stored response are forwarded too:
| Operation | Does |
|---|---|
GET /v1/responses/{id} | Retrieves the response |
GET /v1/responses/{id}/input_items | Lists the input items of one response |
DELETE /v1/responses/{id} | Deletes the response |
Two things they need. Send store: true on the create, since your resource
serves them only for a response it kept. And because these requests carry no
body, there is no model in them for the gateway to route on—it uses the app's
first configured completions model instead, so the app needs a
Model Filtering policy
whose completions allow list starts with an OpenAI-compatible Azure
deployment. Without one the gateway answers 400, asking for preselected
routing, before reaching Azure.
A Claude deployment doesn't work in that first slot, even though the allow list accepts it—Claude doesn't serve Responses at all, so the request still fails.
Azure also takes a moment to make a new response readable. A GET immediately
after a create can return 404 before it settles, so retry rather than treating
the first 404 as final.
Claude deployments don't serve Responses, so a Claude model on this endpoint
fails with a 400 error—use
/v1/messages for those.
Claude models work on /v1/chat/completions through the gateway's translation
to the Messages API, which supports the core chat parameters: messages,
max_tokens, temperature, top_p, stop, and stream. For tool use or
other Anthropic-specific features, call
/v1/messages instead.
This is the gateway's standard handling for Claude, not something specific to
Azure—Bedrock Mantle
serves Claude the same way. You get an ordinary chat.completion object back,
with choices and prompt_tokens/completion_tokens. The one visible trace of
the conversion is the response id, which keeps Anthropic's msg_ prefix.
Azure's OpenAI-compatible models are forwarded instead of translated, so their
responses carry Azure's own fields, such as content_filter_results.
Before you begin
You need:
- An Azure subscription with an Azure OpenAI or Microsoft Foundry resource. Note the resource name—it's the first label of the resource's endpoint host.
- At least one model deployed in that resource, and its deployment name. The gateway addresses deployments, so a resource with no deployments serves nothing. Deploy models in the Azure portal under your resource's Model deployments.
- One of the resource's API keys, from the resource's Keys and Endpoint page in the Azure portal.
- An AI Gateway project in the Zuplo Portal.
- An AI Gateway app to call the models from. The app page shows the app's API URL, and its API key lives on the app's API Key tab.
Use a resource key, not a Microsoft Entra ID token. Azure accepts both on its own API, but the gateway stores long-lived resource keys, and the provider dialog rejects a pasted Entra token—those expire within hours.
Deploying Claude on Foundry
Claude deployments carry extra requirements that Azure applies only to them, and the failures are easy to misread:
- Azure asks for your industry, organization name and country when you create an Anthropic-format deployment. Give a plain organization name; punctuation in it has been enough to fail the deployment.
- Azure validates none of it up front. A deployment can report success, spend a few minutes provisioning, and then land in a Failed state with an internal-error message. Check the deployment's provisioning state before you configure the provider, and delete a failed deployment before reusing its name.
- If you deploy through the Azure REST API or a template rather than the portal,
use API version
2025-12-01or later. Earlier versions silently ignore those fields and then reject the request for not providing them.
Add the provider
Adding or editing providers requires the Edit permission, granted to Zuplo account and project Admins—see Managing Providers.
-
Open Settings → AI Providers in your AI Gateway project in the Zuplo Portal.
-
Click the Add Provider button.
-
In the AI Provider list, select Azure AI from the Default Providers group.
-
Review the Provider Name, which fills in as
azureai(a second configuration becomesazureai-2). You can replace it with your own name, but only now—the name is permanent after creation, and it's the prefix in every model reference: a provider namedazureaiservesazureai/my-gpt. -
In Azure Resource Name, enter your resource's name, such as
my-resource. Use the host family selector beside the field to pickopenai.azure.comorservices.ai.azure.com, matching your resource's endpoint. The gateway sends this provider's requests tohttps://<resource>.<host family>. -
In API Key, paste one of the resource's keys.
-
Select the models to enable, or click Select All. The picker shows per-token prices, which the gateway uses to track cost per app. You can change the selection later.
-
Under Deployment Names, click Add deployment for each deployment whose name differs from the model it serves. Enter the deployment name, then pick the model it serves from the list. Skip this for deployments already named after their model.
-
Click Create.
Saving provider settings triggers an automatic production deployment of your gateway, because provider credentials are part of the deployed gateway. The change is live once the deployment completes.
When you edit the provider later—see Managing Providers—the Azure Resource Name, host family and deployment mappings all stay editable, and you can replace the API key. The Provider Name doesn't change.
Which endpoint form to enter
Enter the resource name and pick a host family; don't paste a full URL. The
provider accepts the openai.azure.com and services.ai.azure.com families
only.
A Foundry resource also has a cognitiveservices.azure.com address, and that's
the one the Azure portal shows as the resource's endpoint. It isn't accepted
here—use the resource name with one of the two families above instead. The
resource is the same either way.
Verify the provider
Once the deployment completes, send a chat completions request to your app's Universal API URL—shown at the top of the app page—with the app's API key as the bearer token and one of your deployments:
Code
The URL is a sample—replace it with your app's API URL plus
/v1/chat/completions, set ZUPLO_APP_API_KEY to the app's API key, and
substitute your own deployment name for my-gpt.
A 200 response confirms the provider works. If the request fails immediately
after you save the provider, the deployment may not have finished—retry before
debugging further.
Call OpenAI-compatible models
Use any OpenAI client with your app's URL plus /v1 as the base URL and the
app's API key:
Code
The same call works with a Claude deployment—the gateway translates it to the Messages API—within the translation's parameter subset.
Call Claude models on the Messages API
Claude deployments on a Foundry resource serve the native
Anthropic Messages API at
/v1/messages. With the Anthropic SDK, set baseURL to the app's URL without
/v1—the SDK appends /v1/messages itself—and pass the app's API key as
authToken, not apiKey:
Code
The gateway forwards the request body to Azure verbatim, so tool use, system prompts and streaming work as they do against Anthropic directly.
anthropic-beta headers are the exception. The gateway forwards the
long-context and prompt-caching betas and drops every other value, because Azure
rejects an unrecognized beta by failing the whole request. A client asking for a
different beta still gets an answer, without that feature.
What the model field reports in responses
The model field in a response doesn't always say what you might expect, and
what it says depends on the model you called.
Claude models and /v1/responses report your deployment name. Everything
else reports Azure's own model ID, which usually carries a version date the
short name doesn't.
| Endpoint | Deployment my-gpt / my-embed / my-claude serves | model in the response |
|---|---|---|
/v1/chat/completions | gpt-4.1-mini | gpt-4.1-mini-2025-04-14 |
/v1/responses | gpt-4.1-mini | my-gpt |
/v1/embeddings | text-embedding-3-small | text-embedding-3-small |
/v1/messages | claude-haiku-4-5 | my-claude |
/v1/chat/completions | claude-haiku-4-5 | my-claude |
The same deployment reports two different values depending on the endpoint you call it on: chat completions answers with Azure's dated ID, Responses with the name you gave the deployment. That's Azure's own behavior on each surface, not something the gateway changes.
A Claude model reports your deployment name on both endpoints—the native Messages API and the chat completions translation—but for a different reason: there the gateway builds the response itself and echoes back the model you asked for.
One exception, if you stream Claude: the message_start event reports Azure's
ID (claude-haiku-4-5-20251001) rather than your deployment name, because the
gateway forwards each event as it arrives instead of rebuilding the response. So
the same request reports two different values depending on whether you streamed
it.
Treat this field as informational either way. If you need to know which deployment served a request, use your own request metadata rather than parsing this.
Troubleshooting
A request fails with a deployment-not-found error. The model value after
the provider prefix must be a deployment name in your Azure resource, not a
published model ID. Check the deployment list in the Azure portal under your
resource's Model deployments, and confirm the deployment finished
provisioning.
A request fails saying the deployment isn't mapped. The deployment exists in Azure, but the gateway can't tell which model it serves, so it can't price the request. Edit the provider, add the deployment under Deployment Names, and pick its model. If the deployment is named after its model, selecting that model is enough. The error lists the names that currently work.
The dialog rejects your endpoint. Enter the resource name, not a URL, and
pick openai.azure.com or services.ai.azure.com. A Foundry resource's
cognitiveservices.azure.com address isn't accepted—use the resource name with
one of those two families. Resource names are 2 to 63 characters of lowercase
letters, digits and hyphens, starting and ending with a letter or digit.
The dialog rejects your API key. The gateway takes a resource key from the resource's Keys and Endpoint page. A Microsoft Entra ID access token is rejected—it expires within hours, so the connection would break the same day.
A Claude model returns an error on an Azure OpenAI resource. Only Foundry resources deploy Claude. Confirm the deployment exists and is Anthropic-format, and see Deploying Claude on Foundry for the requirements Azure applies to those deployments.
A 400 error names /v1/responses. Two different causes, and the message
tells you which. If it names the provider or the endpoint, the deployment is a
Claude one—Claude doesn't serve Responses, so call
/v1/messages instead, or
/v1/chat/completions for the translated form. If it says
The requested operation is unsupported, that came from Azure: the deployed
model doesn't serve Responses. Support is per model and version, so check
Azure's Responses API model list—an embedding deployment always fails this way.
A 400 asks for preselected routing. You called GET or DELETE on a
response, or listed its input items. Those requests carry no body, so there is
no model for the gateway to route on and it falls back to the app's first
configured completions model. Add a
Model Filtering policy
to the app with an OpenAI-compatible Azure deployment first in its
completions allow list. A Claude deployment in that slot still fails, since
Claude doesn't serve Responses.
A model in the picker fails at request time. The picker lists the full Azure catalog, but a model only works once you deploy it in your resource, and model availability varies by region and resource kind. Deploy the model, then map your deployment name to it.
Next steps
- AI Providers—the capability matrix across every supported provider.
- Universal API—the endpoints every app serves and how model references work.
- Managing Providers—edit models, keys, and the endpoint, and understand when changes deploy.
- AI Gateway Apps—create the apps that call your Azure-backed models.
- Model Filtering policy—control which models each app can call.