← Blog

Claude API JSON Mode: Structured Outputs Guide

2026-11-01 · 5 min read · SubToAPI Team

If you're searching for a "JSON mode" toggle in the Claude API like the one OpenAI offers, the short answer is: it doesn't exist as a single flag. Anthropic's Messages API has no response_format: json_object parameter. What it does have — and what actually gets you reliable structured output — is tool use (function calling), combined with a well-defined JSON schema and, optionally, response prefilling.

This matters because the goal behind "JSON mode" searches is almost always the same: you want Claude to return data you can JSON.parse() without regex cleanup, markdown fences, or "Sure, here's the JSON you asked for:" preambles. Claude can do this reliably — you just need to use the right mechanism instead of a magic flag.

Why Claude skips the dedicated JSON mode

Anthropic's design choice leans on tool use as the general-purpose structured output mechanism. Instead of a separate mode that constrains the whole response, you define a tool with an input_schema (JSON Schema), and Claude populates that schema when it decides to "call" the tool. Force the model to always use that tool, and you effectively get guaranteed structured JSON — with the added benefit that you also get strict typing, nested objects, enums, and required fields, which a bare JSON-mode flag usually doesn't give you.

Method 1: Tool use with a forced tool choice (recommended)

This is the most reliable way to get structured JSON from Claude today. Define a tool whose schema matches the shape you want, then set tool_choice to force Claude to use it.

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "tools": [{
      "name": "extract_invoice",
      "description": "Extract structured invoice data",
      "input_schema": {
        "type": "object",
        "properties": {
          "vendor": { "type": "string" },
          "total": { "type": "number" },
          "line_items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "description": { "type": "string" },
                "amount": { "type": "number" }
              },
              "required": ["description", "amount"]
            }
          }
        },
        "required": ["vendor", "total", "line_items"]
      }
    }],
    "tool_choice": { "type": "tool", "name": "extract_invoice" },
    "messages": [
      { "role": "user", "content": "Invoice from Acme Corp, total $420, items: Widget $300, Shipping $120" }
    ]
  }'

The response contains a tool_use content block with an input object that matches your schema exactly — no stray text, no code fences to strip. This is the closest Claude gets to a guaranteed JSON contract, and it's the pattern most production integrations use for extraction, classification, routing, and form-filling tasks.

Method 2: System prompt + prefill

If you don't need strict schema enforcement, you can get Claude to output plain JSON by combining clear instructions with response prefilling — seeding the assistant's reply so it has no room to add a preamble:

{
  "messages": [
    { "role": "user", "content": "Return a JSON object with keys \"name\" and \"age\" for: John, 34 years old." },
    { "role": "assistant", "content": "{" }
  ]
}

By prefilling the assistant turn with {, you remove the model's tendency to say "Here's the JSON:" first. You still need to parse the result defensively (prepend the { back, validate with a schema library) because this method has no hard schema enforcement — it relies on instruction-following, which is good but not airtight.

Method 3: Validate and retry

Whichever method you use, treat the output as untrusted until it passes validation:

Tool use with a forced tool_choice makes this retry loop almost unnecessary for simple schemas, but for deeply nested or conditional structures, a validate-and-retry step is still good defensive engineering.

Structured outputs with SubToAPI

If you're already calling Claude through SubToAPI, the tool-use pattern above works the same way against the SubToAPI endpoint — you just swap the host and auth header:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "tools": [ /* same tool schema as above */ ],
    "tool_choice": { "type": "tool", "name": "extract_invoice" },
    "messages": [ { "role": "user", "content": "..." } ]
  }'

SubToAPI exposes the same tools, tool_choice, and streaming semantics documented at /docs/tools, /docs/messages, and /docs/streaming, so structured-output patterns you build and test against the direct Claude API transfer over without rewriting your extraction logic. The extra value is in the surrounding infrastructure: per-application API keys (sub_live_...), usage metadata per request, and team seats — useful once your structured-output pipeline moves from a prototype into something multiple services or team members depend on. Check /pricing for plan details, or start a free trial at /signup.

Best practices checklist

Questions

Does Claude have a response_format: json_object parameter like OpenAI? No. Claude has no equivalent flag. The supported way to get structured output is tool use with a defined input_schema, optionally forced with tool_choice.

What's the most reliable way to guarantee valid JSON from Claude? Define a tool with a JSON Schema and set tool_choice to force that specific tool. Claude populates the schema in the tool_use block, giving you type-checked, parseable output without extra text.

Can I still get plain JSON without using tools? Yes, with clear system instructions and response prefilling (seeding the assistant turn with {), but you should validate the result yourself since there's no hard schema enforcement, unlike the tool-use approach.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →