Tools mentioned in this article
Open the browser-based tool while you read and try the workflow immediately.
When integrating with an API, the response example is often the most useful source of truth.
Even if the documentation describes the fields, the real response may include null, optional arrays, or environment-specific fields that are easy to miss.
This workflow uses a JSON response as the starting point, then turns it into TypeScript types and a Zod schema for safer implementation.
Start with a real response
Suppose an API returns user data like this.
{
"id": 42,
"name": "Ada Lovelace",
"email": "ada@example.com",
"roles": ["admin", "editor"],
"profile": {
"company": "Example Inc.",
"timezone": "Asia/Tokyo"
},
"lastLoginAt": null
}
First, paste it into the JSON formatter.
This makes the structure easier to scan and helps catch syntax problems before generating anything from it.
Generate TypeScript types
Next, use the JSON to TypeScript tool to generate a type from the response shape.
export interface UserResponse {
id: number;
name: string;
email: string;
roles: string[];
profile: Profile;
lastLoginAt: null;
}
export interface Profile {
company: string;
timezone: string;
}
At this point, review the generated type instead of pasting it blindly.
For example, lastLoginAt may be string | null in the actual API, even if the sample response only contains null.
Add runtime validation with Zod
Types help during development, but they do not validate data at runtime.
If the response comes from an external service, generate a Zod schema as well.
const UserResponseSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string(),
roles: z.array(z.string()),
profile: z.object({
company: z.string(),
timezone: z.string()
}),
lastLoginAt: z.null()
});
Then adjust the schema to match the real contract.
lastLoginAt: z.string().datetime().nullable()
That small edit makes the schema useful beyond the single example response.
What to check before review
- Fields that may be
null - Arrays that may be empty
- Optional fields that are missing from the sample
- Date strings that need stricter validation
- IDs that may be strings in another environment
This keeps the implementation grounded in real data while still leaving room for the actual API contract.