Skip to content

OpenAPI Example

This example demonstrates a complete OpenAPI specification for a Planets API that showcases reusable components, proper schema design, and both GET and POST operations.

openapi: 3.2.0
info:
title: Planets API
description: |
A comprehensive API for managing planetary data in our solar system and beyond.
This API allows you to retrieve information about planets and add new planetary discoveries.
version: 1.0.0
contact:
name: Space Research Team
email: api-support@space-research.com
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://api.space-research.com/v1
description: Production server
- url: https://staging-api.space-research.com/v1
description: Staging server for testing
paths:
/planets:
get:
summary: Retrieve all planets
description: |
Returns a paginated list of all planets in the database.
Results can be filtered and sorted using query parameters.
tags:
- Planets
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/PageSizeParam'
- $ref: '#/components/parameters/SortParam'
- name: system
in: query
description: Filter planets by solar system
required: false
schema:
type: string
example: "Solar System"
- name: habitable
in: query
description: Filter by habitability status
required: false
schema:
type: boolean
example: true
responses:
'200':
description: Successfully retrieved planets
content:
application/json:
schema:
$ref: '#/components/schemas/PlanetListResponse'
examples:
solar_system_planets:
summary: Planets in our solar system
value:
planets:
- id: 1
name: "Earth"
system: "Solar System"
distanceFromStar: 149.6
radius: 6371
mass: 5.972e24
habitable: true
discoveryDate: "1543-05-24"
atmosphere:
composition:
- gas: "Nitrogen"
percentage: 78.08
- gas: "Oxygen"
percentage: 20.95
hasAtmosphere: true
- id: 2
name: "Mars"
system: "Solar System"
distanceFromStar: 227.9
radius: 3390
mass: 6.39e23
habitable: false
discoveryDate: "1543-05-24"
atmosphere:
composition:
- gas: "Carbon Dioxide"
percentage: 95.32
- gas: "Nitrogen"
percentage: 2.7
hasAtmosphere: true
pagination:
page: 1
page_size: 10
total: 2
totalPages: 1
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Add a new planet
description: |
Creates a new planet record in the database.
All required fields must be provided in the request body.
tags:
- Planets
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePlanetRequest'
examples:
exoplanet_example:
summary: Example exoplanet discovery
value:
name: "Kepler-452b"
system: "Kepler-452"
distanceFromStar: 156.5
radius: 8851
mass: 1.9e25
habitable: true
discoveryDate: "2015-07-23"
atmosphere:
hasAtmosphere: true
composition:
- gas: "Hydrogen"
percentage: 75.0
- gas: "Helium"
percentage: 24.0
responses:
'201':
description: Planet successfully created
content:
application/json:
schema:
$ref: '#/components/schemas/Planet'
example:
id: 42
name: "Kepler-452b"
system: "Kepler-452"
distanceFromStar: 156.5
radius: 8851
mass: 1.9e25
habitable: true
discoveryDate: "2015-07-23"
atmosphere:
hasAtmosphere: true
composition:
- gas: "Hydrogen"
percentage: 75.0
- gas: "Helium"
percentage: 24.0
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
description: Validation error
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
example:
error: "Validation failed"
message: "Invalid planet data provided"
details:
- field: "radius"
issue: "Must be a positive number"
- field: "discoveryDate"
issue: "Must be a valid date in YYYY-MM-DD format"
'500':
$ref: '#/components/responses/InternalServerError'
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT token for authenticated requests
parameters:
PageParam:
name: page
in: query
description: Page number for pagination (starts from 1)
required: false
schema:
type: integer
minimum: 1
default: 1
example: 1
PageSizeParam:
name: page_size
in: query
description: Number of items per page
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 10
example: 10
SortParam:
name: sort
in: query
description: Sort field and direction (field:asc or field:desc)
required: false
schema:
type: string
enum: ["name:asc", "name:desc", "radius:asc", "radius:desc", "discoveryDate:asc", "discoveryDate:desc"]
default: "name:asc"
example: "name:asc"
schemas:
Planet:
type: object
required:
- id
- name
- system
- distanceFromStar
- radius
- mass
- habitable
- discoveryDate
properties:
id:
type: integer
description: Unique identifier for the planet
example: 1
readOnly: true
name:
type: string
description: Official name of the planet
minLength: 1
maxLength: 100
example: "Earth"
system:
type: string
description: Name of the solar/planetary system
minLength: 1
maxLength: 100
example: "Solar System"
distanceFromStar:
type: number
description: Distance from the host star in million kilometers
minimum: 0
example: 149.6
radius:
type: number
description: Planet radius in kilometers
minimum: 0
example: 6371
mass:
type: number
description: Planet mass in kilograms (scientific notation supported)
minimum: 0
example: 5.972e24
habitable:
type: boolean
description: Whether the planet is potentially habitable
example: true
discoveryDate:
type: string
format: date
description: Date when the planet was first catalogued (YYYY-MM-DD)
example: "2015-07-23"
atmosphere:
$ref: '#/components/schemas/Atmosphere'
CreatePlanetRequest:
type: object
required:
- name
- system
- distanceFromStar
- radius
- mass
- habitable
- discoveryDate
properties:
name:
type: string
description: Official name of the planet
minLength: 1
maxLength: 100
example: "Kepler-452b"
system:
type: string
description: Name of the solar/planetary system
minLength: 1
maxLength: 100
example: "Kepler-452"
distanceFromStar:
type: number
description: Distance from the host star in million kilometers
minimum: 0
example: 156.5
radius:
type: number
description: Planet radius in kilometers
minimum: 0
example: 8851
mass:
type: number
description: Planet mass in kilograms
minimum: 0
example: 1.9e25
habitable:
type: boolean
description: Whether the planet is potentially habitable
example: true
discoveryDate:
type: string
format: date
description: Date when the planet was discovered (YYYY-MM-DD)
example: "2015-07-23"
atmosphere:
$ref: '#/components/schemas/Atmosphere'
Atmosphere:
type: object
required:
- hasAtmosphere
properties:
hasAtmosphere:
type: boolean
description: Whether the planet has an atmosphere
example: true
composition:
type: array
description: Atmospheric composition breakdown
items:
$ref: '#/components/schemas/AtmosphericComponent'
minItems: 0
example:
- gas: "Nitrogen"
percentage: 78.08
- gas: "Oxygen"
percentage: 20.95
AtmosphericComponent:
type: object
required:
- gas
- percentage
properties:
gas:
type: string
description: Name of the atmospheric gas
minLength: 1
example: "Nitrogen"
percentage:
type: number
description: Percentage of this gas in the atmosphere
minimum: 0
maximum: 100
example: 78.08
PlanetListResponse:
type: object
required:
- planets
- pagination
properties:
planets:
type: array
description: List of planets
items:
$ref: '#/components/schemas/Planet'
pagination:
$ref: '#/components/schemas/PaginationInfo'
PaginationInfo:
type: object
required:
- page
- page_size
- total
- totalPages
properties:
page:
type: integer
description: Current page number
minimum: 1
example: 1
page_size:
type: integer
description: Number of items per page
minimum: 1
example: 10
total:
type: integer
description: Total number of items
minimum: 0
example: 25
totalPages:
type: integer
description: Total number of pages
minimum: 0
example: 3
ErrorResponse:
type: object
required:
- error
- message
properties:
error:
type: string
description: Error type identifier
example: "VALIDATION_ERROR"
message:
type: string
description: Human-readable error message
example: "The request data is invalid"
details:
type: array
description: Additional error details
items:
type: object
properties:
field:
type: string
example: "name"
issue:
type: string
example: "Field is required"
ValidationError:
allOf:
- $ref: '#/components/schemas/ErrorResponse'
- type: object
properties:
details:
type: array
description: Validation error details
items:
type: object
required:
- field
- issue
properties:
field:
type: string
description: Field that failed validation
example: "radius"
issue:
type: string
description: Description of the validation issue
example: "Must be a positive number"
responses:
BadRequest:
description: Bad request - invalid parameters or malformed request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "BAD_REQUEST"
message: "The request parameters are invalid"
Unauthorized:
description: Unauthorized - authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "UNAUTHORIZED"
message: "Authentication required to access this resource"
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: "INTERNAL_SERVER_ERROR"
message: "An unexpected error occurred while processing the request"
tags:
- name: Planets
description: Operations related to planetary data management
  • A schema is a definition of the shape of your data. It describes what fields an object has, what type each field is (string, integer, boolean, etc.), which fields are required, and what constraints apply (e.g., minimum value, max length). Think of it as a blueprint for a JSON object.

  • You can write a schema inline (directly inside an endpoint definition), but if multiple endpoints use the same data structure, you’d be repeating yourself. That’s where the components section comes in. It’s a dedicated place to store reusable definitions. You define a schema once under components > schemas, then reference it anywhere using $ref:

# Define once under components
components:
schemas:
Planet:
type: object
properties:
id:
type: integer
name:
type: string
# Reference anywhere with $ref
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Planet'

The components section can also store reusable parameters, responses, and security schemes. Not just schemas. This keeps your specification DRY (Don’t Repeat Yourself). Update the definition in one place and it applies everywhere.

In this example:

  • Parameters like PageParam, PageSizeParam, and SortParam are defined once and reused across any endpoint that needs pagination.
  • Schemas like Planet and Atmosphere are referenced in both request bodies and responses.
  • Responses like BadRequest and InternalServerError are shared across endpoints instead of duplicating the same error structure.

Real-world data is rarely flat. This example shows how to model relationships between objects:

  • The Planet schema references an Atmosphere object, which in turn contains an array of AtmosphericComponent objects. This mirrors how you’d structure nested JSON in your actual API responses.
  • The ValidationError schema extends ErrorResponse using allOf, which works like inheritance. It includes all fields from ErrorResponse plus its own additional details array.

Notice there are two schemas for planets: Planet (the full object with id) and CreatePlanetRequest (without id). This is a common pattern because:

  • When creating a resource, the client doesn’t provide the id. The server generates it.
  • When returning a resource, the response includes the server-generated id.

In your own specification, consider whether your POST request body needs all the same fields as your GET response.

Every field should have constraints that match your business rules. This example demonstrates:

  • required arrays to mark mandatory fields in each schema.
  • minimum / maximum on numbers (e.g., radius must be positive, percentage must be 0–100).
  • minLength / maxLength on strings to prevent empty or excessively long values.
  • format: date to enforce a specific string format (YYYY-MM-DD).

These constraints help API consumers understand exactly what data is valid before they send a request.

Good examples make your specification usable as a reference during development:

  • Multiple named examples on the GET endpoint (solar_system_planets) show different response scenarios.
  • Error responses include field-level details (e.g., which field failed validation and why), helping developers debug their requests.
  • Consistent error structure (ErrorResponse schema) means consumers can write a single error handler for all endpoints.