API strategy
Platform integration
Definitions in Swagger explained: how to write, reference, compose, and generate the definitions object step by step, with the pitfalls that break most files.

By the end of this guide you will be able to write, reference, and generate the definitions section of a Swagger 2.0 document without copying schemas across every endpoint. You will know how definitions differ from OpenAPI 3's components/schemas, how to reference a schema from a path, and how to generate the whole block from an existing codebase.
Prerequisites: a Swagger 2.0 document you are editing (YAML or JSON), a text editor, and — for the generation step — a running backend in a framework with an OpenAPI/Swagger integration. Roughly 45 minutes end to end.
One clarification before we start. The definitions object exists in Swagger 2.0. In OpenAPI 3.x the same concept moved under components/schemas. If your file starts with swagger: "2.0", follow this guide verbatim. If it starts with openapi: 3.x, the mechanics are identical but the key names change — noted at the end.
Open your Swagger file. Look for a top-level definitions: key. It sits alongside swagger, info, paths, and parameters.
If it isn't there, add it. Order doesn't matter to tooling, but convention is: swagger, info, host, basePath, schemes, paths, definitions, parameters, responses, securityDefinitions.
swagger: "2.0"
info:
title: Orders API
version: "1.0.0"
paths: {}
definitions: {}
An empty definitions: {} is valid. You'll fill it in the next step.
Each entry under definitions is a named JSON Schema object. The name is how you'll reference it later, so keep it PascalCase and descriptive.
Start with a real object your API returns. Here is an Order schema.
definitions:
Order:
type: object
required:
- id
- status
- total
properties:
id:
type: string
format: uuid
status:
type: string
enum: [pending, shipped, delivered, cancelled]
total:
type: number
format: double
created_at:
type: string
format: date-time
Two things to notice. required is a sibling of properties, not a flag inside each property — a common mistake. And format is a hint, not a validator: tooling uses it, but Swagger won't reject a bad UUID at spec level.
Definitions are useless until something points at them. References use the JSON Reference syntax: $ref: "#/definitions/Order".
paths:
/orders/{id}:
get:
parameters:
- name: id
in: path
required: true
type: string
responses:
"200":
description: The order
schema:
$ref: "#/definitions/Order"
The $ref value is a single string. It can't have sibling keys — Swagger 2.0 tooling will silently ignore anything next to a $ref. If you need to add a description, do it inside the referenced schema, not next to the reference.
Open the file in Swagger Editor to confirm the reference resolves. A broken $ref shows as a red error in the right pane.
Most real APIs have base shapes and variants. allOf composes them without duplication.
definitions:
BaseEntity:
type: object
required: [id, created_at]
properties:
id:
type: string
format: uuid
created_at:
type: string
format: date-time
Order:
allOf:
- $ref: "#/definitions/BaseEntity"
- type: object
required: [status, total]
properties:
status:
type: string
enum: [pending, shipped, delivered, cancelled]
total:
type: number
format: double
Order now inherits id and created_at from BaseEntity and adds its own fields. Swagger 2.0 doesn't support oneOf or anyOf — those are OpenAPI 3 features. If you need discriminated unions today, you're waiting for the OpenAPI 3 upgrade.
A schema can reference another schema in its properties. This is how you model nested objects and arrays of objects.
definitions:
LineItem:
type: object
required: [sku, quantity]
properties:
sku:
type: string
quantity:
type: integer
minimum: 1
Order:
type: object
required: [id, items]
properties:
id:
type: string
items:
type: array
items:
$ref: "#/definitions/LineItem"
The items field on an array takes the same shape as any schema — either an inline object or a $ref. Prefer the reference. It keeps your LineItem shape in one place and makes generated client code reuse the same type across endpoints.
Hand-writing definitions for a mature API is not the job. Every serious backend framework has a library that reads your route handlers, model classes, or type annotations and emits a Swagger document.
Install the generator, annotate your models (most frameworks do this from class fields or type hints automatically), and run the export.
# Spring Boot — runtime endpoint (springdoc emits OpenAPI 3, not Swagger 2)
curl http://localhost:8080/v3/api-docs > openapi.json
# Django with drf-spectacular
python manage.py spectacular --file schema.yaml
# Go with swag
swag init -g cmd/api/main.go
Note that springdoc-openapi produces OpenAPI 3.x output — if you specifically need Swagger 2.0, you'll need to convert it (e.g. with api-spec-converter). The legacy Springfox project exposed /v2/api-docs for Swagger 2.0 but is no longer actively maintained.
If you're producing OpenAPI 3 output but need Swagger 2.0, we cover the mechanics of generating an OpenAPI spec from an existing codebase in more detail — including the CI checks worth adding.
Once generated, diff it against your hand-written file. Any drift is a bug in one of them.
A definition that parses in isolation can still break the document. Run a validator.
# @apidevtools/swagger-cli is deprecated; @redocly/cli is the actively maintained successor
npx @redocly/cli lint swagger.yaml
Or use Spectral with the built-in OpenAPI ruleset, which catches issues a syntax validator won't — unused definitions, missing descriptions, inconsistent naming.
npx @stoplight/spectral-cli lint swagger.yaml
Expected output on a clean file is silence, or a small list of style warnings. Anything red — broken refs, invalid types, sibling keys next to $ref — fails CI.
Sibling keys next to $ref. Swagger 2.0 ignores them. If you need to override a field, wrap the reference in allOf.
Definitions that aren't referenced. Unused definitions still appear in generated SDKs and documentation. Spectral's oas2-unused-definition rule catches these — clean them up before publishing.
Confusing Swagger 2.0 with OpenAPI 3. If your file starts with openapi: 3.x, move the block to components/schemas and update refs to #/components/schemas/Order. The OpenAPI specification documents the current structure. Our deep-dive on OpenAPI covers the differences and what changes when agents, not just humans, read the spec.
Treating the spec as documentation only. A spec that drifts from the running code is worse than no spec — it lies. Regenerate on every build and diff against the committed version. OpenAPI spec drift is where most agent integrations quietly break.
Over-nesting with allOf. Two levels of composition is fine. Four levels means you're modelling inheritance in a spec that wasn't built for it. Flatten.
Stay up to date on the ever changing agentic landscape.