Search DevTools

Jump to any tool or page

API Response → TypeScript / Zod / Prisma

Convert your API responses or OpenAPI/Swagger specifications into TypeScript types, Zod schemas, and Prisma models with a single click.

Settings

Options

Input

paste an API response or OpenAPI spec

Output

Generate models and they appear here.

About API Response → Models

Paste a raw API response, or an OpenAPI (v3) / Swagger document, and this tool infers a schema from it and generates TypeScript types, a Zod validation schema, and a Prisma model in one pass. Switch between the three with the output format control above.

Conversion flow

  1. Paste raw JSON, or toggle OpenAPI/Swagger input and paste a spec.
  2. The service parses the input and infers a schema from its shape.
  3. TypeScript types, a Zod schema, and a Prisma model are generated together.

TypeScript output

Given a nested API response:

{ "user": { "id": 1, "email": "test@example.com" } }

the tool generates:

export interface User {
  id: number;
  email: string;
}

export interface Root {
  user: User;
}

Zod output

The same shape becomes a validation schema:

export const UserSchema = z.object({
  id: z.number(),
  email: z.string().email(),
});

export const RootSchema = z.object({
  user: UserSchema,
});

Prisma output

And a database model:

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
}

FAQ

What does "Detect ISO dates" do?

When enabled, string fields that look like ISO 8601 timestamps (for example created_at) are typed as dates instead of plain strings.

What does "Optionality" control?

Smart marks a field optional only when it's missing from some sample objects. All optional and all required force every field one way regardless of the samples.

Can I generate models from an OpenAPI spec instead of a JSON sample?

Yes. Enable OpenAPI/Swagger input and paste the spec — the generator reads the first schema in components.schemas, or the first example response, as the source shape.

API Development

About API to Models

Paste a JSON response and get typed model definitions — TypeScript interfaces, or classes for other languages — inferred from the sample. Inference from a single payload is structurally lossy: a null field, an empty array, and an absent key all look the same to a generator, and the type it emits is a guess about which of those the API actually meant.

Frequently asked questions

Why does one sample produce the wrong optionality?
A generator sees the keys present in the payload you gave it and marks everything required. Fields the API omits when empty appear optional only if you supply a sample where they are missing. The reverse error is just as common: a field that happens to be null in your sample becomes string | null when it is never null in practice. Feed several representative responses, including error and empty-collection cases, before trusting the shape.
How should dates and timestamps be typed?
JSON has no date type, so an ISO 8601 string infers as string and a Unix epoch infers as number. Neither is wrong, but both push parsing into every call site. A useful convention is to keep the wire type honest in the generated model and convert at a boundary layer, because doing it in the model implies the deserialiser will run — which it will not if you are casting a fetch result. Watch for epochs in seconds where code expects milliseconds; the resulting dates land in 1970.
What goes wrong with numbers in generated models?
Everything numeric infers as number in TypeScript, which is an IEEE 754 double. Identifiers beyond 2^53-1 have already lost precision by the time JSON.parse returns, so no model can rescue them — the fix is a string on the wire, or BigInt with a custom reviver. Monetary values have the parallel problem: 0.1 plus 0.2 is not 0.3, so amounts belong as integer minor units or decimal strings, and a generated number type quietly endorses the wrong choice.
Do the generated types actually validate anything at runtime?
TypeScript interfaces are erased at compile time. Casting a fetch result to an interface asserts a shape without checking it, so a schema change ships to production as an undefined property access deep in a component rather than an error at the boundary. If correctness matters, generate a runtime schema — Zod, io-ts, or similar — and derive the static type from it, so one definition covers both the compiler and the actual bytes arriving.
How are heterogeneous arrays and dynamic keys handled?
An array whose elements differ structurally, such as a feed of mixed event types, infers as a union of every observed shape or, worse, as an intersection where everything is optional. The clean fix is a discriminated union keyed on a type field, which a generator cannot infer without being told which field discriminates. Objects used as maps — keys that are IDs rather than fixed field names — should become Record<string, T> by hand, since inference will otherwise emit one property per sampled key.