Azure OpenAi generated URL is wrong? (/v1/) added in between
It seems that the generated URL for the Azure OpenAI service is adding a /v1/ in between. If I'm wrong and it has something todo with my config, I'm sorry then please point me to the problem and close the issue.
using opencode version 0.3.110
my custom provider config:
{
"$schema": "https://opencode.ai/config.json",
"model": "Foundry/o3-mini",
"provider": {
"Foundry": {
"npm": "@ai-sdk/azure",
"name": "Foundry",
"options": {
"baseURL": "https://<removed>.openai.azure.com/openai/deployments/o3-mini",
"apiKey": "{env:AZURE_KEY_O3MINI}",
"apiVersion": "2025-01-01-preview"
},
"models": {
"o3-mini": {
"name": "o3-mini"
}
}
}
}
}
Accual used URL
https://removed.openai.azure.com/openai/deployments/o3-mini/v1/chat/completions?api-version=2025-01-01-preview
Expected URL (as by Azure OpenAi
https://removed.openai.azure.com/openai/deployments/o3-mini/chat/completions?api-version=2025-01-01-preview
the error message where you can see that the used url was wrong
{
"error": {
"name": "AI_APICallError",
"url": "https://<removed>.openai.azure.com/openai/deployments/o3-mini/v1/chat/completions?api-version=2025-01-01-preview",
"requestBodyValues": {
"model": "o3-mini",
"max_completion_tokens": 32000,
"messages": [
{
"role": "developer",
"content": "<removed>"
},
{
"role": "developer",
"content": "<removed>"
},
{
"role": "user",
"content": "write bash hello world"
}
],
"tools": ["<removed>"],
"tool_choice": "auto",
"stream": true,
"stream_options": {
"include_usage": true
}
},
"statusCode": 404,
"responseHeaders": {
"apim-request-id": "3b1a9292-9501-4f88-9389-38613332b4e7",
"content-length": "56",
"content-type": "application/json",
"date": "Fri, 01 Aug 2025 12:11:05 GMT",
"strict-transport-security": "max-age=31536000; includeSubDomains; preload",
"x-content-type-options": "nosniff"
},
"responseBody": {
"error": {
"code": "404",
"message": "Resource not found"
}
},
"isRetryable": false,
"data": {
"error": {
"message": "Resource not found",
"code": "404"
}
}
}
}
Azure OpenAi curl example example
curl -X POST "https://<removed>.openai.azure.com/openai/deployments/o3-mini/chat/completions?api-version=2025-01-01-preview \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AZURE_API_KEY" \
-d '{
"messages": [
{
"role": "user",
"content": "I am going to Paris, what should I see?"
}
],
"max_completion_tokens": 100000,
"model": "o3-mini"
}'
To me, it looks like ai-sdk updated to the more current Azure API which includes /v1/ in the path:
https://github.com/vercel/ai/issues/7372
For me, in my opencode/config.json, I changed my "baseURL" from:
"https:<url>/openai/deployments"
to:
"https:<url>/openai/"
I also deleted the apiVersion as it seemed to not be supported now.
No every Azure OpenAI endpoint supports the /v1 - this needs to be optional
ISTM that Azure does not provide great documentation of the new API when you're adding a new deployment.
AFAICT it is mostly possible to exchange the following (i.e. the "old style"):
https://<removed>.openai.azure.com/openai/deployments/<deployment>/chat/completions?api-version=2025-01-01-preview
with
https://<removed>.openai.azure.com/openai/v1/chat/completions?api-version=preview
(The model name should be provided in the json body.)
I tried to create a new model but at the creation process i did not get any opportunity to select the API type also not when i try to edit them after the creation.
after some Microsoft doc digging i found this.
Only a subset of dataplane authoring features are currently supported with the v1 API. A subset of dataplane inference and dataplane authoring features are supported with the v1 preview API.
Azure OpenAI in Azure AI Foundry Models v1 REST API reference
The rest of the article covers our new v1 preview API release of the Azure OpenAI data plane inference specification. Learn more in our API lifecycle guide. If you're looking for documentation on the latest GA API release, refer to the latest GA data plane inference API
Azure OpenAI in Azure AI Foundry Models REST API v1 preview reference
so i guess, "some" party have already adopted the v1 API but i guess mostly there eval and grading endpoints
+1 for making it optional.
In my company we also have endpoints like:
- https://....azure-api.net/openai/deployments/gpt-5/chat/completions?api-version=2025-01-01-preview
and it gets generated by opencode like:
- https://....azure-api.net/openai/deployments/gpt-5/v1/chat/completions?api-version=2025-01-01-preview
I had to add LiteLLM in between with such opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"mycompany": {
"npm": "@ai-sdk/openai-compatible",
"name": "MyCompany Azure OpenAI",
"options": {
"baseURL": "http://0.0.0.0:4000/",
"apiKey": "...",
"headers": {
"api-key": "..."
}
},
"models": {
"mycompany-gpt-5": {
"name": "MyCompany GPT-5"
},
"mycompany-gpt-4.1": {
"name": "MyCompany GPT-4.1"
}
}
}
},
"model": "mycompany/mycompany-gpt-4.1"
}
Can I help providing a fix?
@tbrandenburg I think a fix would be welcome, go ahead
Hej guys,
I found this setting in Vercel's AI SDK: https://github.com/vercel/ai/blob/main/content/providers/01-ai-sdk-providers/04-azure.mdx?plain=1#L89
I would probably go down this way.
Other ideas?
Hej guys,
I found this setting in Vercel's AI SDK: https://github.com/vercel/ai/blob/main/content/providers/01-ai-sdk-providers/04-azure.mdx?plain=1#L89
I would probably go down this way.
Other ideas?
my thoughts: if that could be configurable via the provider configuration in opencode that might be nice, since we will not know when Microsoft decides to switch complete to the new API or old deployments might keep using the old style even after.
Hej guys,
I found this setting in Vercel's AI SDK: https://github.com/vercel/ai/blob/main/content/providers/01-ai-sdk-providers/04-azure.mdx?plain=1#L89
I would probably go down this way.
Other ideas?
This seems to work for chat completions, but not the responses API
Stupid question (currently travelling just with my mobile): Is opencode using the Azure responses API?
@tbrandenburg yes: https://github.com/sst/opencode/blob/40bdbf92a368952812954f512b8ded56fc5cb1dd/packages/opencode/src/provider/provider.ts#L48-L56
Hej guys,
diving deeper I realized that the JSON-options are actually passed to the provider creation method. So I tried running with:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"azure": {
"npm": "@ai-sdk/azure",
"name": "MyCompany Azure OpenAI",
"options": {
"baseURL": "https://mycompany.azure-api.net/openai/",
"useDeploymentBasedUrls": true,
"apiKey": "...",
"apiVersion": "2024-12-01-preview",
"headers": {
"api-key": "..."
}
},
"models": {
"gpt-5": {
"name": "MyCompany GPT-5"
}
}
}
},
"model": "azure/gpt-5"
}
And it worked! 🎉
Out of the logs I could see that the URL used is:
https://mycompany.azure-api.net/openai/deployments/gpt-5/chat/completions?api-version=2024-12-01-preview
I also think that Responses API is supported looking at https://github.com/vercel/ai/blob/main/packages/azure/src/azure-openai-provider.ts#L153.
Can somebody else test as well?
we're not using deployments for the responses API just https://subdomain.openai.azure.com/openai/responses?api-version=2025-03-01-preview - so this does not work either.
worth noting responses api is not available in every region at the time of writing this our internally allowed deployment regions are not in that list.
we're not using deployments for the responses API just https://subdomain.openai.azure.com/openai/responses?api-version=2025-03-01-preview - so this does not work either.
Which results into a contribution to Vercel's SDK and how it is building the URL, right?
using the config flag, changes the url back from v1 to deployments
"useDeploymentBasedUrls": true,
but now i can see that the url that is generated is a "responses" not chat completion
so the newly generated URL is
https://resourcename.cognitiveservices.azure.com/openai/deployments/o4-mini/responses?api-version=2025-01-01-preview
but should be
https://resourcename.cognitiveservices.azure.com/openai/deployments/o4-mini/chat/completions?api-version=2025-01-01-preview
is there another flag i can set in the config to make it aware that the model is chat completion not responses?
not sure if that is the correct code part
opencode/packages/opencode/src/provider/provider.ts
azure: async () => { return { autoload: false, async getModel(sdk: any, modelID: string) { return sdk.responses(modelID) }, options: {}, } },
and if i understand the VercelAI code correctly there should also be the option to load
completion(deploymentId: string): LanguageModelV2;
instead of
responses(deploymentId: string): LanguageModelV2;
so that this should be like that?
opencode/packages/opencode/src/provider/provider.ts
azure: async () => { return { autoload: false, async getModel(sdk: any, modelID: string) { return sdk.completion(modelID) }, options: {}, } },
now if we should have something in the config file that lets us decide if we want/need completion or responses for the model, that might do the trick?
apology if i hallucinate a solution here that might not be as easy as i think
i gave it a try for a fix, feedback would be appreciated. not sure if i got the "correct" solution for the issue, but at least it worked in my tests that the URL is generated correctly and opencode (in the dev Version) was able to use my Azure OpenAi models now.
just wanted to see if there is any update? would my pr be an acceptable solution for the issue ?
I will take a look at it when I get a chance today or tmr, if I don't have feedback for you soon just @ me and i will get to it
currently wrapping up work at my day job but i will have a lot more bandwidth to be able to review and help very soon
added a PR for updating the docs with additional information on azure provider configuration - including the changes made in the PR to this issue.
After spending a couple days poking at this, I managed to get the /deployments/%Model%/chat/completions API working as described in this comment: https://github.com/anomalyco/opencode/issues/1508#issuecomment-3206393616, but due to my company's API deployment not using /v1/responses (just /responses) I was failing to get any of the non-deployment endpoints to work.
Based on the table from this PR updating the documentation, it looks like the only two options directly supported for endpoints are /v1/... or /deployments/..., which tracks with what seems to be the only two options @ai-sdk/azure will give you from createAzure.url shown here.
I eventually managed to solve this with a short custom opencode plugin that just patches the URL before each request on the fly, which seems to work pretty well from my short testing so far. A couple of caveats with this approach:
- It only seems to work if you use the official
azureprovider, I haven't managed to create a custommyproviderthat achieves the same results - Model ID
gpt-5-codexdidn't seem to work, butgpt-5.1-codex,gpt-5.1-codex-mini,gpt-5.1, andgpt-5seem to work fine (these are the only ones I have access to on our instance so that's all I could test) - The custom loader to patch the URLs is only used if you have an entry for the provider in your
~/.config/opencode/auth.jsonfile:
The plugin to patch the urls is just this file placed at ~/.config/opencode/plugin/patch_endpoint.ts:
(I know basically no typescript/javascript, so bear with me here and make suggestions if you have them)
import type { Plugin } from "@opencode-ai/plugin"
export const PatchApiEndpoint: Plugin = async (ctx) => {
return {
auth: {
provider: "azure",
methods: [],
loader: async (_auth, _provider) => {
await ctx.client.app.log({
body: { service: "patch-api-endpoint", level: "info", message: "Loader initialized..." }
})
return {
fetch: async (url: string | URL | Request, init?: RequestInit) => {
const oldUrl = url instanceof Request ? url.url : String(url)
const newUrl = new URL(oldUrl.replace("/v1/responses","/responses"))
ctx.client.app.log({
body: {
service: "patch-api-endpoint",
level: "info",
message: "Patching API Endpoint",
extra: { oldUrl: oldUrl, newUrl: newUrl.toString() },
}
})
return fetch(newUrl.toString(), init)
},
}
},
},
}
}
export default PatchApiEndpoint
~/.local/share/opencode/auth.json:
{
"azure": {
"type": "api",
"key": "file:~/.config/opencode/my_custom_ai.key"
}
~/.config/opencode/opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"enabled_providers": ["azure"],
"share": "disabled",
"autoupdate": "notify",
"provider": {
"azure": {
"name": "MyCustomAI",
"whitelist": ["gpt-5.1-codex", "gpt-5", "gpt-5.1-codex-mini", "gpt-5.1"], // These are the models that seemed to work for me, YMMV
"options": {
"baseURL": "https://api.my_custom_ai.com/openai",
"useDeploymentBasedUrls": false,
"apiVersion": "2025-03-01-preview",
"headers": {
"api-key": "{file:~/.config/opencode/my_custom_ai.key}"
}
}
},
}
}
then after making any request with one of the models I get this in my log file:
$ rg 'oldUrl' 2026-01-07T050321.log
INFO 2026-01-07T05:03:35 +0ms service=patch-api-endpoint oldUrl=https://api.my_custom_ai.com/openai/v1/responses?api-version=2025-03-01-preview newUrl=https://api.my_custom_ai.com/openai/responses?api-version=2025-03-01-preview Patching API Endpoint
INFO 2026-01-07T05:03:35 +0ms service=patch-api-endpoint oldUrl=https://api.my_custom_ai.com/openai/v1/responses?api-version=2025-03-01-preview newUrl=https://api.my_custom_ai.com/openai/responses?api-version=2025-03-01-preview Patching API Endpoint
INFO 2026-01-07T05:03:35 +0ms service=patch-api-endpoint oldUrl=https://api.my_custom_ai.com/openai/v1/responses?api-version=2025-03-01-preview newUrl=https://api.my_custom_ai.com/openai/responses?api-version=2025-03-01-preview Patching API Endpoint
Hope this is helpful to anyone else trying this.