<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup" -->

---
title: OpenAPI tutorial: document and validate a REST API
description: A hands-on guide to building a books REST API using Hono, Zod, and OpenAPI. Covers defining reusable schemas with Zod, creating typed route definitions,...
canonical: https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: OpenAPI tutorial: document and validate a REST API | daily.dev
og:description: A hands-on guide to building a books REST API using Hono, Zod, and OpenAPI. Covers defining reusable schemas with Zod, creating typed route definitions,...
og:url: https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup
og:image: https://api.daily.dev/og/posts/kJyodzFuP.png
og:image:alt: OpenAPI tutorial: document and validate a REST API
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAPI tutorial: document and validate a REST API

**[Flavio Copes](https://daily.dev/sources/flaviocopes)** · 8 min read · 1 upvotes · 1 comments

## Summary

A hands-on guide to building a books REST API using Hono, Zod, and OpenAPI. Covers defining reusable schemas with Zod, creating typed route definitions, validating request bodies and path parameters, generating an OpenAPI 3.1 JSON document, mounting interactive Scalar documentation, generating TypeScript client types with openapi-typescript, writing contract tests with Vitest, detecting breaking changes in CI, and comparing design-first vs code-first workflows. Also includes guidance on what a production-ready OpenAPI document should contain.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://flaviocopes.com/openapi-tutorial>

## Questions this post answers

### How do I generate TypeScript types from an OpenAPI document?

Install openapi-typescript as a dev dependency, then run npx openapi-typescript against your running server's OpenAPI JSON endpoint with an --output flag pointing to a destination file, such as src/api-types.d.ts. The generated file contains TypeScript types for paths, operations, and schemas, and should never be edited directly - regenerate it whenever the API schema changes.

_Generating typed clients from OpenAPI specs gets easier with implementation notes developers curate on daily.dev._

### How do I detect breaking changes in my REST API before deploying?

Save the released OpenAPI document in the repository or pull it from production, then compare it against the new document with an OpenAPI diff tool in CI. Breaking changes typically include removing an endpoint or response field, making an optional field required, changing a field's type, or removing an accepted enum value; adding an optional response field is usually safe if clients ignore unknown fields.

_Teams tracking API contract changes swap CI diffing tips like this on daily.dev._

### Should I design an OpenAPI contract first or generate it from code?

Neither approach is automatically better: design-first, writing openapi.yaml before implementing and generating server stubs and clients from it, works well when multiple teams must agree before implementation starts, while code-first, generating the document from route definitions, reduces duplication in a smaller TypeScript project. The worst option is a handwritten document nobody checks against the running API, since it goes stale and misleads clients.

_Weighing design-first against code-first API workflows is easier with real comparisons on daily.dev._

## Community discussion

Top comments from developers on daily.dev.

**@agustinbarrientos** · 0 upvotes

> How noisy has the schema-break check been in CI?

## Similar posts on daily.dev

- [How to Build Type-Safe APIs with Hono and Zod](https://daily.dev/posts/how-to-build-type-safe-apis-with-hono-and-zod-0aku3long) · freeCodeCamp · 1 upvotes · 0 comments
- [Document Your Spring REST APIs with Annotations](https://daily.dev/posts/document-your-spring-rest-apis-with-annotations-hhsdellg2) · Foojay.io · 21 upvotes · 0 comments
- [Zod \+ TypeScript: Schema Validation Made Easy](https://daily.dev/posts/zod-typescript-schema-validation-made-easy-w9edwu63u) · Telerik · 1 upvotes · 1 comments
- [Stop Writing REST APIs From Scratch in 2025](https://daily.dev/posts/stop-writing-rest-apis-from-scratch-in-2025-whupvklwz) · LogRocket · 278 upvotes · 14 comments

---

Tags: [#typescript](https://daily.dev/tags/typescript), [#rest-api](https://daily.dev/tags/rest-api), [#openapi](https://daily.dev/tags/openapi), [#zod](https://daily.dev/tags/zod)

[View this post on daily.dev](https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"OpenAPI tutorial: document and validate a REST API","url":"https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup"},"datePublished":"2026-07-22T07:50:06.788Z","dateModified":"2026-09-14T09:17:08.955Z","description":"A hands-on guide to building a books REST API using Hono, Zod, and OpenAPI. Covers defining reusable schemas with Zod, creating typed route definitions,...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/907c6c028f107fad7d0379f1571dde35?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/907c6c028f107fad7d0379f1571dde35?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Flavio Copes","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Flavio Copes","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/1f2dbd275797411bbd37bfdaaf0951a9","url":"https://daily.dev/sources/flaviocopes"},"commentCount":1,"discussionUrl":"https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":1}],"keywords":"typescript,rest-api,openapi,zod","timeRequired":"PT8M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Flavio Copes","item":"https://daily.dev/sources/flaviocopes"},{"@type":"ListItem","position":3,"name":"OpenAPI tutorial: document and validate a REST API"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup","comment":[{"@type":"Comment","text":"How noisy has the schema-break check been in CI?","datePublished":"2026-08-01T19:04:32.939Z","url":"https://daily.dev/posts/kJyodzFuP#c-DpekCnmo0","author":{"@type":"Person","name":"Agustin Barrientos","url":"https://daily.dev/agustinbarrientos","image":"https://media.daily.dev/image/upload/s--5ayxQnqn--/f_auto/v1788281802/avatars/avatar_wQYYVe5Tbj0NJ7C7qPoa8?_a=BAMAMicg0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/openapi-tutorial-document-and-validate-a-rest-api-kjyodzfup#faq","mainEntity":[{"@type":"Question","name":"How do I generate TypeScript types from an OpenAPI document?","acceptedAnswer":{"@type":"Answer","text":"Install openapi-typescript as a dev dependency, then run npx openapi-typescript against your running server's OpenAPI JSON endpoint with an --output flag pointing to a destination file, such as src/api-types.d.ts. The generated file contains TypeScript types for paths, operations, and schemas, and should never be edited directly - regenerate it whenever the API schema changes. Generating typed clients from OpenAPI specs gets easier with implementation notes developers curate on daily.dev."}},{"@type":"Question","name":"How do I detect breaking changes in my REST API before deploying?","acceptedAnswer":{"@type":"Answer","text":"Save the released OpenAPI document in the repository or pull it from production, then compare it against the new document with an OpenAPI diff tool in CI. Breaking changes typically include removing an endpoint or response field, making an optional field required, changing a field's type, or removing an accepted enum value; adding an optional response field is usually safe if clients ignore unknown fields. Teams tracking API contract changes swap CI diffing tips like this on daily.dev."}},{"@type":"Question","name":"Should I design an OpenAPI contract first or generate it from code?","acceptedAnswer":{"@type":"Answer","text":"Neither approach is automatically better: design-first, writing openapi.yaml before implementing and generating server stubs and clients from it, works well when multiple teams must agree before implementation starts, while code-first, generating the document from route definitions, reduces duplication in a smaller TypeScript project. The worst option is a handwritten document nobody checks against the running API, since it goes stale and misleads clients. Weighing design-first against code-first API workflows is easier with real comparisons on daily.dev."}}]}
```

