Our own visit statistics are always on. Google Analytics, which helps us understand how people use our public pages (not your signed-in workspace), is enabled only with your permission. See our Privacy policy.

Claude strict tool use with a data API: two layers that keep calls valid

Opus 5.5 rejects forced tool_choice. We pair strict tools with 422 errors that explain the fix: 29 real calls, bad params back in 0.17 s, no charge.

Illustration. A light gray robot arm holds a teal block over a metal stencil plate. One square slot on the plate glows teal and matches the block exactly. The plate also has round, long and triangular slots. A short conveyor then carries the block into a cabinet of drawers that hold review cards with star marks. Behind the plate, a tray holds gray blocks of the wrong shape that nobody uses. The image shows a model that can only send data requests in a fixed shape.

Claude Opus 5.5, Sonnet 5.5 and Fable 5.1 return a 400 error when tool_choice is any or tool. Code that forced a tool call to get fixed JSON stops working on these models. Anthropic says to keep tool_choice: auto and add strict: true, or to move the schema into structured outputs. On November 1, 2026, we wrote strict tools for Trustpilot, App Store and Amazon reviews from the EveryInfra catalog. Then we sent 29 real requests to our API. Ten of them were control calls that we added in the afternoon.

That evening we sent 12 more requests as a retest.

Requests with a wrong parameter name or enum value came back as a 422 in 0.11 to 0.23 seconds. Each 422 had the allowed values and the next step, and none cost money. In the early catalog, two parameters had no allowed values. In an afternoon control test, wrong values for them did not fail. The API returned 200, charged the normal fee, and quietly sent back a different set of reviews. Nothing in the response told the model that something was wrong.

That evening the gateway added allowed values for these two parameters. Now a wrong value gets a 422 before any charge, and our retest at 19:18 SGT showed this.

This article answers one practical question. You have a Claude app that calls an outside data API. In the past you forced the model to call your tool, so each request had the same shape. On a new model, that line now fails. How do you change it so the model still calls the API reliably and returns JSON that you can store?

Every statement about Claude comes from the Anthropic documentation, and we link each one. We do not have an Anthropic API key on our test machine. So the Claude code in this article is a configuration example, not a test result. Every number about EveryInfra comes from the raw responses of real calls on November 1, 2026.

Illustration. On the left, a metal frame lets only correctly shaped teal capsules pass, which stands for the strict tool layer. In the middle, a server cabinet takes the capsules. One capsule with a slightly wrong shape bounces back from the cabinet with a folded note and a teal arrow that points to the correct shape, which stands for the 422 with a fix. The corrected capsule goes back in and a neat stack of cards comes out on the right. A coin lies untouched next to the bounced capsule, which means no charge.
Two layers. Strict tools keep the request shape correct, and the 422 sends back value errors at no charge.

What changed: three new models reject forced tool_choice, so claude strict tool use is now the default

The change is simple, and every design choice later in this article depends on it. The Anthropic API release notes for September 1, 2026, say that Fable 5.1 and Mythos 5.1 do not support tool_choice types any and tool. Such requests return a 400 error, while auto and none do not change (API release notes). The notes recommend strict tool use or structured outputs to get schema-conformant tool input. On September 22, the Opus 5.5 entry says the same 400 applies "as on Claude Fable 5.1". On September 28, the Sonnet 5.5 entry lists it as one of five ways that Sonnet 5 code can break.

Each model has a "What's new" page with a section named "Forced tool use is not supported". All three pages show the same error text, which we quote below. You can read it on the pages for Opus 5.5, Sonnet 5.5 and Fable 5.1. The text is tool_choice: type "tool" and "any" are not supported for this model. The same check also applies to the token counting endpoint. So you cannot use token counting to test a forced call before you send it.

Screenshot of the Anthropic docs page "What's new in Claude Opus 5.5", section "Forced tool use is not supported". A teal box marks the first paragraph and the error text. The text says that Claude Opus 5.5 does not support forced tool use, that tool_choice set to any or to a named tool returns a 400 invalid_request_error, and the error reads: tool_choice: type "tool" and "any" are not supported for this model. The next paragraph says auto and none still work, and that for schema-valid JSON you keep auto and set strict: true, or use structured outputs.
The Opus 5.5 page, captured on November 1, 2026. Anthropic documentation

Why did Anthropic remove forced calls? The Fable 5.1 page gives the reason. On these models, thinking is always on, and a forced tool call skips it. The model then writes its reasoning into the tool arguments, and argument quality drops. This matters if your app calls a data API.

In the old design, you forced the call to get a stable shape. Now the stable shape comes from the strict grammar, and the decision to call goes back to the model. Your prompt must say when the tool applies. The Fable 5.1 page adds that the model follows explicit tool instructions reliably, for example "Use the get_weather tool to answer".

ModelRelease date`tool_choice` any / toolAnthropic's replacementStandard price, input / output per MTok
Fable 5.1September 1, 2026400 errorauto + strict, or structured outputs$10 / $50
Opus 5.5September 22, 2026400 errorauto + strict, or structured outputs$4 / $20
Sonnet 5.5September 28, 2026400 errorauto + strict, or structured outputs$2 / $10
Haiku 5.5October 7, 2026Not listed in the release notes—$0.10 / $0.50

The dates and prices come from the release notes and the pricing page, read on November 1, 2026. The pricing page also shows that this change is not temporary. Its table of tool use system prompt tokens has two columns, one for auto, none and one for any, tool. For Opus 5.5, only the first column has a value, 286 tokens.

For Opus 5, both columns have values, 286 and 406 tokens. The Haiku 5.5 release notes list other breaking changes, such as manual thinking budgets, sampling parameters and prefill. They do not list forced tool use, so we make no claim about Haiku 5.5. We still use strict tools for it, so the same code runs on all four models.

Strict tool use is not new, and it is not only for new models. Two pages say that the feature is available on every model and is eligible for HIPAA readiness (strict tool use, structured outputs). What changed is its role. It was an optional safety step, and now it is the main path.

The Opus 5.5 migration checklist says to replace any and tool with auto plus strict tool use or structured outputs. It also says to check each input_schema first, because strict accepts only a subset of JSON Schema (Opus 5.5 migration guide). Most of the migration work is in your schemas, not in your call code.

Strict tool use and claude structured outputs: what each one controls

The two names are similar, but they control different parts of the response. Strict tool use adds "strict": true to a tool definition. It controls the input of each tool_use block. The API uses grammar-constrained sampling, so the input always matches the input_schema, and the tool name is always valid.

Anthropic's example is a booking system that needs passengers: int. Without strict mode, the model can send "two" or "2". With strict mode, it always sends 2.

Claude structured outputs means the output_config.format field of a request. It controls the final text of the response, which becomes JSON that matches your schema. For a data API workflow, you need both. Strict tools keep the parameters that go to POST /api/v1/social correct. Structured outputs turn the reviews that come back into fixed fields, such as topic, severity and a short quote. Both features use the same grammar pipeline, so they share the same limits.

The "JSON Schema limitations" section of the structured outputs page lists those limits. Supported: all basic types, enum, const, anyOf, internal $ref, ten string formats, and simple regex patterns. Not supported: recursive schemas, numeric limits such as minimum and maximum, string length limits, and minItems other than 0 or 1. Every object must set additionalProperties: false. If you use an unsupported feature, the API returns a 400 error with details.

ItemStrict tool useStructured outputs (`output_config.format`)
What it controlsTool arguments in tool_use blocksThe final response text
How to turn it onAdd "strict": true to a toolAdd a JSON Schema in output_config.format
Role in this articleCorrect parameters for EveryInfraFixed fields for each review
Shared limits per request20 strict tools, 24 optional params, 16 union-type paramsSame limits, counted together
Not supportedNumeric ranges, string length, recursionSame, and it cannot run with citations
First requestExtra delay while the grammar compiles; cache lasts 24 hoursSame

The phrase "per request" is the usual trap. The structured outputs page gives an example. Four strict tools with six optional parameters each already reach the limit of 24, even if no single tool looks complex. Above the explicit limits, there are internal limits on the size of the compiled grammar. If you exceed them, the API returns "Schema is too complex for compilation". The last safety limit is a compile timeout of 180 seconds.

Anthropic suggests four steps, in this order. Mark only critical tools as strict. Make parameters required. Flatten nested objects. Split work across requests or subagents.

Flow animation with five boxes from left to right. Box 1, Claude, with tool_choice auto and strict true tools. Box 2, tool_use input, which always matches the schema for types, required fields and enums. Box 3, your code, which sends POST /api/v1/social. Box 4, EveryInfra, which checks values for unknown names and bad enums. Box 5, the result, 200 with results and a charge per call. Boxes 2 and 4 are teal. A gray dot moves from Claude to EveryInfra, turns teal, and goes back to Claude along a dashed arc labeled 422 with allowed, did_you_mean, not charged. Then a teal dot moves from Claude to the result.

The diagram shows the main idea of this article. The first layer is on the Claude side. Strict mode makes sure that types, required fields and enum values match your schema. The model cannot send a field such as max_results if your schema does not have it. The second layer is on the EveryInfra side.

Some rules do not fit in a schema, for example "is this link a product page" or "what does this platform call this sort order". Our API checks those values against the catalog. When a value is wrong, it returns a 422 with the allowed values and the closest match. The model changes one field and sends the request again.

Layer one: build strict tools for POST /api/v1/social from the catalog

The EveryInfra catalog endpoint, GET /api/v1/social/catalog, is free and needs no key (raw catalog). For each capability, it gives required and optional parameters, a description of each parameter, the allowed values (allowed_values), the returned fields and the price. We read it on November 1, 2026, at 00:46 SGT. It listed 426 capabilities on 91 platforms. Of these, 402 capabilities on 89 platforms were available that day.

The available capabilities have 809 parameter descriptions. Of these, 155 list allowed values, 143 have the uri format and 38 have the date format. These three groups map directly to enum, format: uri and format: date in a strict schema. Without overlaps, 336 of 809 parameters (41.5%) translate into a constraint that strict mode can guarantee.

Only 155 (about 19%) can become an enum. The rest are free text or numbers. For those, the description and the second layer must do the work.

Here are tool definitions for three review capabilities, written from the catalog. This is a configuration example. We did not run it against Claude.

json
[
  {
    "name": "trustpilot_reviews",
    "description": "Get recent Trustpilot reviews of one company through EveryInfra (platform trustpilot, action reviews). Call it whenever the user names a company and asks what customers say. company is the company's website domain, for example temu.com.",
    "strict": true,
    "input_schema": {
      "type": "object",
      "properties": {
        "company": {"type": "string", "description": "Website domain such as temu.com, or a trustpilot.com/review/<domain> link"},
        "stars": {"type": "array", "items": {"type": "string", "enum": ["1", "2", "3", "4", "5"]}, "description": "Star ratings to keep; [] keeps all"},
        "date": {"type": "string", "enum": ["any", "last7days", "last30days", "last3months", "last6months", "last12months"], "description": "any = no date filter"},
        "sort": {"type": "string", "enum": ["recency", "relevance"]},
        "limit": {"type": "integer", "description": "1 to 200; use 20 unless the user asks for more"}
      },
      "required": ["company", "stars", "date", "sort", "limit"],
      "additionalProperties": false
    }
  },
  {
    "name": "app_store_reviews",
    "description": "Get App Store reviews of one iOS app through EveryInfra (platform app_store, action reviews).",
    "strict": true,
    "input_schema": {
      "type": "object",
      "properties": {
        "app_id": {"type": "string", "pattern": "^[0-9]{6,12}$", "description": "Numeric App Store id, for example 6473753684"},
        "country": {"type": "string", "pattern": "^[a-z]{2}$"},
        "sort": {"type": "string", "enum": ["newest", "most_helpful"]},
        "limit": {"type": "integer", "description": "1 to 500; use 30 unless the user asks for more"}
      },
      "required": ["app_id", "country", "sort", "limit"],
      "additionalProperties": false
    }
  },
  {
    "name": "amazon_reviews",
    "description": "Get the featured customer reviews shown on one Amazon product page (platform amazon, action reviews). Usually about a dozen reviews per product.",
    "strict": true,
    "input_schema": {
      "type": "object",
      "properties": {
        "url": {"type": "string", "pattern": "^https://www\\.amazon\\.[a-z.]{2,6}/(dp|gp/product|product-reviews)/[A-Z0-9]{10}"},
        "domain": {"type": "string", "enum": ["amazon.com", "amazon.co.uk", "amazon.de", "amazon.fr", "amazon.it", "amazon.es", "amazon.ca", "amazon.com.au", "amazon.in", "amazon.co.jp", "amazon.sg"]}
      },
      "required": ["url", "domain"],
      "additionalProperties": false
    }
  }
]

The limits above forced four design choices. First, every parameter is required. The catalog gives trustpilot/reviews six optional parameters, plus limit, so seven in total. If we copied them as optional, they would use almost a third of the 24 slots.

Anthropic suggests a different approach: when a parameter always has a reasonable default, make it required and let the model fill in the default. So we added an any value to date and allowed an empty array for stars. Our code removes any and [] before it sends the request, because the catalog says that an empty value means no filter. In the evening we sent date: any to the API as a test, and it got a 422 in 0.11 seconds. So do not skip this step.

Second, the range of limit is in the description, not in minimum or maximum, because numeric limits are not supported. Values above the maximum are a matter for the API. Six capabilities in the catalog say "capped" for this case, so the API uses the maximum. Third, a simple regex limits the Amazon link to product pages. The catalog note for amazon/reviews says that a store home page does not work.

We tested a store link against this schema with a local JSON Schema validator, and the regex rejected it.

Fourth, the catalog that we read early on November 1 did not give allowed_values for date and sort on trustpilot/reviews. We copied the values from the catalog text. The next section shows why that mattered. That evening the catalog added these values, so we added last7days above. For domain, we used the 11 sites that the catalog listed at 22:14 SGT. amazon.com.mx is not one of them, because that site now returns 422 before any charge. The limits section has the details.

The whole definition uses only enum, required, additionalProperties: false, simple pattern and format. Most constrained decoding systems support these. Numeric ranges and lengths have different support in different systems. The JSONSchemaBench test of six frameworks shows this. So we leave them to the 422. The same tool definitions can then move to another model provider with small name changes, and the second layer does not change.

Screenshot of the "Explicit limits" table in the Anthropic structured outputs documentation. It has three rows: strict tools per request, 20; optional parameters, 24; parameters with union types, 16. A teal box marks the optional parameters row, which says the limit is the total of all parameters not listed in required, across all strict tool schemas and JSON output schemas.
Strict tools and structured outputs share one set of limits per request. Captured on November 1, 2026. Anthropic documentation

How many catalog capabilities fit in this budget? We counted the optional parameters of all 402 available capabilities. For capabilities that return a list, we also counted limit. The median is 1 and the maximum is 9. No single capability goes above 24. 100 capabilities have no optional parameters and 139 have one, so 239 capabilities (59.5%) have zero or one.

Bar chart of 402 available EveryInfra capabilities by number of optional parameters. 0 params, 100 capabilities. 1 param, 139 capabilities. These two bars are teal. 2 params, 70. 3 params, 37. 4 params, 25. 5 params, 13. 6 params, 4. 7 params, 6. 8 params, 7. 9 params, 1. Source is the catalog read on November 1, 2026, at 00:46 SGT.

This distribution tells us two things. The good news: if you make every parameter required, any 20 capabilities fit in one request with no optional slots used. The bad news: you cannot turn all 402 capabilities into strict tools in one place. Their optional parameters add up to 686. At 24 per request, you need at least 29 groups.

Our greedy packing used 30 groups. The limit of 20 strict tools per request alone needs at least 21 groups. So the right approach is to choose tools by task. For a review monitor, eight review capabilities together use exactly 23 optional slots.

Horizontal bar chart. Running total of optional parameters for eight review tools. amazon/reviews 2, trustpilot/reviews 9, app_store/reviews 12, google_play/reviews 17, g2/reviews 19, capterra/reviews 20, yelp/reviews 22, tripadvisor/reviews 23, which is teal. A dashed line marks the limit of 24. One more tool with an optional parameter goes over the limit.

23 is one below the limit of 24. Add a structured output schema with one optional field and the request fails. That is why Anthropic says to make parameters required where you can. Our three example tools are fully required, so they use zero optional slots. That leaves the budget for the output schema.

There is also a useful counterexample. The EveryInfra remote MCP server has a general tool, everyinfra_call_api. Its params field is an open object, because the tool must accept all 426 capabilities. That is fine for a normal tool.

But strict mode needs additionalProperties: false on every object, so this schema cannot be strict. When we read the MCP tool list again at 15:41 SGT on November 1, 2026, it had 12 tools and was 16,247 bytes. The params field of everyinfra_call_api was still an open object. If you want the strict guarantee, write task-specific tools like the ones above. Keep the general tool for exploration.

Turn the catalog into schemas automatically, and rebuild them every day

You can write three tools by hand. With thirty tools, you will make mistakes, and the catalog also changes. A safer approach is a small script. It reads the free catalog once a day, builds strict tools from fixed rules, and compares the result with the previous day.

We use six rules, and each rule comes from a limit described above. Our code removes the "not set" values before each call.

Catalog fieldStrict schemaReason
required_paramsCopy into requiredRequired fields do not use optional slots
optional_paramsAlso into required, with a "not set" value such as any or []Keeps the 24-slot budget free
allowed_valuesenum, copied exactly, same caseStrict mode guarantees enum values
format: uri or dateSame formatStrict mode accepts ten string formats
default_limit, max_limitinteger, with the range in the descriptionminimum and maximum are not supported
Every objectadditionalProperties: falseStrict mode requires it

Two cases need a person. The first case is a parameter that lists its values only in text, with no allowed_values. The date and sort parameters of trustpilot/reviews are examples. The script cannot find these values. A person must copy them into an enum, or wait for the catalog to add them. The catalog added these two on the evening of November 1.

We keep a list of these parameters and show it at each rebuild.

The second case is a very large enum. On the day of our test, 8 enums had more than 100 values, and the largest had 183. A large enum makes the compiled grammar bigger. Anthropic says these internal limits have no single number. For such parameters, we skip the enum, list the most common values in the description, and let the 422 do the check. The 422 sends back the full allowed list anyway.

A daily rebuild also tells you when you will pay for a new compile. The structured outputs page says that compiled grammars stay in a cache for 24 hours after last use. A change to the schema structure clears the cache. When you use structured outputs and tools together, a change to the set of tools also clears it. A change to only name or description does not. So the script must separate two kinds of change.

If only the text changed, replace it at no cost. If parameters, values or required fields changed, the next request will be slower. In a batch, this delay does not matter. In a live chat, send one warm-up request at a quiet time. A batch also gains from this rule: thousands of requests share one set of tools and one output schema, so the grammar compiles once.

Layer two: the 422 lets the model fix its own call

The first layer stops shape errors. It does not stop value errors. A model can choose a wrong value that the schema still allows. For example, it can send most_recent as the App Store sort order, which is the name on another platform. Or your app may not use strict mode at all and may call the general tool. For these cases, the second layer must fail fast, charge nothing, and explain the fix.

The Anthropic page on tool calls says two things that apply here (handle tool calls). First, put the error in a tool_result with is_error: true. The model will then retry with corrections, usually 2 to 3 times before it apologizes to the user. Second, write instructive error messages. Do not write only "failed". Say what went wrong and what Claude should try next.

On November 1, 2026, between 00:48 and 00:49 SGT, we sent seven bad requests on purpose. At 00:57 SGT, we sent one more through MCP. Here is the raw response for an unknown parameter. The request has an extra max_results.

The API returned a 422 in 0.12 seconds. The allowed field lists all eight valid parameter names. The example field gives a request that works. The next_steps field says to remove max_results, and it says that nothing was charged.

Screenshot of a request to POST /api/v1/social with platform trustpilot, action reviews, company temu.com and an extra max_results of 20. Below it is the raw HTTP 422 response, 0.12 seconds, 703 bytes, at 2026-11-01 00:48:38 SGT. The error code is unknown_param. The message says max_results is not a parameter of trustpilot/reviews, company is required, and date, lang, language, limit, sort, stars and verified_only are optional. Teal boxes mark the allowed list, the next_steps text (remove max_results, see catalog_url, example is a working request, nothing was charged) and the example request body.
The raw 422 response for an unknown parameter. The key is shown as an environment variable name. Real EveryInfra API response

A wrong enum value is the more typical case. At 00:49 SGT, we sent sort: most_recent to app_store/reviews. The API returned a 422 in 0.11 seconds. The did_you_mean field was ["newest"], and allowed was ["most_helpful", "newest"]. The first next_steps line says to change only sort to a value in allowed and send again, and that nothing was charged.

The second line is also useful. It says what to do if the catalog lists the value you sent. Then the bug is on the EveryInfra side, and the model should ask the user about a support ticket. This line is for the model. It separates "my input was wrong" from "the service is wrong". So the model does not treat its own mistake as an outage and retry the same value.

Screenshot of a request to app_store/reviews with app_id 6448311069 and sort most_recent. The response is HTTP 422, 0.11 seconds, 621 bytes, at 2026-11-01 00:49:03 SGT. The error code is invalid_value, and the message says sort must be most_helpful or newest, got most_recent. Teal boxes mark did_you_mean (newest), allowed (most_helpful, newest) and next_steps (change only sort to a value in allowed, then resend, nothing was charged; if the catalog lists your value, it is a bug on the EveryInfra side, so ask the user about a support ticket).
The raw 422 response for a bad enum. did_you_mean gives the fix directly. Real EveryInfra API response

The table below shows the eight error cases, the two afternoon control calls and five evening retests after the fix. The last column comes from a local check. We validated each input against the tool definitions above. We used a JSON Schema validator for the Draft 2020-12 validation vocabulary.

Time (SGT)What we brokeResponseTimeChargeFix hints in the responseStrict blocks it first?
00:48:37No key401 missing_key0.12 s0Says to send a keyNot related
00:48:38Extra max_results422 unknown_param0.12 s0Param list, example requestYes
00:48:42company typed as compnay422 missing_param0.23 s0Names the typo, exampleYes
00:48:42date: last7days5031.69 s0 (refunded)Only "retry later"Yes then; a valid value after the evening fix
00:48:44sort: newest5031.91 s0 (refunded)Only "retry later"Yes then; a valid value after the evening fix
00:49:03sort: most_recent422 invalid_value0.11 s0did_you_mean, allowedYes
00:49:03G2 sort: newst422 invalid_value0.20 s0did_you_mean, allowedYes
00:57:45G2 sort: most_recent over MCPisError: true—0Same, in structuredContentNot applicable
15:39:38sort: newest (control)200, 20 rows14.3 s$0.001389None; different reviewsYes then; a valid value after the evening fix
15:39:38date: last7days (control)200, 20 rows14.4 s$0.001389None; different reviewsYes then; a valid value after the evening fix
19:18:39sort: newst (after the fix)422 invalid_value0.21 s0did_you_mean (newest), allowedYes
19:18:46date: last_week (after the fix)422 invalid_value0.12 s0did_you_mean (last7days), allowedYes
19:18:53date: any (after the fix)422 invalid_value0.11 s0allowedNo; the schema allows it, and the code removes it
19:19:01language: eng (after the fix)422 missing_param0.19 s0Asks for a two-letter codeNot in our definition
19:19:23sort: newest (after the fix, now valid)200, 20 rows14.1 s$0.001389Same rows as recencyNot needed

The four daytime trustpilot/reviews rows need a close look. In the early catalog, the date and sort parameters of this capability have only a text description, with no allowed_values. So the API cannot check them as enums at the door. At 00:48 SGT, each wrong value got a 503 after 1.7 to 1.9 seconds. We were not charged, and next_steps said only to retry after retry_after seconds.

But we cannot blame those two 503 errors on the values. In the same few minutes, another of our tests called trustpilot/profile without these parameters, and it also got a 503. So the platform itself was unstable at that time.

So we ran a control test in the afternoon. At 15:39:38 SGT, we sent four calls in the same minute, all for temu.com. Each call changed one parameter only. We compared sort: newest with the valid sort: recency, and date: last7days with the valid date: last30days. At 15:40 SGT, we added a baseline call with no optional parameters and one repeat of newest. All six calls returned 200 with 20 rows, and each cost $0.001389.

The results split into two clean groups. The two valid values and the baseline returned the same 20 reviews. All were in English, and verification_level and source had values. The two unlisted values and the repeat returned a different set of 20 reviews. Of these, 13 were in English, 3 in French, 2 in Spanish and 2 in Italian. In all 20, those two fields were empty.

So during the day on November 1, a wrong value got no 422 and no 503. The API accepted it, charged the normal fee, and quietly changed the result.

For a model, this is worse than a 503. The model sees a success, so it does not retry and does not warn the user. The mixed-language reviews go straight into your pipeline. The catalog text for sort actually says to use recency and not the newest value from other platforms. But only a reader of the text sees that. The API check did not.

Those are the daytime results. That evening the gateway changed these rules:

ParameterDuring the day on November 1After the evening fix
sortNo listed values; newest was accepted and charged, with different reviewsnewest (the same as recency), recency, relevance
dateNo listed values; last7days was accepted and charged, with different reviewsFive presets that cut by posting date: 7, 30, 92, 183 and 366 days back
language, langThe text gave only examplesTwo-letter codes only; with no language, English reviews only
Values not in the listCould be accepted and chargedA 422 before any charge, with allowed values and a did-you-mean hint

The last five rows of the error table are our retest with the same company. Wrong values got a 422 with a hint and no charge. Four calls returned 200 at $0.001389 each: sort: newest, sort: recency, date: last7days and a baseline. All four returned the same 20 English reviews, with verification_level and source in every row. The oldest review was less than one day old, so last7days and no date must match.

This also shows why the first layer is necessary. Our strict schema lists date and sort as enums, so these errors cannot leave Claude. After the evening fix, a 422 also stops these two errors. But other parameters can still list their values only in text, so your client schema is still the first check.

The MCP side uses the same split. The MCP specification, tools section puts input validation errors with tool execution errors. They go in the result with isError: true, and the client gives them to the model so that it can correct itself. Our MCP call at 00:57 SGT returned exactly this. Our guide to API errors covers each error code, and the refund check guide shows how to match refunds.

Heatmap of which fields each of 7 real error responses carries, teal means present. 401 no key has only next_steps and says not charged. 422 unknown param has param, allowed, example, catalog_url, next_steps and says not charged, but no did_you_mean. 422 required param typo has param, example, catalog_url, next_steps and says not charged. 422 bad enum, 422 enum typo and MCP isError bad enum have param, allowed, did_you_mean, catalog_url, next_steps and say not charged, but no example. 503 bad date preset has only next_steps and says not charged.

Another finding comes from a small note in the Anthropic documentation. Structured outputs do not guarantee the case of string enum values. The model can return a value that differs from your schema only in capital letters, with no error. The note says this also applies to strict tool use (structured outputs, "Invalid outputs"). So even with strict mode, newest can become Newest. At 14:33 SGT, we tested app_store/reviews with sort: Newest.

The API did not return an error. It returned 200 with 30 reviews in newest-first order, and it charged $0.001389.

One call is not enough for a rule, so from 15:39 to 15:41 SGT we tested two more platforms. On g2/reviews, sort: Newest and sort: newest returned the same 21 records. On google_play/reviews, sort: Top_Rated returned 40 reviews, all five-star. A sort: Newest call in the same minute returned a mix of one to five stars, so the capitalized value did take effect. These four calls cost $0.001389 each.

So on the three capabilities that we tested, a case difference counts as the same value. We did not test the other enums in the catalog. The safe method is to change enum values to lowercase in your code before you send them. That one line costs much less than one wrong call. Anthropic's other advice also applies: do not define two enum values that differ only in case.

Parallel tool use also affects both layers. It is on by default. So the model can send several tool_use blocks in one turn, for example Trustpilot and App Store together. The parallel tool use page gives two format rules. All tool results for the turn go in one user message, and no text comes before the results. So your code must handle a 422 and a 200 in the same turn.

Mark the 422 result with is_error: true and return the 200 result as usual. The model then resends only the failed call. If your key has a low rate limit, or you want simple logs, add disable_parallel_tool_use: true inside the tool_choice object. In auto mode, the model then calls at most one tool per response. This setting is not a top-level request parameter.

Horizontal bar chart on a log scale. Time and charge for 17 of the first 19 real calls, before 15:00 SGT. The Mexico store call, the Spanish-language call and the 10 afternoon control calls are not shown. Four 422 calls (sort most_recent 0.11 s, unknown max_results 0.12 s, sort newst 0.20 s, typo compnay 0.23 s) and the 401 at 0.12 s cost nothing; the 422 bars are teal. Three App Store calls with 200 took 0.44 to 0.51 s and cost $0.001389 each. Two 503 calls took 1.69 and 1.91 s and cost nothing. amazon/search took 11.78 s and cost $0.002236. Trustpilot with 20 rows took 56.95 s and with 100 rows took 84.00 s, at $0.001389 each. Three sync amazon/reviews calls took 66 to 73 s, returned 0 rows and cost nothing.

The chart shows the same fact from a different side. A 422 retry costs $0 and about 0.17 seconds on the API side, which is the mean of the four 422 calls. The cost is in the extra model turn.

Use this formula for one extra turn: rework cost = (context tokens + error tokens) × input price + fix tokens × output price. We use about 240 tokens for the error body and about 120 output tokens for the fix. The context length sets most of the cost, so the table shows three sizes. Prices come from the pricing page, read on November 1, 2026. The number in parentheses is the cost in review calls at $0.001389 each.

ContextHaiku 5.5Sonnet 5.5Opus 5.5Fable 5.1
1,000 tokens$0.00018 (0.1)$0.0037 (2.6)$0.0074 (5.3)$0.0184 (13)
5,000 tokens$0.00058 (0.4)$0.0117 (8.4)$0.0234 (17)$0.0584 (42)
20,000 tokens$0.0021 (1.5)$0.0417 (30)$0.0834 (60)$0.2084 (150)

An app with three tool definitions and a few turns often has a 20,000-token context. Then one mistake on Opus 5.5 costs about 60 data calls. With prompt caching, the context part uses the cache read price. That price is 10% of the input price on Haiku 5.5, 5% on Opus 5.5 and Sonnet 5.5, and 2.5% on Fable 5.1. At 20,000 tokens on Opus 5.5, that brings one extra turn from $0.0834 to about $0.0074.

Put your own context length into the formula to get your own ratio. The direction is the same at every size: a longer context makes a retry more expensive. That is the economic reason for the first layer. Strict mode stops the most common retry before it starts.

One full round trip: what the model sends and what comes back

The code below joins the two layers in a minimal loop. It follows the Anthropic documentation. It is a configuration example, and we did not run the Claude side. The EveryInfra requests and responses are real results from November 1, 2026.

python
import json, os, requests, anthropic

client = anthropic.Anthropic()                 # reads ANTHROPIC_API_KEY
EI = "https://api.everyinfra.com/api/v1/social"
TOOLS = json.load(open("tools.json"))           # the three strict tools above
ROUTE = {"trustpilot_reviews": ("trustpilot", "reviews"),
         "app_store_reviews": ("app_store", "reviews"),
         "amazon_reviews": ("amazon", "reviews")}

def call_everyinfra(name, args):
    platform, action = ROUTE[name]
    params = {k: v for k, v in args.items() if v not in ("any", [], None)}   # "any" and [] mean no filter
    r = requests.post(EI, json={"platform": platform, "action": action, "params": params},
                      headers={"Authorization": f"Bearer {os.environ['EVERYINFRA_API_KEY']}"}, timeout=90)
    body = r.json()
    if r.status_code == 422:                    # value error: pass it to the model as is
        return json.dumps(body["error"]), True
    if r.status_code >= 400:
        return json.dumps(body.get("error", body)), True
    rows = [{k: x.get(k) for k in ("id", "rating", "title", "text", "posted_at")} for x in body["results"]]
    return json.dumps({"count": body["count"], "charged_usd": body["billing"]["charged_usd"], "reviews": rows}), False

messages = [{"role": "user", "content": "Use the trustpilot_reviews tool to get 20 one- and two-star reviews of temu.com from the last 30 days, then group them by topic."}]
while True:
    resp = client.messages.create(model="claude-opus-5-5", max_tokens=4000, tools=TOOLS,
                                  tool_choice={"type": "auto"}, messages=messages)
    messages.append({"role": "assistant", "content": resp.content})
    if resp.stop_reason != "tool_use":
        break
    results = []
    for block in resp.content:
        if block.type == "tool_use":
            text, is_err = call_everyinfra(block.name, block.input)
            results.append({"type": "tool_result", "tool_use_id": block.id, "content": text, "is_error": is_err})
    messages.append({"role": "user", "content": results})

A few details make this loop stable. The code sets tool_choice to auto. That is the default, but the explicit value tells the next developer that no forced call is in use. The user message names the tool.

That is the replacement for a forced call in the Opus 5.5 and Fable 5.1 documents. The code puts the 422 error body in the tool_result as it is, with is_error: true. Do not replace it with "bad parameter", because allowed and did_you_mean are the parts that the model can use.

On success, the code returns only five fields to the model: id, rating, title, text and post time.

We measured this on the real responses of that day. The results for 20 Trustpilot reviews had 31,046 characters. With the five fields only, they had 13,040 characters, which is 58% less. For 30 App Store reviews, the size went from 13,012 to 7,726 characters, which is 41% less. When the model reads less, each turn costs less. We use the trimmed size in the batch math below.

Here is the real round trip for this loop at 00:49 SGT on November 1, 2026. Strict mode makes the model send parameters like {"company": "temu.com", "stars": ["1", "2"], "date": "last30days", "sort": "recency", "limit": 20}. Our code sends them to trustpilot/reviews. The API returned 200 after 56.9 seconds with 20 reviews: 19 one-star and 1 two-star, posted between October 30, 2026 and October 31, 2026.

By country, 10 came from the UK and 3 from the US, and 16 had a reply from the company. The charge was $0.001389, the same as the catalog price_usd. If the model had chosen "sort": "newest", strict mode would stop that call. Without strict mode, the API would not reject the value. As in the control test above, it would charge the normal fee and return a set of reviews in mixed languages.

What will the structured output see? We did not run Claude, so we report no model output. Instead, we used simple keyword rules on the 100 Trustpilot reviews from the 14:37 SGT call. Of 100 reviews, 40 mention a refund and 20 mention a return.

35 mention delivery, 33 mention quality or damage, 35 mention customer service, and 14 mention an account. 16 reviews match no rule. The median text length is 432 characters, and the longest review has 3,371 characters.

These numbers help in two ways. First, one review often matches more than one topic. If your schema allows only one topic, the model must choose, so put the rule in the description, for example "prefer the topic about money". Second, the longest review is about 1,350 tokens.

When you plan 25 reviews per request, plan for the length distribution, not the average. Otherwise some requests can hit your max_tokens. These reviews were posted from October 27, 2026 to November 1, 2026, so they describe only those days.

The second step asks the model to put each review into fixed fields with claude structured outputs. This schema is also a configuration example:

json
{
  "type": "json_schema",
  "schema": {
    "type": "object",
    "properties": {
      "source": {"type": "string", "enum": ["trustpilot", "amazon", "app_store"]},
      "items": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "review_id": {"type": "string"},
            "rating": {"type": "integer"},
            "topic": {"type": "string", "enum": ["delivery", "refund", "quality", "price", "support", "app_bug", "account", "other"]},
            "severity": {"type": "string", "enum": ["low", "medium", "high"]},
            "quote": {"type": "string", "description": "At most 20 words copied from the review"}
          },
          "required": ["review_id", "rating", "topic", "severity", "quote"],
          "additionalProperties": false
        }
      }
    },
    "required": ["source", "items"],
    "additionalProperties": false
  }
}

This schema has zero optional parameters, so it fits in the same request as the three strict tools. The quote field says "at most 20 words" in the description instead of maxLength, because length limits are not supported. Two documented exceptions remain. If the model refuses, the response has stop_reason: "refusal", and the output may not match the schema.

If the output reaches max_tokens, the response has stop_reason: "max_tokens", and the output may be incomplete. So check stop_reason before you store anything. Also, a field that asks for "step-by-step reasoning" can cause a reasoning_extraction refusal. The refusals and fallback page suggests asking for a short explanation instead.

US app teams will often start with App Store reviews. At 00:54 SGT, we read the newest 30 US reviews of the Claude app (app_store/reviews, app_id 6473753684). 24 came from version 1.261026.20 and 6 from version 1.261028.19. The reviews were posted between October 28, 2026 and October 30, 2026. The table puts these samples next to the Trustpilot samples.

SampleTime (SGT)Rows1 or 2 stars5 starsCharge
trustpilot/reviews, temu.com, stars 1–2, limit 2000:4920200$0.001389
trustpilot/reviews, temu.com, stars 1–2, limit 10014:371001000$0.001389
app_store/reviews, Claude app, US, newest00:54301016$0.001389
app_store/reviews, ChatGPT app, US, newest00:5430521$0.001389

These counts have no statistical weight. They show one practical fact. The same schema sees almost only bad reviews on Trustpilot, because we filtered for one and two stars. On the App Store, it sees a mix.

The distribution of a field like severity changes with the source, so set alert levels per source. Apple's developer page says that the summary rating is per storefront and can reset with a new version. Written reviews stay (Apple, ratings and reviews). So reviews by version are more useful than the total score.

Batches: the cost of 1,000 reviews with Message Batches

After one round trip works, the cost is in volume. The Message Batches API processes requests asynchronously, and all usage costs 50% of standard prices. A batch can hold up to 100,000 requests or 256 MB. Most batches finish within one hour. Requests that do not finish in 24 hours expire and are not billed.

Results stay available for 29 days (batch processing). The structured outputs page says the feature works with batches at the same 50% discount. Each request in a batch is a full Messages request. So the strict tools and output_config.format go in as they are (create a Message Batch).

On the data side, the first question is how many rows to get per call. The catalog gives trustpilot/reviews a default of 20 and a maximum of 200, at $0.001389 per call. It has no per-row price field. At 14:37 SGT, we sent limit: 100.

We got 100 reviews, and the charge was still $0.001389, the same as for 20 rows. Of these 100 reviews, 95 were one-star and 5 were two-star. 44 came from the UK and 21 from the US.

The cost of a large limit is time. The sync call took 84.0 seconds, and the catalog says the sync budget is 85 seconds. That is very close to the limit. So for bulk review pulls, use a large limit and add "mode": "async" to the request body. Then poll GET /api/v1/jobs/{job_id}. Do not wait on a sync call.

Per 1,000 reviewsHaiku 5.5Sonnet 5.5Opus 5.5Fable 5.1
Model cost, standard$0.0577$1.1537$2.3073$5.7683
Model cost, Message Batches$0.0288$0.5768$1.1537$2.8842
Data fee, limit=100 (10 calls)$0.0139$0.0139$0.0139$0.0139
Total, batch + limit=100$0.0427$0.5907$1.1676$2.8981

Here is how we estimated the model cost, so you can use your own numbers. The models overview says 1M tokens is about 2.5M Unicode characters, so we use 0.4 tokens per character.

Input to the estimateValueWhere it comes from
Reviews per request25, so 40 requestsOur choice
Characters per trimmed reviewAbout 440Real Trustpilot and App Store responses
Instructions and schema per requestAbout 1,424 charactersOur prompt and output schema
Characters per output itemAbout 189One sample output item
Total tokensAbout 198,832 in, 75,600 outCharacters × 0.4

We did not count thinking tokens, the tool use system prompt (286 tokens on Opus 5.5) or the format prompt that structured outputs adds. So the numbers are a lower bound. With the default limit=20, the data fee for 1,000 reviews is 50 calls and $0.0694, five times the cost at limit=100.

Stacked horizontal bar chart. USD cost to turn 1,000 reviews into JSON, with model cost at Message Batches prices and the data fee at limit=100, $0.001389 per call. Haiku 5.5 total $0.0427, teal. Sonnet 5.5 $0.5907. Opus 5.5 $1.1676. Fable 5.1 $2.8981. The data fee is $0.0139 in each bar. It is about one third of the Haiku bar and almost invisible in the other three.

The result is clear. Review grouping means a lot of reading and simple decisions, so give it to Haiku 5.5. Then the model cost and the data fee are similar, about $0.04 per 1,000 reviews in total. Opus 5.5 costs 27 times more, and Fable 5.1 costs 68 times more. Haiku 5.5 has one price step to watch.

Above 100,000 prompt tokens, the price becomes $0.50 / $2.50, or $0.25 / $1.25 in a batch. With 25 short reviews per request, you stay far below that line. If you need finer judgment, for example "slow delivery" versus "seller refused a return", run Haiku on everything first. Then send only the severity: high items to Opus 5.5.

Now apply this to a daily monitor. Take one-star and two-star Trustpilot reviews for 50 companies, plus new App Store reviews for 50 apps. That is 100 API calls per day: $0.1389 per day and $4.17 for 30 days. The monitor reads up to about 2,500 reviews per day.

For 30 days, grouping costs about $2.16 on Haiku 5.5 in batches, $43.26 on Sonnet 5.5 and $86.53 on Opus 5.5. Batches and prompt caching can work together, and cached system prompts and tool definitions cost less. But the cache hit rate in a batch depends on request order. We did not test it, so it is not in these numbers.

What does not work, and what to watch

First, our own gap. amazon/reviews returned no reviews in four tries on November 1, 2026. Two sync calls at 00:50 and 00:51 SGT waited about 68 and 73 seconds. One async job at 00:53 SGT finished with 0 rows.

One more sync call at 14:34 SGT, with domain set, waited 66 seconds and also returned 0 rows. None of the four calls cost anything. Empty results are refunded by rule, and the async job was charged and then refunded.

That evening the gateway changed two Amazon cases. We retested them from 19:19 to 19:24 SGT:

RequestDuring the dayEvening retestCharge
US site, sync200, 0 rows, 66–73 s503 access_blocked in 24.6 s; next_steps says that a quick retry will not help0
US site, asyncJob done, 0 rows202 with a $0.001389 hold; the job failed with access_blocked0 (refunded)
amazon.co.jpNot tested19:19: 422 missing_param, message "missing domain". 22:14: 200 in 35.3 s with 5 reviews, all by buyers in other countries (3 United States, 2 Germany)0 at 19:19; $0.001389 at 22:14
amazon.com.mxNot tested19:19: 422 missing_param. 22:14: 422 invalid_value in 0.09 s, with the list of 11 supported sites0

At 19:19, the error message did not say that these two sites were not supported. At 22:14, the catalog gave domain as an enum of 11 sites: amazon.com, co.uk, de, fr, it, es, ca, com.au, in, co.jp and sg. The Mexico site is now stopped before any charge, and the error lists the 11 values. The tool definition above uses the same list. The Japan site now returns reviews, but they are not always by buyers in Japan. To keep only reviews from Japan, filter on the country field.

The catalog already says that this capability gets only the featured reviews on a product page, usually about a dozen per product. That day, it did not get even those. So the Amazon tool in this article is only a configuration example. Our real tests used trustpilot/reviews and app_store/reviews, which worked that day.

At the same time, amazon/search worked: at 00:51 SGT, a search for "anker power bank 10000mah" returned 5 products in 11.8 seconds for $0.002236. Before you add Amazon reviews to a batch, check the catalog. Then make one small call on that day.

Next, the limits that Anthropic documents. Strict tools are HIPAA eligible, but the API caches compiled schemas apart from message content, without the same protection (strict tool use, data retention). So do not put a customer list into an enum. The Fable 5.1 migration guide covers the CMEK case (Fable 5.1 migration guide).

LimitWhat it means for a data APISource
No health data in schemasNo PHI in property names, enum, const or patternStrict tool use, data retention
CMEK organizationsNo structured outputs or strict: true on Fable models; use the instruction aloneFable 5.1 migration guide
CitationsCannot run with structured outputs; a 400 errorStructured outputs, feature compatibility
Format changeA new output_config.format clears the prompt cacheStructured outputs, token costs

The citations limit needs one more note. For structured data with a source for each value, use the special method in the citations docs.

Finally, the second layer has limits. A 422 can stop only errors that the catalog defines: unknown parameters, missing required parameters, and enums with listed values.

It cannot stop errors in rules that the catalog gives only as text. During the day on November 1, date and sort on trustpilot/reviews were examples. At that time, wrong values for those two did not even fail. They cost the normal fee and changed the result. The evening fix added allowed values for these two, so now they get a 422.

The 422 also cannot stop facts that are known only at run time, such as "does this company have a Trustpilot page".

So use both layers. Put every rule you can into the strict schema. Leave the rest to the 422. For enums that you copied from catalog text, also check the language and key fields of each response in your code.

Troubleshooting: seven symptoms and their fixes

In production, problems usually come from the edges. A schema suddenly fails to compile. A model does not call a tool on one turn. A few items in a batch do not match. The table below lists seven symptoms from the documentation and from our real calls.

First, check who returned the status code. A 400 comes from Anthropic and means the request or schema is wrong, so change the code. A 422 or 503 comes from EveryInfra and means the shape is correct but a value or the run failed, so follow next_steps. This one check saves most of the debugging time, because the two error formats look different and are easy to mix up in logs.

SymptomWho returned itCauseFix
400, tool_choice not supportedAnthropicany or tool on a new modelUse auto and name the tool in the user message
400, schema too complexAnthropicMore than 24 optional params, or a large grammarMake params required; replace large enums with text and the 422
Model replies in text, no tool callAnthropicInstruction not clearName the tool and the trigger; check stop_reason and ask again
422 invalid_valueEveryInfraValue not in catalog allowed_valuesChange one field per did_you_mean; no charge
503 that repeatsEveryInfraThe platform is unstable; our calls without suspect values also got it. With reason: access_blocked, the target page needs a login or is restrictedWait retry_after; after repeated failures, a person checks; for access_blocked, change the target
200, but language or fields look wrongEveryInfraA value that the catalog text does not list was accepted and changed the result. As with date and sort on trustpilot/reviews before the evening fixBlock it with a client enum; check the catalog text
200 with 0 rowsEveryInfraNo data on the target page that dayAlready refunded; change the target or the capability

The last three rows come from our tests, and the first four come from the Anthropic documentation. Put the sixth row into code, because other parameters can have the same problem. Write every enum that you copied from catalog text into the schema. After each response, check the language mix and key fields against a baseline. If they differ, mark the call for a person. In our control test, 7 of the 20 reviews for the wrong values were not in English. Two fields were empty in all 20. A simple check finds this at once.

Recent changes that matter for this setup

DateChangeWhat it means for you
September 22, 2026Opus 5.5 launch; thinking cannot be turned off; forced tool_choice returns 400Remove forced calls before you move from Opus 5; use auto plus strict
September 28, 2026Sonnet 5.5 launch; also rejects forced tool_choiceA move back to Sonnet does not avoid the change
October 7, 2026Haiku 5.5 launch; 1M context; batch price $0.05 / $0.25Model cost for bulk grouping is now close to the data fee
October 15, 2026Models API reports between_tools thinking support; Opus 5.5 fast mode leaves research previewCheck model features in code, not from the model ID
October 21, 2026API version 2026-10-21 and new SDKs (Python 2.0.0 and others)Check for old fields such as output_format when you update the SDK
October 22, 2026Claude through Google Cloud, Anthropic managedAnother billing path for batch work; strict usage does not change
October 28, 2026Messages request size limit goes from 32 MB to 128 MBMore reviews fit in one request, but cost follows tokens
October 29, 2026Usage and Cost Analytics API in beta, grouped by model, workspace and keySplit model cost by task and compare it with the data fee
October 30, 2026Fast mode for Opus 4.8 to be removed on November 30, 2026Plan a move if you run live extraction on that model

These items come from the API release notes, updated on October 30, 2026, and the API version migration guide. The most important item for this article is the Haiku 5.5 launch on October 7, 2026. Before it, bulk grouping on Haiku 4.5 in batches cost $0.50 / $2.50, ten times more, and the model cost was far above the data fee. Now the two are of similar size, so the data API price becomes a real factor.

Another item is from September 22, 2026: a mid-conversation system message can carry a full tool definition, in beta. It lets you add a strict tool mid-session without breaking the prompt cache. Anthropic lists it as one replacement for forced calls.

Frequently asked questions

Can I still force tool use in Claude?

This question comes from the search suggestion "claude force tool use". Not on Fable 5.1, Mythos 5.1, Opus 5.5 or Sonnet 5.5. A tool_choice of any or tool returns a 400, and the token counting endpoint applies the same check. auto and none still work. Keep auto, add strict: true to your tools, and say in the user message when to use each tool. If a tool must run on the current turn, the Fable 5.1 migration guide suggests a mid-conversation system message.

What do I do when claude tool_choice is auto and the model does not call the tool?

This comes from the suggestion "claude tool_choice". Anthropic says that Fable 5.1 follows explicit tool instructions reliably. So first, make the instruction clear: name the tool and the trigger. Second, check stop_reason in your loop.

If the model replied in text and you need data, add a user message that asks for the call. Third, write a clear tool description. The define tools page calls detailed descriptions "by far the most important factor in tool performance".

Do claude structured outputs work on Bedrock?

This comes from the suggestion "claude structured outputs bedrock". The availability table on the strict tool use page lists Amazon Bedrock, including InvokeModel, and Google Cloud. The structured outputs page says "all supported platforms" and "all models". Fable models need 30-day data retention and are not covered by zero data retention. Check the data retention page before you use them.

How do I use claude structured output with pydantic?

This comes from the suggestion "claude structured output pydantic". The structured outputs page recommends that you pass a Pydantic model to client.messages.parse(). The SDK changes the schema and moves unsupported limits, such as minimum and maxLength, into descriptions. Then it checks the response against the original schema with all limits.

For EveryInfra, write the catalog allowed_values as Literal[...], which becomes an enum. Write the limit range with Field(ge=1, le=200), and the SDK checks it locally. In the catalog, six capabilities say that values above the maximum are capped.

Should I use claude structured outputs api and strict tools in the same request?

This comes from the suggestion "claude structured outputs api". Yes, you can. The "Feature compatibility" section of the structured outputs page says both can run in one request. They share the limits of 20 strict tools, 24 optional parameters and 16 union-type parameters, so keep the output schema fully required too.

How to start

  1. Read the catalog. GET https://api.everyinfra.com/api/v1/social/catalog?platform=trustpilot is free and needs no key. It gives parameters, allowed values and prices.
  2. Write strict tools with the six rules above. Make params required, write allowed_values as enum, and put ranges in descriptions.
  3. Get a key in the quickstart. Send one request with a wrong enum, and check that you get a 422 with did_you_mean.
  4. For bulk work, use a large limit and "mode": "async". On the Claude side, use Message Batches.

Platform pages: Trustpilot Scraper API, App Store Scraper API and Amazon Scraper API. Capability pages: Trustpilot reviews, App Store reviews and Amazon reviews. More review pages: G2 reviews and Google Play reviews. To connect the remote MCP server in Claude with no code, read remote MCP setup.

For review data as a product, read review data as a paid product. Also read one SKILL.md for four AI tools. For parallel data pulls with subagents, read Claude Code subagents for TikTok brand accounts. Compare capability prices in the data market.

References

  1. What's new in Claude Opus 5.5 (Forced tool use is not supported), Anthropic, September 22, 2026, https://platform.claude.com/docs/en/models/opus-5-5/whats-new-opus-5-5
  2. What's new in Claude Fable 5.1, Anthropic, September 1, 2026, https://platform.claude.com/docs/en/models/fable-5-1/whats-new-fable-5-1
  3. What's new in Claude Sonnet 5.5, Anthropic, September 28, 2026, https://platform.claude.com/docs/en/models/sonnet-5-5/whats-new-sonnet-5-5
  4. Claude Opus 5.5 migration guide, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/models/opus-5-5/migration-guide
  5. Claude Fable 5.1 migration guide, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/models/fable-5-1/migration-guide
  6. Claude Sonnet 5.5 migration guide, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/models/sonnet-5-5/migration-guide
  7. API release notes, Anthropic, updated October 30, 2026, https://platform.claude.com/docs/en/release-notes/overview
  8. Strict tool use, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use
  9. Structured outputs, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/structured-outputs
  10. Define tools, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools
  11. Handle tool calls, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls
  12. Tool use overview, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview
  13. How tool use works, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/how-tool-use-works
  14. Troubleshooting tool use, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/troubleshooting-tool-use
  15. Parallel tool use, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use
  16. Tool runner, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-runner
  17. Tool search tool, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool
  18. Programmatic tool calling, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/tool-use/programmatic-tool-calling
  19. Batch processing, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/batch-processing
  20. Create a Message Batch (API reference), Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/api/messages/batches/create
  21. Pricing, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/about-claude/pricing
  22. Prompt caching, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/prompt-caching
  23. Token counting, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/token-counting
  24. Rate limits, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/api/rate-limits
  25. Errors, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/api/errors
  26. Models overview, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/models/overview
  27. Claude Haiku 5.5 overview, Anthropic, October 7, 2026, https://platform.claude.com/docs/en/models/haiku-5-5/overview
  28. Claude Opus 5.5 overview, Anthropic, September 22, 2026, https://platform.claude.com/docs/en/models/opus-5-5/overview
  29. Claude Mythos 5.1 overview, Anthropic, September 1, 2026, https://platform.claude.com/docs/en/models/mythos-5-1/overview
  30. Effort, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/effort
  31. Streaming, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/streaming
  32. Refusals and fallback, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback
  33. Citations, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/build-with-claude/citations
  34. MCP connector, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/mcp-connector
  35. Remote MCP servers, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/agents-and-tools/remote-mcp-servers
  36. Migrating to API version 2026-10-21, Anthropic, October 21, 2026, https://platform.claude.com/docs/en/api/migration-2026-10-21
  37. API and data retention, Anthropic, read November 1, 2026, https://platform.claude.com/docs/en/manage-claude/api-and-data-retention
  38. Model Context Protocol specification 2025-11-25: Tools, MCP, https://modelcontextprotocol.io/specification/2025-11-25/server/tools
  39. JSON Schema Validation, draft 2020-12, JSON Schema, https://json-schema.org/draft/2020-12/json-schema-validation
  40. JSONSchemaBench, Geng et al., arXiv 2501.10868, 2025, https://arxiv.org/abs/2501.10868
  41. Ratings, reviews, and responses, Apple Developer, read November 1, 2026, https://developer.apple.com/app-store/ratings-and-reviews/
  42. EveryInfra data catalog (GET /api/v1/social/catalog), EveryInfra, read November 1, 2026 at 00:46 SGT, https://api.everyinfra.com/api/v1/social/catalog

Reference BL-60