JSON Schema to Zod
schema.convert_json_schema_to_zod
Overview
You send a JSON Schema and name the Zod major you are on, and we return TypeScript source declaring one constant per definition and one for the root, with the optional z.infer type aliases beside them. The mapping is published per major, because Zod 4 moved string formats to top-level factories and changed z.record, so a single undifferentiated target would emit code that fails to compile on one of the two. Anything Zod cannot express — if/then/else, dependent schemas, propertyNames, contains, unevaluated keywords, not — becomes z.unknown() with a warning naming the pointer and the construct and lossy set true, or a refusal if you would rather not ship a silent gap. Nothing here compiles or runs JavaScript: the answer is text.
Generated TypeScript types vanish at run time, so the boundary where untrusted JSON actually arrives is exactly where they stop helping. A runtime validator is the missing half, and hand-writing it beside a schema is how the two drift apart.
Reliability
The same schema and options always produce byte-identical source, independent of your machine's locale, time zone and default character set. Definitions are emitted before the declarations that reference them, so the file evaluates in order. Twelve refusals stop the call and an unchanged retry will not help. ZOD_SCHEMA_INVALID means schema is absent, is not an object, or holds a reference to a location that is not in the document; ZOD_SCHEMA_TOO_LARGE means it is over 262144 bytes; ZOD_OPTION_INVALID means an option is outside its published range, including a rootSchemaName outside 1 to 128 characters; ZOD_TARGET_UNSUPPORTED means target is neither ZOD_4 nor ZOD_3; ZOD_CONSTRUCT_UNSUPPORTED is raised only under unknownConstruct REFUSE and names the pointer and the construct; ZOD_REF_REMOTE_REFUSED, ZOD_REF_CYCLE_DETECTED and ZOD_REF_DEPTH_EXCEEDED are the reference refusals; ZOD_NODE_LIMIT_EXCEEDED means over 20000 nodes, deeper than 64 levels, a per-object cap broken, or over 100000 nodes once local references were expanded; ZOD_DECLARATION_LIMIT_EXCEEDED means the schema needs more constants than maxDeclarations allows; ZOD_WORK_REFUSED means the run was projected past the 2000000-unit budget before it started and reports both numbers; and ZOD_OUTPUT_TOO_LARGE means the source would pass 1048576 characters or the 2 MiB response ceiling.
Context footprint
The answer is dominated by zodCode, which is roughly the size of the schema you sent; warnings are one short line each and capped at 200. A successful call costs 1 execution credit.
When to use it
When a TypeScript codebase needs to check incoming JSON against a schema it already publishes.
When you want compile-time types only, or when you want to validate a document rather than generate a validator.
Scope
Non-goals
- We never compile, evaluate or execute the code we emit — zod is not on our classpath and no script engine is
- We never validate a document: this produces a validator, it does not run one
- We never guess the Zod major; the mapping differs, so you declare it
- We never silently drop a construct: anything unmappable is warned or refused
- We never fetch a reference outside the document you sent
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
How we handle your data
What this means
This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.
Squillify guarantees
- Runs inside Squillify
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response may contain submitted or transformed content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| schema | object | Yes | JSON Schema to convert, 2 through 262144 bytes; extra keys are schema keywords and only same-document #/ references resolve. — unconstrained RFC 8259 JSON items. |
| options | object | No | Closed conversion options; omit the object for Zod 4, root name Root, type exports, descriptions, WARN_AS_UNKNOWN and 500 declarations. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| zodCode | string | Yes | Generated TypeScript Zod source with two-space indent, LF endings and a trailing newline. |
| targetApplied | string | Yes | Zod major the mapping actually ran under. |
| emittedRootName | string | Yes | Constant holding the root schema after sanitisation. |
| declarations | array | Yes | Emitted constant names in source order, 0 through 500 strings. |
| lossy | boolean | Yes | True when at least one construct became z.unknown(). |
| warnings | array | Yes | Unmappable constructs, 0 through 200 closed {pointer, construct, code, message} objects. |
| summary | object | Yes | Closed size receipt with nodeCount, declarationCount, codeBytes and whether the warning list was truncated. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"schema.convert_json_schema_to_zod","input":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("schema.convert_json_schema_to_zod", {"options":{"rootSchemaName":"Order"},"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"total":{"type":"number","minimum":0},"shipTo":{"$ref":"#/$defs/address"}},"required":["id","total"],"$defs":{"address":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| ZOD_SCHEMA_INVALID | 400 | No | The request payload failed this skill's input validation. |
| ZOD_SCHEMA_TOO_LARGE | 429 | No | A size, quota, rate, or time limit was exceeded. |
| ZOD_OPTION_INVALID | 400 | No | The request payload failed this skill's input validation. |
| ZOD_TARGET_UNSUPPORTED | 400 | No | The skill does not support the requested variant. |
| ZOD_CONSTRUCT_UNSUPPORTED | 400 | No | The skill does not support the requested variant. |
| ZOD_REF_REMOTE_REFUSED | 400 | No | The request payload failed this skill's input validation. |
| ZOD_REF_CYCLE_DETECTED | 400 | No | The request payload failed this skill's input validation. |
| ZOD_REF_DEPTH_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| ZOD_NODE_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| ZOD_DECLARATION_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| ZOD_WORK_REFUSED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| ZOD_OUTPUT_TOO_LARGE | 429 | No | A size, quota, rate, or time limit was exceeded. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- We never compile, evaluate or execute the code we emit — zod is not on our classpath and no script engine is
- We never validate a document: this produces a validator, it does not run one
- We never guess the Zod major; the mapping differs, so you declare it
- We never silently drop a construct: anything unmappable is warned or refused
- We never fetch a reference outside the document you sent
- Validating a document against a schema, which schema.validate_json does
- Producing compile-time types only, which schema.convert_json_schema_to_typescript does
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "schema.convert_json_schema_to_zod",
"input": {
"options": {
"rootSchemaName": "Order"
},
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"total": {
"type": "number",
"minimum": 0
},
"shipTo": {
"$ref": "#/$defs/address"
}
},
"required": [
"id",
"total"
],
"$defs": {
"address": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
}
}
}Examples
A schema with a definition, a format and an optional property
{
"options": {
"rootSchemaName": "Order"
},
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"total": {
"type": "number",
"minimum": 0
},
"shipTo": {
"$ref": "#/$defs/address"
}
},
"required": [
"id",
"total"
],
"$defs": {
"address": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
}
}{
"zodCode": "import { z } from \"zod\";\n\nexport const AddressSchema = z.object({\n city: z.string(),\n});\n\nexport type Address = z.infer<typeof AddressSchema>;\n\nexport const OrderSchema = z.object({\n id: z.uuid(),\n total: z.number().min(0),\n shipTo: AddressSchema.optional(),\n});\n\nexport type Order = z.infer<typeof OrderSchema>;\n",
"emittedRootName": "OrderSchema",
"lossy": false,
"summary": {
"nodeCount": 22,
"declarationCount": 2,
"codeBytes": 317,
"truncated": false
},
"targetApplied": "ZOD_4",
"declarations": [
"AddressSchema",
"OrderSchema"
],
"warnings": []
}A construct Zod cannot express, reported rather than hidden
{
"options": {
"rootSchemaName": "Event",
"emitTypeExports": false
},
"schema": {
"type": "object",
"properties": {
"payload": {
"not": {
"type": "string"
}
}
}
}
}{
"zodCode": "import { z } from \"zod\";\n\nexport const EventSchema = z.object({\n payload: z.unknown().optional(),\n});\n",
"emittedRootName": "EventSchema",
"lossy": true,
"summary": {
"nodeCount": 6,
"declarationCount": 1,
"codeBytes": 103,
"truncated": false
},
"targetApplied": "ZOD_4",
"declarations": [
"EventSchema"
],
"warnings": [
{
"pointer": "/properties/payload",
"construct": "not",
"code": "ZOD_CONSTRUCT_UNSUPPORTED",
"message": "This construct has no Zod equivalent, so the generated validator accepts any value here."
}
]
}Recommended use cases
- Generate a runtime validator to sit beside generated TypeScript types
- Turn a published tool schema into a Zod parser for a TypeScript client
- Check, before adopting Zod, how much of a schema it can actually express
Avoid for
- Validating a document against a schema, which schema.validate_json does
- Producing compile-time types only, which schema.convert_json_schema_to_typescript does
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.