Structured extraction
Pass a JSON Schema and get back only the fields you need, extracted with AI.
Supply a JSON Schema in the jsonSchema field and the response body becomes the structured
data extracted from the page and coerced into your schema — instead of the raw page response.
curl https://request.usestring.ai/v1/fetch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.example.com/listing/123",
"jsonSchema": {
"type": "object",
"properties": {
"title": { "type": "string" },
"price": { "type": ["number", "null"] },
"condition": { "type": "string", "enum": ["New", "Used"] }
},
"required": ["title"]
}
}'The response is the coerced object:
{ "title": "2027 Keystone COUGAR 316RLS", "price": 69674, "condition": "New" }Rules and bounds
- Must be a valid JSON Schema object — shorthand like
{ "title": "string" }is rejected with a400. formatmust bejson(the default). SupplyingjsonSchemawithformat: raworformat: markdownis a400.- Bounds: maximum nesting depth 10, maximum 200 keys, and 50 KB when serialized.
- List the fields you require in the schema's
requiredarray.
Fallback behavior
If extraction can't produce the fields you marked as required, the request falls back to the standard format: json
response rather than returning a partial object — the page still reaches you, as data:
{ "statusCode": 200, "headers": { "content-type": ["text/html; charset=utf-8"] }, "data": "<html>…</html>" }Detecting a fallback
Every jsonSchema response tells you which of the two it is. Branch on the header, not the body shape:
| Header | Value |
|---|---|
x-json-schema-applied | true — the body is your extracted object. false — the body is the fallback envelope above. |
x-json-schema-fallback-reason | Present only when applied is false. One of the reasons below. |
| Reason | What happened | Extraction fee |
|---|---|---|
schema_mismatch | Extraction ran, but the page didn't yield a required field (or the top-level type didn't match). Retrying won't help — adjust the schema or the target. | charged |
unparseable_output | Extraction ran but returned nothing usable. Usually transient; worth a retry. | charged |
llm_error | The extraction call itself failed. Transient; worth a retry. | not charged |
body_too_large | The page exceeded the extraction size ceiling, so extraction was skipped. | not charged |
empty_body | The destination returned an empty body, so there was nothing to extract. | not charged |
Extraction adds a dynamic fee
Structured extraction adds a fee on top of the per-request rate, metered per request and scaled to the page size and
schema. The fee applies whenever extraction runs — including the fallbacks where it ran and the result didn't
satisfy your schema (schema_mismatch, unparseable_output). It isn't charged when extraction never ran
(body_too_large, empty_body) or didn't complete (llm_error). See Pricing.