OpenAPI Specification
openapi-spec.Given a Film with the following structure:
We want our Spring Boot application to expose these endpoints:
/api/filmslist all films./api/films/{id}get film by identifier.
OpenAPI Specification
The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to HTTP APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined, a consumer can understand and interact with the remote service with a minimal amount of implementation logic.
For better visualization you can copy-paste the OpenAPI Specification YAML file from the codebase into Swagger Editor or use OpenAPI (Swagger) Editor in IntelliJ IDEA.
-
All error responses would look like this:
-
/api/filmsresponses would look like this: -
/api/films/{id}responses would look like this:
The Envelope Pattern
You might be looking at the response examples and thinking, "What's with all that extra fluff? Why wrap the actual film data inside a data object?"
That is a deliberate choice called the Envelope Pattern. And once you start using it, you'll never go back.
Think of it like physical mail. Every piece of mail you get, whether it's a birthday card or a bill, comes in an envelope. The envelope has standard information on it: a return address, a destination address, a stamp. The actual message is inside.
Our API responses work the same way. The ResponseMetadata schema is our envelope.
Every single response from the API, whether it's a success (200 OK) or an error (404 Not Found, 500 Internal Server Error, etc.), will have this same top-level structure.
- The actual payload goes inside the
dataproperty for successful responses. - For errors, we swap
datafortitleanddetailso we keep adhering to Problem Details for HTTP APIs.
Why Bother?
Consistency. That's the whole game.
- Client side sanity: The developer building the frontend or mobile app can write one piece of code to handle all API responses. They always know where to find the
traceID to show a user reporting a bug. They can build a generic error handler that always looks fortitleanddetail. They aren't guessing whether the payload is the object itself, an array, or some weird error shape. - Future proofing: What if we need to add some other metadata? No problem. We just add a new field to the envelope level. The
datapart remains untouched, and we don't break the client's parsing logic for the actual film data. - It just looks professional: An API with a consistent response structure feels solid and well-thought-out. An inconsistent one feels amateurish and is a pain to work with.
Pagination
The/api/films endpoint "lists all films." But if you take that literally in the real world, you're gonna have a bad time.
Imagine your database has a million films. Trying to pull all of them in one go is a recipe for disaster. Your database will crash, your server's memory will evaporate, and the poor user's browser will crash trying to render a colossal JSON payload.
This is where pagination comes in. It's the simple idea of breaking a large result set into smaller, manageable "pages." Instead of asking for all the films, you ask for "page 1 with 20 films," then "page 2 with 20 films," and so on.
This is standard practice everywhere. Think about Google search results or browsing products on Amazon. You never get everything at once; you get a page and a "Next" button.
For the sake of keeping things simple right now, the specification doesn't include pagination parameters. We'll add proper pagination later.