← Back to blog

OpenAPI Best Practices: From Interface Description to Production Contract

OpenAPI is more than "auto-generated API docs." This article covers the design-first workflow, using OpenAPI as a frontend-backend contract, auto-generating client SDKs, integrating with API testing, and multi-version management — for teams building or standardizing their API practice.

The Bottom Line: OpenAPI Is Not About Documentation — It Is About Contracts

Many teams treat OpenAPI as a “documentation generator.” This misses the point. OpenAPI’s core value is as a contract layer — defining the shape of an API before writing a line of code, so consumers and providers align on the same agreement.


1. Design-First vs Code-First

Design-First

Write OpenAPI spec → Review → Finalize → Generate interface skeleton → Implement business logic

Best for: external APIs, cross-team collaboration, third-party integrations

Code-First

Write code + annotations → Auto-generate OpenAPI spec

Best for: internal services, same-team frontend/backend, rapid prototyping

  • New / external APIs: design-first
  • Existing / internal APIs: code-first, gradually enrich the spec

2. Keeping Spec and Implementation in Sync

Two engineering practices prevent drift:

CI Schema Validation

- run: npx @redocly/cli lint openapi/openapi.yaml
- run: npx openapi-generator-cli validate -i openapi/openapi.yaml

Integration Test Schema Assertions

const validateResponse = createResponseValidator(spec, '/users', 'get');
const response = await api.getUsers();
const errors = validateResponse(response.statusCode, response.body);
expect(errors).toHaveLength(0);

Every CI run says “the spec and implementation have not drifted today.”


3. Auto-Generated Client SDKs

Strategy

Generate only the interface layer, not business logic:

  • Request/response models (DTOs)
  • API call methods (HTTP request wrappers)
  • Error types

Do NOT generate:

  • Business logic
  • Data transformation/mapping
  • Caching strategies

Versioning

SDK versions should stay in lockstep with the spec:

openapi/
  v1/
    openapi.yaml
    sdks/typescript/
    sdks/python/
  v2/
    openapi.yaml
    sdks/typescript/
    sdks/python/

4. Multi-Version Management

Directory Structure

openapi/
  v1/openapi.yaml
  v2/openapi.yaml
  common/schemas/pagination.yaml

Routing

URL path prefix versioning is the simplest and most transparent approach:

/v1/users
/v2/users

Version Lifecycle

PhaseStatusDescription
AlphaIn developmentInternal testing only
BetaPreviewLimited external access, may change
StableReleasedFull backward compatibility
DeprecatedDeprecatedBug fixes only, no new features
SunsetEnd of lifeReturns 410 Gone

5. Toolchain

PurposeToolDescription
EditorStoplight Studio / RedoclyVisual editor + live preview
Validateredocly lintCI-level spec validation
DocsRedoc / Swagger UIInteractive API docs
SDKopenapi-generator-cli40+ language code generation
Testdredd / openapi-response-validatorAPI test + schema assertion
Mockprism / openapi-mockMock server from spec

Summary

LayerKey PrincipleCommon Mistake
WorkflowDesign-first for external, code-first for internalOne-size-fits-all
ConsistencyCI validation + test assertionsWrite it and forget it
SDKInterface layer only, no business logicFull-code generation, then manually delete half
VersioningIndependent directories + path prefixOne file with 5 versions, all deprecated
LifecycleClear status for each versionNever deprecate until a client breaks

The best time to invest in OpenAPI is not “before the project starts” — it is “when you need to change the third endpoint.” Before that, the number of interfaces is small and the cost of change is low. After 10+ endpoints and 2+ consumer teams, an API without a spec will start producing “I thought you did not change that” bugs.

Need backend API development or OpenAPI standardization? Contact us — tell us your interface scope and scale, feasibility within 24 hours.

FAQ

Design-first or code-first — which should I choose?

The deciding factor is whether the API consumer and provider are the same team. For internal services with a single team, code-first is more efficient. For external APIs, multiple consumer teams, or third-party integrations, design-first is essential — the API contract must be agreed upon before implementation, or the cost of change multiplies during integration testing.

How do you keep the OpenAPI spec in sync with the actual implementation?

Two complementary approaches: ① CI-level schema validation — validate the spec file on every PR (`openapi-generator-cli validate` or `redocly lint`); ② integration test schema assertions — validate actual API responses against the spec-defined response schemas. Together, these prevent spec drift.

What are the pitfalls of auto-generated client SDKs?

Three common ones: ① Code quality — auto-generated code often does not match team style and contains excessive generics; generate only the interface layer, not business logic. ② Versioning — SDK version should stay in lockstep with the spec version. ③ Null handling — different generators handle `nullable` and `optional` differently; agree on a strategy upfront.

How do you manage multiple API versions?

Organize spec files by version directory: `openapi/v1/openapi.yaml`, `openapi/v2/openapi.yaml`. Each version evolves independently. Use URL path prefixes (`/v1/`, `/v2/`) for routing. Do not use a single file with `deprecated` markers for multiple versions — once it exceeds 2000 lines, maintainability drops sharply.

This article comes from AI Enable Harness front-line delivery practice. Need a similar system or optimization service?

Subscribe to Updates

Get notified when new articles are published. No spam, occasional updates only.

Subscribe →