DEV Community

Cover image for What Does It Mean to Treat Your API Spec as Code?
Hassann
Hassann

Posted on • Originally published at apidog.com

What Does It Mean to Treat Your API Spec as Code?

Your API contract probably lives in three places: a wiki diagram, an exported Postman collection, and a Markdown file that no longer matches production. When those disagree, developers guess. Guessing breaks integrations.

Try Apidog today

Spec-as-code fixes this by making one OpenAPI file the source of truth. You commit it to Git, review it in pull requests, and generate mocks, tests, docs, and SDKs from that same file.

This guide shows how to treat your OpenAPI spec like application code and wire it into a practical development workflow.

What spec-as-code means

Spec-as-code means your API definition is a plain-text file stored in version control. It is not a database record, a hosted document, or a manually updated wiki page. It is a file your team can diff, branch, review, merge, and roll back.

Spec-as-code workflow

The pattern is similar to docs-as-code: keep the artifact close to the code and ship it through the same workflow. With APIs, the artifact is usually an OpenAPI document in YAML or JSON.

A typical repo layout looks like this:

my-service/
├── api/
│   └── openapi.yaml
├── src/
├── tests/
└── package.json
Enter fullscreen mode Exit fullscreen mode

That api/openapi.yaml file becomes the contract. Developers check it before implementing endpoints. QA uses it to build contract tests. Consumers use it to generate SDKs or read reference docs.

Why treat the API spec like code?

Once the spec is in Git, you can apply the same controls you already use for source code.

Review changes in pull requests

Endpoint changes become visible diffs.

Instead of discovering a breaking change after deployment, reviewers can catch it before merge:

 status:
   type: string
-  enum: [pending, shipped, delivered]
+  enum: [pending, shipped, delivered, canceled]
Enter fullscreen mode Exit fullscreen mode

That diff immediately shows a contract change. Reviewers can decide whether it is safe, backward-compatible, or needs a version bump.

This is the core of a Git-native API workflow.

Keep history and rollback simple

Every spec change has:

  • a commit
  • an author
  • a timestamp
  • a pull request discussion
  • a rollback path

If a spec change causes problems, rollback is standard Git:

git revert <commit-sha>
Enter fullscreen mode Exit fullscreen mode

For API versioning strategies, see OpenAPI version control with Git.

Generate downstream outputs from one file

When mocks, tests, documentation, and SDKs all come from the same OpenAPI file, they cannot drift independently.

Update the spec, regenerate outputs, and your API ecosystem stays aligned.

Concern Spec in a hosted tool API spec as code
Change review Manual, easy to miss PR diff, blocking review
History Limited or vendor-locked Full Git log
Rollback Often manual git revert
Source of truth Ambiguous The committed file
CI integration Bolt-on Native

Use OpenAPI as the artifact

OpenAPI is the practical choice because it is widely supported, human-readable, and machine-parseable.

Here is a small OpenAPI 3.1 example you could keep at api/openapi.yaml:

openapi: 3.1.0
info:
  title: Orders API
  version: 1.2.0

paths:
  /orders/{orderId}:
    get:
      summary: Get an order by ID
      operationId: getOrder
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: The requested order
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
        "404":
          description: Order not found

components:
  schemas:
    Order:
      type: object
      required:
        - id
        - status
        - total
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - pending
            - shipped
            - delivered
        total:
          type: number
          format: float
Enter fullscreen mode Exit fullscreen mode

Now every contract change is explicit.

Adding a property becomes a small diff:

 properties:
   total:
     type: number
     format: float
+  currency:
+    type: string
+    example: USD
Enter fullscreen mode Exit fullscreen mode

Changing a response code is also visible:

 responses:
   "200":
     description: The requested order
+  "401":
+    description: Unauthorized
   "404":
     description: Order not found
Enter fullscreen mode Exit fullscreen mode

That is the main benefit: API design decisions become reviewable source changes.

Generate mocks, tests, docs, and SDKs

The value of spec-as-code comes from wiring outputs to the spec.

1. Generate mocks

Point a mock server at the OpenAPI file so frontend and mobile teams can start integration before the backend is complete.

The workflow is:

OpenAPI spec -> mock server -> frontend/mobile integration
Enter fullscreen mode Exit fullscreen mode

When the spec changes, the mock changes with it.

2. Generate contract tests

Contract tests verify that the running service still matches the committed spec.

A useful CI check should catch issues like:

  • endpoint missing from implementation
  • undocumented response status
  • missing documented response field
  • response type mismatch
  • invalid request schema

The workflow is:

OpenAPI spec -> contract test -> live service validation
Enter fullscreen mode Exit fullscreen mode

Without this check, the spec can still drift from production.

3. Generate documentation

Reference docs should be rendered from the OpenAPI file instead of maintained by hand.

The workflow is:

OpenAPI spec -> API reference docs
Enter fullscreen mode Exit fullscreen mode

That keeps endpoint paths, parameters, schemas, and response examples aligned with the contract.

4. Generate SDKs

Client SDKs can be generated from the same file.

The workflow is:

OpenAPI spec -> generated SDKs -> API consumers
Enter fullscreen mode Exit fullscreen mode

This gives consumers typed clients that reflect the current API contract.

Generated API outputs

How Apidog fits into a spec-as-code workflow

Running spec-as-code manually usually means connecting several tools:

  • OpenAPI editor
  • linter
  • mock server
  • docs generator
  • contract test runner
  • Git workflow

Apidog’s Spec-First Mode is designed around the OpenAPI file as the authoritative API definition. You can design endpoints against the spec and keep mocks, tests, and documentation aligned with that contract.

Apidog Spec-First Mode

The key workflow is two-way Git sync. Apidog can read the OpenAPI file from a repository and write changes back to it. That lets teams work visually when useful, edit YAML directly when needed, and still keep Git as the source of truth.

For the mechanics, see how to sync your OpenAPI spec to GitHub.

The important point: visual tooling should sit on top of the committed OpenAPI file, not replace it.

Common implementation pitfalls

Pitfall 1: No CI check

Committing the spec is not enough. If CI never validates it, invalid OpenAPI can still merge.

Add a CI step that lints the file on every pull request.

Example workflow:

Pull request opened
        ↓
Lint OpenAPI spec
        ↓
Run contract checks
        ↓
Merge only if checks pass
Enter fullscreen mode Exit fullscreen mode

Pitfall 2: Spec and implementation drift

If the running API is not tested against the spec, the two can diverge quietly.

Fix this by adding contract tests that compare live responses against the committed OpenAPI document.

Pitfall 3: Two sources of truth

Avoid mixing two competing workflows:

Code annotations generate spec
Manual spec edits generate docs
Enter fullscreen mode Exit fullscreen mode

Pick one authoritative direction.

If the OpenAPI file is the source of truth, then implementation should be checked against it. If code annotations are the source, then generated OpenAPI should be treated as the output.

Do not let both become master copies.

Pitfall 4: Treating the spec as documentation only

A spec you only read is documentation.

A spec that generates mocks, tests, docs, and SDKs is a contract.

The value comes from connecting the file to your development pipeline.

Pitfall 5: Skipping review

A spec in Git without review is just another unchecked file.

Require pull request review for API contract changes, especially changes to:

  • request schemas
  • response schemas
  • status codes
  • authentication requirements
  • path or query parameters
  • enum values
  • required fields

A practical adoption plan

You can adopt spec-as-code incrementally.

Step 1: Commit the OpenAPI file

Move the spec into your service repo:

api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

Commit it like any other source file.

git add api/openapi.yaml
git commit -m "Add OpenAPI contract"
Enter fullscreen mode Exit fullscreen mode

Step 2: Require pull request review

Make API changes go through PRs.

A reviewer should be able to answer:

  • Did the endpoint path change?
  • Did any required fields change?
  • Were new response codes added?
  • Is the change backward-compatible?
  • Does this require a version bump?

Step 3: Generate one output

Start small. Pick one generated output:

  • mocks
  • documentation
  • contract tests
  • SDKs

Do not try to automate everything on day one.

Step 4: Add a spec lint check

Add CI validation so malformed OpenAPI cannot merge.

At minimum, check that:

  • the file is valid OpenAPI
  • required metadata exists
  • paths and operations are well formed
  • schemas are valid

Step 5: Add contract tests

Once the spec is stable, test the live service against it.

This closes the loop:

Committed spec -> implementation -> contract test -> CI result
Enter fullscreen mode Exit fullscreen mode

If the API changes without a matching spec update, CI should fail.

Final takeaway

Spec-as-code is a small workflow change with a large impact:

One OpenAPI file
        ↓
Committed to Git
        ↓
Reviewed in pull requests
        ↓
Used to generate mocks, tests, docs, and SDKs
Enter fullscreen mode Exit fullscreen mode

That makes your API contract visible, reviewable, and enforceable.

If you want visual editing and Git sync built into the workflow, try Apidog’s Spec-First Mode and keep your OpenAPI file as the single source of truth.

FAQ

Is “API spec as code” the same as “docs-as-code”?

They use the same principle: keep the artifact in version control and ship it through your normal workflow.

Docs-as-code applies that to documentation. Spec-as-code applies it to the API contract. When documentation is generated from a committed OpenAPI file, the two workflows reinforce each other.

What format should the spec file use?

OpenAPI in YAML is the common choice. YAML is readable, diff-friendly, and supported by many API tools.

JSON also works, but YAML usually produces cleaner pull request diffs.

How do I stop the spec from drifting away from the real API?

Add contract tests to CI. The tests should compare the running service against the committed OpenAPI file.

If an endpoint returns an undocumented field, omits a documented field, or changes a response shape, the build should fail.

Top comments (0)