Generate Zod schemas from any JSON API — no OpenAPI spec required

typescript dev.to

I built this after the nth time I hand-typed a third-party API response into a Zod schema, squinting at the JSON trying to figure out which fields were nullable.

Tools like orval and openapi-typescript are great — if the API has an OpenAPI spec. But most third-party APIs, internal services, and quick prototypes don't. So I built apitype: point it at any URL or JSON and it infers the full schema from the actual data.

npx @jayeshbansal/apitype https://api.github.com/users/octocat --name GithubUser
Enter fullscreen mode Exit fullscreen mode
import { z } from 'zod'

export const githubUserSchema = z.object({
  login: z.string(),
  id: z.number().int().nonnegative(),
  avatar_url: z.string().url(),
  created_at: z.string().datetime(),
  public_repos: z.number().int().nonnegative(),
  // ...
})

export type GithubUser = z.infer<typeof githubUserSchema>
Enter fullscreen mode Exit fullscreen mode

What makes it more than JSON.parse + guesswork

Format detection. It recognizes 14 string formats from the values — UUID, email, URL, ISO datetime, IP, JWT, CUID, NanoID, base64, semver, hex color — and emits the matching Zod validator (.uuid(), .email(), .datetime()) instead of a bare z.string().

Nullable/optional inference by sampling. A single response can't tell you whether bio is always null or sometimes a string. So apitype can fetch an endpoint N times and merge the samples: a key that's missing in some responses becomes .optional(), a key that's null in some becomes .nullable().

npx @jayeshbansal/apitype https://api.example.com/posts/random --samples 5 --name Post
Enter fullscreen mode Exit fullscreen mode

Four output formats. Same engine, your choice of target:

  • zod — Zod schema + inferred type
  • typebox — TypeBox with Static<>
  • typescript — plain export type, zero runtime
  • jsonschema — JSON Schema draft-07

The part I actually care about: it's an MCP server

The same inference engine runs as a Model Context Protocol server, so AI coding assistants (Claude, Cursor, Windsurf) can call apitype as a tool:

{"mcpServers":{"apitype":{"command":"npx","args":["@jayeshbansal/apitype","--mcp"]}}}
Enter fullscreen mode Exit fullscreen mode

Now when you ask your assistant to "type this API response," it doesn't hallucinate a schema — it calls a deterministic tool that fetched the real data and detected the real formats.

There's also a Vite plugin (regenerate types on dev-server start), a batch config mode (keep a whole API's types in sync in CI), and a programmatic API (import { fromUrl } from '@jayeshbansal/apitype').

When you should not use this

Honesty matters: if your API ships an OpenAPI/Swagger spec, use a spec-based generator. The spec is the source of truth — inference is only as good as the sample responses you feed it. apitype is for the (very common) case where no spec exists.

Try it

npx @jayeshbansal/apitype <url|file>           # one-off, no install
npm install -D @jayeshbansal/apitype           # project dependency
Enter fullscreen mode Exit fullscreen mode

Repo: https://github.com/jayesh-bansal/apitype · MIT, zero runtime deps.

If you hit an API whose shape it gets wrong, open an issue with the response — those are the best test cases.

Source: dev.to

arrow_back Back to Tutorials