> ## Documentation Index
> Fetch the complete documentation index at: https://hobbyist-e43fa225.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# How to use structured outputs with Azure OpenAI in Microsoft Foundry Models

> Learn how to improve your model responses with structured outputs

export const ZonePivot = ({group, options = [], defaultValue, label = "Choose an experience"}) => {
  const values = options.map(option => option.id);
  const optionKey = options.map(option => `${option.id}:${option.title}`).join("|");
  const [activePivot, setActivePivot] = useState(defaultValue || values[0]);
  const slugify = value => value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
  const resolvePivot = () => {
    if (typeof window === "undefined") return defaultValue || values[0];
    const params = new URLSearchParams(window.location.search);
    const requested = params.get("pivots");
    if (requested) {
      const requestedIds = requested.split(",").map(value => value.trim()).filter(Boolean);
      const match = requestedIds.find(id => values.includes(id));
      if (match) return match;
    }
    const hash = window.location.hash.replace(/^#/, "");
    if (hash) {
      const match = options.find(option => option.id === hash || slugify(option.title) === hash);
      if (match) return match.id;
    }
    try {
      const stored = window.localStorage.getItem(`foundry-zone-pivot:${group}`);
      if (values.includes(stored)) return stored;
    } catch {
      return defaultValue || values[0];
    }
    return defaultValue || values[0];
  };
  const publishPivotChange = value => {
    if (typeof window === "undefined") return;
    window.dispatchEvent(new CustomEvent("foundry-zone-pivot-change", {
      detail: {
        group,
        value
      }
    }));
  };
  const syncTableOfContents = () => {
    if (typeof window === "undefined") return;
    window.requestAnimationFrame(() => {
      const toc = document.getElementById("table-of-contents-content");
      if (!toc) return;
      const links = Array.from(toc.querySelectorAll('a[href^="#"]'));
      for (const link of links) {
        const item = link.closest("li");
        const rawId = link.getAttribute("href")?.slice(1);
        if (!item || !rawId) continue;
        let id = rawId;
        try {
          id = decodeURIComponent(rawId);
        } catch {}
        item.style.display = document.getElementById(id) ? "" : "none";
      }
    });
  };
  useEffect(() => {
    const resolvedPivot = resolvePivot();
    setActivePivot(resolvedPivot);
    publishPivotChange(resolvedPivot);
    window.setTimeout(syncTableOfContents, 0);
  }, [group, defaultValue, values.join("|"), optionKey]);
  const selectPivot = value => {
    setActivePivot(value);
    if (typeof window !== "undefined") {
      try {
        window.localStorage.setItem(`foundry-zone-pivot:${group}`, value);
      } catch {}
      const url = new URL(window.location.href);
      const current = url.searchParams.get("pivots");
      const preserved = current ? current.split(",").map(id => id.trim()).filter(id => id && !values.includes(id)) : [];
      url.searchParams.set("pivots", [...preserved, value].join(","));
      window.history.replaceState(null, "", `${url.pathname}${url.search}${url.hash}`);
    }
    publishPivotChange(value);
    window.setTimeout(syncTableOfContents, 0);
  };
  if (options.length < 2) return null;
  return <div className="not-prose my-6 border-b border-slate-200 pb-3 dark:border-slate-800">
      <div className="mb-2 text-xs font-semibold uppercase tracking-wide text-slate-500 dark:text-slate-400">
        {label}
      </div>
      <div className="flex flex-wrap gap-2" role="tablist" aria-label={label}>
        {options.map(option => {
    const selected = option.id === activePivot;
    return <button key={option.id} type="button" role="tab" aria-selected={selected} onClick={() => selectPivot(option.id)} className={`rounded-md border px-3 py-1.5 text-sm font-medium transition ${selected ? "border-slate-900 bg-slate-900 text-white shadow-sm dark:border-slate-100 dark:bg-slate-100 dark:text-slate-950" : "border-slate-200 bg-white text-slate-700 hover:border-slate-400 hover:text-slate-950 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-200 dark:hover:border-slate-500"}`}>
              {option.title}
            </button>;
  })}
      </div>
    </div>;
};

export const ZoneContent = ({group, value, options = [], values = [], defaultValue, children}) => {
  const optionKey = options.map(option => `${option.id}:${option.title}`).join("|");
  const [activePivot, setActivePivot] = useState(defaultValue || values[0]);
  const slugify = value => value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
  const resolvePivot = () => {
    if (typeof window === "undefined") return defaultValue || values[0];
    const params = new URLSearchParams(window.location.search);
    const requested = params.get("pivots");
    if (requested) {
      const requestedIds = requested.split(",").map(value => value.trim()).filter(Boolean);
      const match = requestedIds.find(id => values.includes(id));
      if (match) return match;
    }
    const hash = window.location.hash.replace(/^#/, "");
    if (hash) {
      const match = options.find(option => option.id === hash || slugify(option.title) === hash);
      if (match) return match.id;
    }
    try {
      const stored = window.localStorage.getItem(`foundry-zone-pivot:${group}`);
      if (values.includes(stored)) return stored;
    } catch {
      return defaultValue || values[0];
    }
    return defaultValue || values[0];
  };
  useEffect(() => {
    setActivePivot(resolvePivot());
  }, [group, defaultValue, values.join("|"), optionKey]);
  useEffect(() => {
    const onPivotChange = event => {
      if (event.detail?.group === group && values.includes(event.detail.value)) {
        setActivePivot(event.detail.value);
      }
    };
    window.addEventListener("foundry-zone-pivot-change", onPivotChange);
    return () => window.removeEventListener("foundry-zone-pivot-change", onPivotChange);
  }, [group, values.join("|")]);
  if (activePivot !== value) return null;
  return <>{children}</>;
};

Structured outputs make a model follow a [JSON Schema](https://json-schema.org/overview/what-is-jsonschema) definition that you provide as part of your inference API call. This approach contrasts with the older [JSON mode](/models/json-mode) feature, which guaranteed valid JSON but couldn't ensure strict adherence to the supplied schema. Use structured outputs for function calling, extracting structured data, and building complex multi-step workflows.

<ZonePivot group="programming-language-csharp__programming-language-python__programming-language-rest" options={[{"id": "programming-language-python", "title": "Python"}, {"id": "programming-language-csharp", "title": "C#"}, {"id": "programming-language-rest", "title": "REST"}]} defaultValue="programming-language-python" />

<ZoneContent group="programming-language-csharp__programming-language-python__programming-language-rest" value="programming-language-python" options={[{"id": "programming-language-python", "title": "Python"}, {"id": "programming-language-csharp", "title": "C#"}, {"id": "programming-language-rest", "title": "REST"}]} values={["programming-language-python", "programming-language-csharp", "programming-language-rest"]} defaultValue="programming-language-python">
  ## Getting started

  <Tabs>
    <Tab title="Python (Microsoft Entra ID)">
      You can use [`Pydantic`](https://docs.pydantic.dev/latest/) to define object schemas in Python. Depending on what version of the [OpenAI](https://pypi.org/project/openai/) and [`Pydantic` libraries](https://pypi.org/project/pydantic/) you're running you might need to upgrade to a newer version. These examples were tested against `openai 1.42.0` and `pydantic 2.8.2`.

      ```cmd theme={null}
      pip install openai pydantic azure-identity --upgrade
      ```

      If you are new to using Microsoft Entra ID for authentication see [How to configure Azure OpenAI in Microsoft Foundry Models with Microsoft Entra ID authentication](https://learn.microsoft.com/en-us/azure/foundry-classic/openai/how-to/managed-identity).

      ```python theme={null}
      from pydantic import BaseModel
      from openai import OpenAI
      from azure.identity import DefaultAzureCredential, get_bearer_token_provider

      token_provider = get_bearer_token_provider(
          DefaultAzureCredential(), "https://ai.azure.com/.default"
      )

      client = OpenAI(  
        base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
        api_key=token_provider,
      )

      class CalendarEvent(BaseModel):
          name: str
          date: str
          participants: list[str]

      completion = client.beta.chat.completions.parse(
          model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
          messages=[
              {"role": "system", "content": "Extract the event information."},
              {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
          ],
          response_format=CalendarEvent,
      )

      event = completion.choices[0].message.parsed

      print(event)
      print(completion.model_dump_json(indent=2))
      ```

      ### Output

      ```json theme={null}
      name='Science Fair' date='Friday' participants=['Alice', 'Bob']
      {
        "id": "chatcmpl-A1EUP2fAmL4SeB1lVMinwM7I2vcqG",
        "choices": [
          {
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null,
            "message": {
              "content": "{\n  \"name\": \"Science Fair\",\n  \"date\": \"Friday\",\n  \"participants\": [\"Alice\", \"Bob\"]\n}",
              "refusal": null,
              "role": "assistant",
              "function_call": null,
              "tool_calls": [],
              "parsed": {
                "name": "Science Fair",
                "date": "Friday",
                "participants": [
                  "Alice",
                  "Bob"
                ]
              }
            }
          }
        ],
        "created": 1724857389,
        "model": "gpt-4o-2024-08-06",
        "object": "chat.completion",
        "service_tier": null,
        "system_fingerprint": "fp_1c2eaec9fe",
        "usage": {
          "completion_tokens": 27,
          "prompt_tokens": 32,
          "total_tokens": 59
        }
      }
      ```
    </Tab>

    <Tab title="Python (key-based auth)">
      You can use [`Pydantic`](https://docs.pydantic.dev/latest/) to define object schemas in Python. Depending on what version of the [OpenAI](https://pypi.org/project/openai/) and [`Pydantic` libraries](https://pypi.org/project/pydantic/) you're running you might need to upgrade to a newer version. These examples were tested against `openai 1.42.0` and `pydantic 2.8.2`.

      ```cmd theme={null}
      pip install openai pydantic --upgrade
      ```

      ```python theme={null}
      import os
      from pydantic import BaseModel
      from openai import OpenAI

      client = OpenAI(
        base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
        api_key=os.getenv("AZURE_OPENAI_API_KEY")  
      )

      class CalendarEvent(BaseModel):
          name: str
          date: str
          participants: list[str]

      completion = client.beta.chat.completions.parse(
          model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
          messages=[
              {"role": "system", "content": "Extract the event information."},
              {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
          ],
          response_format=CalendarEvent,
      )

      event = completion.choices[0].message.parsed

      print(event)
      print(completion.model_dump_json(indent=2))
      ```

      ### Output

      ```json theme={null}
      name='Science Fair' date='Friday' participants=['Alice', 'Bob']
      {
        "id": "chatcmpl-A1EUP2fAmL4SeB1lVMinwM7I2vcqG",
        "choices": [
          {
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null,
            "message": {
              "content": "{\n  \"name\": \"Science Fair\",\n  \"date\": \"Friday\",\n  \"participants\": [\"Alice\", \"Bob\"]\n}",
              "refusal": null,
              "role": "assistant",
              "function_call": null,
              "tool_calls": [],
              "parsed": {
                "name": "Science Fair",
                "date": "Friday",
                "participants": [
                  "Alice",
                  "Bob"
                ]
              }
            }
          }
        ],
        "created": 1724857389,
        "model": "gpt-4o-2024-08-06",
        "object": "chat.completion",
        "service_tier": null,
        "system_fingerprint": "fp_1c2eaec9fe",
        "usage": {
          "completion_tokens": 27,
          "prompt_tokens": 32,
          "total_tokens": 59
        }
      }
      ```
    </Tab>
  </Tabs>

  ## Function calling with structured outputs

  Structured Outputs for function calling can be enabled with a single parameter, by supplying `strict: true`.

  <Note>
    Structured outputs are not supported with parallel function calls. When using structured outputs set `parallel_tool_calls` to `false`.
  </Note>

  <CodeGroup>
    ```python Python (Microsoft Entra ID) theme={null}
        import openai
        from pydantic import BaseModel
        from openai import OpenAI
        from azure.identity import DefaultAzureCredential, get_bearer_token_provider

        token_provider = get_bearer_token_provider(
            DefaultAzureCredential(), "https://ai.azure.com/.default"
        )

        client = OpenAI(  
          base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
          api_key=token_provider,
        )

        class GetDeliveryDate(BaseModel):
            order_id: str

        tools = [openai.pydantic_function_tool(GetDeliveryDate)]

        messages = []
        messages.append({"role": "system", "content": "You are a helpful customer support assistant. Use the supplied tools to assist the user."})
        messages.append({"role": "user", "content": "Hi, can you tell me the delivery date for my order #12345?"}) 

        response = client.chat.completions.create(
            model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
            messages=messages,
            tools=tools
        )

        print(response.choices[0].message.tool_calls[0].function)
        print(response.model_dump_json(indent=2))
    ```

    ```python Python (key-based auth) theme={null}
        import os
        from pydantic import BaseModel
        import openai
        from openai import OpenAI

        client = OpenAI(
          base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
          api_key=os.getenv("AZURE_OPENAI_API_KEY")  
        )

        class GetDeliveryDate(BaseModel):
            order_id: str

        tools = [openai.pydantic_function_tool(GetDeliveryDate)]

        messages = []
        messages.append({"role": "system", "content": "You are a helpful customer support assistant. Use the supplied tools to assist the user."})
        messages.append({"role": "user", "content": "Hi, can you tell me the delivery date for my order #12345?"}) 

        response = client.chat.completions.create(
            model="MODEL_DEPLOYMENT_NAME", # replace with the model deployment name of your gpt-4o 2024-08-06 deployment
            messages=messages,
            tools=tools
        )

        print(response.choices[0].message.tool_calls[0].function)
        print(response.model_dump_json(indent=2))
    ```
  </CodeGroup>
</ZoneContent>

<ZoneContent group="programming-language-csharp__programming-language-python__programming-language-rest" value="programming-language-csharp" options={[{"id": "programming-language-python", "title": "Python"}, {"id": "programming-language-csharp", "title": "C#"}, {"id": "programming-language-rest", "title": "REST"}]} values={["programming-language-python", "programming-language-csharp", "programming-language-rest"]} defaultValue="programming-language-python">
  ## Getting started

  Add the following packages to your project:

  * **[OpenAI](https://www.nuget.org/packages/OpenAI)**: Standard OpenAI .NET library.
  * **[Azure.Identity](https://www.nuget.org/packages/Azure.Identity)**: Provides Microsoft Entra ID token authentication support across the Azure SDK libraries.

  ```dotnetcli theme={null}
  dotnet add package OpenAI
  dotnet add package Azure.Identity
  ```

  <Tabs>
    <Tab title="Microsoft Entra ID">
      If you're new to using Microsoft Entra ID for authentication see [How to configure Azure OpenAI in Microsoft Foundry Models with Microsoft Entra ID authentication](https://learn.microsoft.com/en-us/azure/foundry-classic/openai/how-to/managed-identity).

      ```csharp theme={null}
      using Azure.Identity;
      using OpenAI;
      using OpenAI.Chat;
      using System.ClientModel.Primitives;
      using System.Text.Json;

      #pragma warning disable OPENAI001

      BearerTokenPolicy tokenPolicy = new(
          new DefaultAzureCredential(),
          "https://ai.azure.com/.default");

      ChatClient client = new(
          model: "gpt-4.1",
          authenticationPolicy: tokenPolicy,
          options: new OpenAIClientOptions()
          {
              Endpoint = new Uri("https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1")
          }
      );

      ChatCompletionOptions options = new()
      {
          ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
              jsonSchemaFormatName: "math_reasoning",
              jsonSchema: BinaryData.FromBytes("""
                  {
                      "type": "object",
                      "properties": {
                          "steps": {
                              "type": "array",
                              "items": {
                                  "type": "object",
                                  "properties": {
                                      "explanation": { "type": "string" },
                                      "output": { "type": "string" }
                                  },
                                  "required": ["explanation", "output"],
                                  "additionalProperties": false
                              }
                          },
                          "final_answer": { "type": "string" }
                      },
                      "required": ["steps", "final_answer"],
                      "additionalProperties": false
                  }
                  """u8.ToArray()),
              jsonSchemaIsStrict: true)
      };

      // Create a list of ChatMessage objects
      ChatCompletion completion = client.CompleteChat(
          [
              new UserChatMessage("How can I solve 8x + 7 = -23?")
          ],
          options);

      using JsonDocument structuredJson = JsonDocument.Parse(completion.Content[0].Text);

      Console.WriteLine($"Final answer: {structuredJson.RootElement.GetProperty("final_answer")}");
      Console.WriteLine("Reasoning steps:");

      foreach (JsonElement stepElement in structuredJson.RootElement.GetProperty("steps").EnumerateArray())
      {
          Console.WriteLine($"  - Explanation: {stepElement.GetProperty("explanation")}");
          Console.WriteLine($"    Output: {stepElement.GetProperty("output")}");
      }
      ```
    </Tab>

    <Tab title="API Key">
      ```csharp theme={null}

      using OpenAI;
      using OpenAI.Chat;
      using System.ClientModel;
      using System.Text.Json;

      string keyFromEnvironment = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY");

      ChatClient client = new(
          model: "gpt-4o-mini",
          credential: new ApiKeyCredential(keyFromEnvironment),
          options: new OpenAIClientOptions() { 
              Endpoint = new Uri("https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1")
          }
      );

      ChatCompletionOptions options = new()
      {
          ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
              jsonSchemaFormatName: "math_reasoning",
              jsonSchema: BinaryData.FromBytes("""
                  {
                      "type": "object",
                      "properties": {
                          "steps": {
                              "type": "array",
                              "items": {
                                  "type": "object",
                                  "properties": {
                                      "explanation": { "type": "string" },
                                      "output": { "type": "string" }
                                  },
                                  "required": ["explanation", "output"],
                                  "additionalProperties": false
                              }
                          },
                          "final_answer": { "type": "string" }
                      },
                      "required": ["steps", "final_answer"],
                      "additionalProperties": false
                  }
                  """u8.ToArray()),
              jsonSchemaIsStrict: true)
      };

      // Create a list of ChatMessage objects
      ChatCompletion completion = client.CompleteChat(
          [
              new UserChatMessage("How can I solve 8x + 7 = -23?")
          ],
          options);

      using JsonDocument structuredJson = JsonDocument.Parse(completion.Content[0].Text);

      Console.WriteLine($"Final answer: {structuredJson.RootElement.GetProperty("final_answer")}");
      Console.WriteLine("Reasoning steps:");

      foreach (JsonElement stepElement in structuredJson.RootElement.GetProperty("steps").EnumerateArray())
      {
          Console.WriteLine($"  - Explanation: {stepElement.GetProperty("explanation")}");
          Console.WriteLine($"    Output: {stepElement.GetProperty("output")}");
      }

      ```
    </Tab>
  </Tabs>
</ZoneContent>

<ZoneContent group="programming-language-csharp__programming-language-python__programming-language-rest" value="programming-language-rest" options={[{"id": "programming-language-python", "title": "Python"}, {"id": "programming-language-csharp", "title": "C#"}, {"id": "programming-language-rest", "title": "REST"}]} values={["programming-language-python", "programming-language-csharp", "programming-language-rest"]} defaultValue="programming-language-python">
  ## Getting started

  `response_format` is set to `json_schema` with `strict: true` set.

  ```bash theme={null}
  curl -X POST  https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1/chat/completions \
    -H "api-key: $AZURE_OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
      -d '{
          "model": "YOUR_MODEL_DEPLOYMENT_NAME",
          "messages": [
                  {"role": "system", "content": "Extract the event information."},
                  {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."}
              ],
              "response_format": {
                  "type": "json_schema",
                  "json_schema": {
                      "name": "CalendarEventResponse",
                      "strict": true,
                      "schema": {
                          "type": "object",
                          "properties": {
                              "name": {
                                "type": "string"
                              },
                              "date": {
                                  "type": "string"
                              },
                              "participants": {
                                  "type": "array",
                                  "items": {
                                      "type": "string"
                                  }
                              }
                          },
                          "required": [
                              "name",
                              "date",
                              "participants"
                          ],
                          "additionalProperties": false
                      }
                  }
            }
    }'
  ```

  Output:

  ```json theme={null}
  {
    "id": "chatcmpl-A1HKsHAe2hH9MEooYslRn9UmEwsag",
    "object": "chat.completion",
    "created": 1724868330,
    "model": "gpt-4o-2024-08-06",
    "choices": [
      {
        "index": 0,
        "message": {
          "role": "assistant",
          "content": "{\n  \"name\": \"Science Fair\",\n  \"date\": \"Friday\",\n  \"participants\": [\"Alice\", \"Bob\"]\n}"
        },
        "logprobs": null,
        "finish_reason": "stop"
      }
    ],
    "usage": {
      "prompt_tokens": 33,
      "completion_tokens": 27,
      "total_tokens": 60
    },
    "system_fingerprint": "fp_1c2eaec9fe"
  }

  ```

  ## Function calling with structured outputs

  ```bash theme={null}
  curl -X POST  https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1/chat/completions \
    -H "api-key: $AZURE_OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
    "model": "YOUR_MODEL_DEPLOYMENT_NAME",
    "messages": [
      {
        "role": "system",
        "content": "You are a helpful assistant. The current date is August 6, 2024. You help users query for the data they are looking for by calling the query function."
      },
      {
        "role": "user",
        "content": "look up all my orders in may of last year that were fulfilled but not delivered on time"
      }
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "query",
          "description": "Execute a query.",
          "strict": true,
          "parameters": {
            "type": "object",
            "properties": {
              "table_name": {
                "type": "string",
                "enum": ["orders"]
              },
              "columns": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "id",
                    "status",
                    "expected_delivery_date",
                    "delivered_at",
                    "shipped_at",
                    "ordered_at",
                    "canceled_at"
                  ]
                }
              },
              "conditions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "column": {
                      "type": "string"
                    },
                    "operator": {
                      "type": "string",
                      "enum": ["=", ">", "<", ">=", "<=", "!="]
                    },
                    "value": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "column_name": {
                              "type": "string"
                            }
                          },
                          "required": ["column_name"],
                          "additionalProperties": false
                        }
                      ]
                    }
                  },
                  "required": ["column", "operator", "value"],
                  "additionalProperties": false
                }
              },
              "order_by": {
                "type": "string",
                "enum": ["asc", "desc"]
              }
            },
            "required": ["table_name", "columns", "conditions", "order_by"],
            "additionalProperties": false
          }
        }
      }
    ]
  }'
  ```
</ZoneContent>

## JSON Schema support and limitations

Azure OpenAI structured outputs support the same subset of the [JSON Schema](https://json-schema.org/docs) as OpenAI.

### Supported types

* String
* Number
* Boolean
* Integer
* Object
* Array
* Enum
* anyOf

<Note>
  Root objects can't be the `anyOf` type.
</Note>

### All fields must be required

Include all fields or function parameters as required. In the following example, both `location` and `unit` appear under `"required": ["location", "unit"]`.

```json theme={null}
{
    "name": "get_weather",
    "description": "Fetches the weather in the given location",
    "strict": true,
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location to get the weather for"
            },
            "unit": {
                "type": "string",
                "description": "The unit to return the temperature in",
                "enum": ["F", "C"]
            }
        },
        "additionalProperties": false,
        "required": ["location", "unit"]
    }
}
```

If needed, you can emulate an optional parameter by using a union type with `null`. In this example, this approach is represented by the line `"type": ["string", "null"],`.

```json theme={null}
{
    "name": "get_weather",
    "description": "Fetches the weather in the given location",
    "strict": true,
    "parameters": {
        "type": "object",
        "properties": {
            "location": {
                "type": "string",
                "description": "The location to get the weather for"
            },
            "unit": {
                "type": ["string", "null"],
                "description": "The unit to return the temperature in",
                "enum": ["F", "C"]
            }
        },
        "additionalProperties": false,
        "required": [
            "location", "unit"
        ]
    }
}
```

### Nesting depth

A schema can have up to 100 object properties total, with up to five levels of nesting.

### Always set `additionalProperties: false` in objects

This property controls if an object can have other key value pairs that weren't defined in the JSON Schema. To use structured outputs, set this value to false.

### Key ordering

Structured outputs follow the same order as the provided schema. To change the output order, modify the order of the schema that you send as part of your inference request.

### Unsupported type-specific keywords

| Type    | Unsupported Keyword                                                                                                     |
| ------- | ----------------------------------------------------------------------------------------------------------------------- |
| String  | minlength<br /> maxLength<br /> pattern<br /> format                                                                    |
| Number  | minimum<br /> maximum<br /> multipleOf                                                                                  |
| Objects | patternProperties<br /> unevaluatedProperties<br /> propertyNames<br /> minProperties<br /> maxProperties               |
| Arrays  | unevaluatedItems <br /> contains <br /> minContains <br /> maxContains <br /> minItems<br /> maxItems<br /> uniqueItems |

### Nested schemas using anyOf must adhere to the overall JSON Schema subset

Example supported `anyOf` schema:

```json theme={null}
{
    "type": "object",
    "properties": {
        "item": {
            "anyOf": [
                {
                    "type": "object",
                    "description": "The user object to insert into the database",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "The name of the user"
                        },
                        "age": {
                            "type": "number",
                            "description": "The age of the user"
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "name",
                        "age"
                    ]
                },
                {
                    "type": "object",
                    "description": "The address object to insert into the database",
                    "properties": {
                        "number": {
                            "type": "string",
                            "description": "The number of the address. Eg. for 123 main st, this would be 123"
                        },
                        "street": {
                            "type": "string",
                            "description": "The street name. Eg. for 123 main st, this would be main st"
                        },
                        "city": {
                            "type": "string",
                            "description": "The city of the address"
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "number",
                        "street",
                        "city"
                    ]
                }
            ]
        }
    },
    "additionalProperties": false,
    "required": [
        "item"
    ]
}
```

### Definitions are supported

Supported example:

```json theme={null}
{
    "type": "object",
    "properties": {
        "steps": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/step"
            }
        },
        "final_answer": {
            "type": "string"
        }
    },
    "$defs": {
        "step": {
            "type": "object",
            "properties": {
                "explanation": {
                    "type": "string"
                },
                "output": {
                    "type": "string"
                }
            },
            "required": [
                "explanation",
                "output"
            ],
            "additionalProperties": false
        }
    },
    "required": [
        "steps",
        "final_answer"
    ],
    "additionalProperties": false
}
```

### Recursive schemas are supported

Example using `#` for root recursion:

```json theme={null}
{
        "name": "ui",
        "description": "Dynamically generated UI",
        "strict": true,
        "schema": {
            "type": "object",
            "properties": {
                "type": {
                    "type": "string",
                    "description": "The type of the UI component",
                    "enum": ["div", "button", "header", "section", "field", "form"]
                },
                "label": {
                    "type": "string",
                    "description": "The label of the UI component, used for buttons or form fields"
                },
                "children": {
                    "type": "array",
                    "description": "Nested UI components",
                    "items": {
                        "$ref": "#"
                    }
                },
                "attributes": {
                    "type": "array",
                    "description": "Arbitrary attributes for the UI component, suitable for any element",
                    "items": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string",
                                "description": "The name of the attribute, for example onClick or className"
                            },
                            "value": {
                                "type": "string",
                                "description": "The value of the attribute"
                            }
                        },
                      "additionalProperties": false,
                      "required": ["name", "value"]
                    }
                }
            },
            "required": ["type", "label", "children", "attributes"],
            "additionalProperties": false
        }
    }
```

Example of explicit recursion:

```json theme={null}
{
    "type": "object",
    "properties": {
        "linked_list": {
            "$ref": "#/$defs/linked_list_node"
        }
    },
    "$defs": {
        "linked_list_node": {
            "type": "object",
            "properties": {
                "value": {
                    "type": "number"
                },
                "next": {
                    "anyOf": [
                        {
                            "$ref": "#/$defs/linked_list_node"
                        },
                        {
                            "type": "null"
                        }
                    ]
                }
            },
            "additionalProperties": false,
            "required": [
                "next",
                "value"
            ]
        }
    },
    "additionalProperties": false,
    "required": [
        "linked_list"
    ]
}
```

<Note>
  Currently, structured outputs aren't supported with:

  * [Bring your own data](https://learn.microsoft.com/en-us/azure/foundry-classic/openai/concepts/use-your-data) scenarios.
  * [Assistants](https://learn.microsoft.com/en-us/azure/foundry-classic/openai/how-to/assistant) or [Foundry Agents Service](/agents/overview).
  * `gpt-4o-audio-preview` and `gpt-4o-mini-audio-preview` version: `2024-12-17`.
</Note>

## Supported models

* `gpt-5.1-codex` version: `2025-11-13`
* `gpt-5.1-codex mini` version: `2025-11-13`
* `gpt-5.1` version: `2025-11-13`
* `gpt-5.1-chat` version: `2025-11-13`
* `gpt-5-pro` version `2025-10-06`
* `gpt-5-codex` version `2025-09-11`
* `gpt-5` version `2025-08-07`
* `gpt-5-mini` version `2025-08-07`
* `gpt-5-nano` version `2025-08-07`
* `codex-mini` version `2025-05-16`
* `o3-pro` version `2025-06-10`
* `o3-mini` version `2025-01-31`
* `o1` version: `2024-12-17`
* `gpt-4o-mini` version: `2024-07-18`
* `gpt-4o` version: `2024-08-06`
* `gpt-4o` version: `2024-11-20`
* `gpt-4.1` version `2025-04-14`
* `gpt-4.1-nano` version `2025-04-14`
* `gpt-4.1-mini` version: `2025-04-14`
* `o4-mini` version: `2025-04-16`
* `o3` version: `2025-04-16`

## API support

API version `2024-08-01-preview` is the first version that supports structured outputs. The latest preview APIs and the latest GA API, `v1`, also support structured outputs.
