← Blog

Claude API Tool Use JSON Schema Examples

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

Tool use (also called function calling) lets Claude decide when to call one of your defined functions and returns structured arguments that match a JSON Schema you provide. The most common search behind "claude api tool use json schema examples" is: what does a working tools payload actually look like, and how do I define parameters correctly so Claude returns valid, parseable JSON every time.

This article gives you copy-pasteable examples for the schema types you'll actually need — strings, enums, numbers, nested objects, arrays, and optional fields — plus the mistakes that cause malformed or missing tool calls.

The basic shape of a tool definition

Every tool you give Claude needs three things: a name, a description, and an input_schema written in JSON Schema (draft-07 subset). Claude uses the description to decide when to call the tool, and the schema to decide what arguments to produce.

{
  "name": "get_weather",
  "description": "Get the current weather for a specific city and unit system.",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "City name, e.g. 'Berlin' or 'San Francisco'"
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"],
        "description": "Temperature unit to return"
      }
    },
    "required": ["city"]
  }
}

Notice unit is not in required — Claude will omit it if the user doesn't specify, and your backend should supply a default. The description fields aren't decorative; they're the only signal Claude has about what valid input looks like, so be specific about formats, units, and edge cases.

Request structure with tool_choice

To request tool use, pass the tools array alongside your normal messages call:

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-opus-4-20250514",
    "max_tokens": 1024,
    "tools": [{
      "name": "get_weather",
      "description": "Get current weather for a city",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {"type": "string"}
        },
        "required": ["city"]
      }
    }],
    "messages": [{"role": "user", "content": "What is the weather in Lisbon?"}]
  }'

The response contains a tool_use content block with the tool name, an id, and input matching your schema. You then run the real function, and send the result back as a tool_result block in the next message to continue the conversation.

If you're routing these calls through SubToAPI instead of calling Anthropic directly, the request and response format is identical — see /docs/tools for the full tool-use reference and /docs/messages for the base message schema.

Enums and constrained values

When arguments must come from a fixed set, use enum. This drastically reduces invalid values compared to free-text strings:

{
  "status": {
    "type": "string",
    "enum": ["open", "in_progress", "closed", "cancelled"],
    "description": "Current ticket status"
  }
}

Numbers, booleans, and formats

Numeric fields should specify type: "number" or type: "integer" explicitly — don't leave them as strings, since Claude will respect the schema type and this saves you a cast-and-validate step downstream.

{
  "quantity": {
    "type": "integer",
    "minimum": 1,
    "description": "Number of units to order"
  },
  "express_shipping": {
    "type": "boolean",
    "description": "Whether to use express shipping"
  }
}

Nested objects

For structured arguments like an address or a line item, nest an object schema inside properties:

{
  "name": "create_invoice",
  "description": "Create an invoice for a customer",
  "input_schema": {
    "type": "object",
    "properties": {
      "customer": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "email": {"type": "string"}
        },
        "required": ["name", "email"]
      },
      "line_items": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "description": {"type": "string"},
            "amount": {"type": "number"}
          },
          "required": ["description", "amount"]
        }
      }
    },
    "required": ["customer", "line_items"]
  }
}

Arrays of objects like line_items are the most common source of confusion — remember items describes the schema of each array element, it isn't itself a list.

Forcing a specific tool

By default Claude chooses whether and which tool to call based on the conversation. If you want to force a call to a particular tool (useful for structured extraction pipelines), set tool_choice:

"tool_choice": {"type": "tool", "name": "create_invoice"}

Use {"type": "any"} to require some tool call but let Claude pick which one, or {"type": "auto"} (the default) to let Claude also choose to respond with plain text.

Common mistakes in tool schemas

If you're building a product on top of Claude's tool-use API — a support bot, a data extraction pipeline, an agent that calls internal services — SubToAPI wraps this into a standard HTTPS API with sub_live_... application keys, streaming, and per-key usage metadata, so you don't have to build key management and billing yourself. Check /docs/quickstart to see the same tool-use payloads working end to end, or /pricing for plan details.

Questions

Does the order of properties in the schema matter? No. JSON Schema property order doesn't affect Claude's behavior; what matters is clear description text and correct type/required values.

Can I use oneOf or anyOf in input_schema? Stick to straightforward object, string, number, boolean, array, and enum combinations. Complex schema composition like oneOf is not reliably supported and tends to produce inconsistent tool calls.

What happens if Claude returns input that doesn't match my schema? It's rare but possible, especially with very complex nested schemas. Always validate tool_use input server-side before executing your function, and return a tool_result with an error message if validation fails so Claude can retry.

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 →