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
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>
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
Four output formats. Same engine, your choice of target:
-
zod— Zod schema + inferred type -
typebox— TypeBox withStatic<> -
typescript— plainexport 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"]}}}
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
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.