Realtime TTS-2 is live. Built for realtime conversation that feels human. Read the Realtime TTS-2 announcement

Text generation

Structured outputs

Get JSON that matches your schema on Inworld Inference with response_format, see which providers support it, and know how JSON mode differs.

Structured outputs make the model return JSON that follows your JSON Schema. Set response_format on a chat completion. Inworld Inference translates it to the provider's structured output feature.

There are two modes:

Moderesponse_formatWhat you get
Structured outputs{"type": "json_schema", "json_schema": {...}}JSON that follows your schema.
JSON mode{"type": "json_object"}Valid JSON, with no schema. Not available on Anthropic models, which drop it.

Prefer structured outputs. They work on more providers, including Anthropic, and tell the model exactly which fields you expect.

Request a schema

cURL
curl --request POST \
  --url https://api.inworld.ai/v1/chat/completions \
  --header "Authorization: Basic $INWORLD_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "openai/gpt-5",
    "messages": [
      {"role": "user", "content": "Extract the event: Alice and Bob meet for lunch on Friday."}
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "calendar_event",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "title": {"type": "string"},
            "day": {"type": "string"},
            "participants": {"type": "array", "items": {"type": "string"}}
          },
          "required": ["title", "day", "participants"],
          "additionalProperties": false
        }
      }
    }
  }'

The JSON arrives as a string in message.content. Parse it, but handle finish_reason: "length": a response cut short can contain incomplete JSON.

json_schema fields

FieldTypeRequiredDescription
namestringYesA name for the schema.
schemaobjectNoThe JSON Schema the output must follow. Without it, the request is sent as JSON mode (json_object), so Anthropic models drop the format.
strictbooleanNoAsk the provider to enforce the schema exactly. Defaults to false.
descriptionstringNoWhat the output is for.

A json_schema format without a json_schema object, without a name, or with a schema that is not a JSON object returns 400.

Provider behavior

The router sends the format the provider understands. Support differs by provider. To find models that accept structured outputs, check spec.capabilities.responseFormatCapability.jsonSchema in the List models response.

Providerjson_schemajson_object
OpenAISent as is.Sent as is.
Other OpenAI-compatible providersSent in OpenAI's format. Support depends on the provider and model.Sent in OpenAI's format. Support depends on the provider and model.
AnthropicUses Anthropic's structured outputs, which constrain the answer to your schema without a strict flag. Only the schema is sent; name, description and strict are not.Not supported. The router drops the format without an error, and the model answers in ordinary text. Use json_schema instead.
GoogleUses Gemini's JSON response schema.Uses Gemini's JSON response type.

On Gemini models earlier than Gemini 3, the response format is dropped when the request also includes tools, because those models do not accept both.

Each provider supports its own subset of JSON Schema. If you route across providers or use fallbacks, keep schemas simple (objects, arrays, strings, numbers, booleans and enums) so they work everywhere.

When the answer doesn't match

A schema makes a matching answer very likely, not certain. A response can return 200 with text that doesn't match, so check choices[0].finish_reason before you parse:

  • stop: the answer finished. Parse it, then validate the result against your schema before you use it.
  • length: the answer was cut off at the token limit and is likely incomplete. Raise max_tokens and retry.
  • content_filter: the model refused, or a filter stopped the answer. Anthropic refusals arrive this way. The text may not match your schema; handle it as a refusal rather than parsing it.

JSON mode

{"type": "json_object"} asks for valid JSON without a schema:

json
{
  "model": "openai/gpt-5",
  "messages": [
    {"role": "system", "content": "Reply in JSON with the keys \"title\" and \"day\"."},
    {"role": "user", "content": "Alice and Bob meet for lunch on Friday."}
  ],
  "response_format": {"type": "json_object"}
}

Describe the JSON you want in the prompt, because the model has no schema to follow.

Anthropic models have no JSON mode. A request with json_object that reaches one, directly or through a fallback, returns 200 with ordinary text: the router drops the format and does not return an error or a warning. Use json_schema with a schema when a request can reach Anthropic; it works there and on the other providers in the table.

An unrecognized response_format.type is treated as text rather than rejected.

Next steps