API-First Development: OpenAPI Contracts with AI
Designing the contract before the implementation catches integration mismatches while they're free to fix. How to generate, review, and keep OpenAPI specs honest with AI in the loop.
Code-first API development — write the controller, let the framework generate docs from it — is fast until two teams building against the same API disagree about what it does. Contract-first flips the order: the OpenAPI spec is written and agreed on before implementation starts, so both the backend team and every consumer are building against the same explicit source of truth.
Why contract-first catches problems earlier
A written contract forces decisions that code-first defers: what exactly does a 404 vs a 422 mean here, is this field nullable, what's the pagination shape, which fields are immutable after creation. Code-first lets these stay implicit until a consumer hits the edge case in production. Writing the spec first — and having a frontend or integration team review it before a single endpoint is implemented — moves that discovery to the cheapest possible point.
Generating a spec with AI, correctly
Context: Building a REST API for a course-progress tracking feature. Entities: User, Course, Enrollment, LessonProgress. Business rules: a user can enroll in a course once; progress is tracked per lesson as a percentage 0-100; a course is 'completed' when all lessons reach 100%.
Task: Write an OpenAPI 3.1 spec covering: list courses, enroll in a course, get enrollment progress, update lesson progress.
Constraints:
- Every error response must be explicit per endpoint (400/401/404/409 as applicable), with a shared error schema.
- Use consistent naming: kebab-case paths, camelCase JSON fields.
- Mark fields that are immutable after creation as readOnly.
- Include realistic example request/response bodies for every endpoint, not just schemas.
Output format: A single valid OpenAPI 3.1 YAML document, no surrounding explanation.Run it through an actual OpenAPI validator (swagger-cli, spectral, or your editor's linter) before treating it as final. A spec that looks plausible can still be invalid YAML/schema — the same grounding problem as any other generated artifact.
Keeping the contract honest after implementation starts
The contract is only valuable if implementation actually matches it. Two techniques keep this honest without manual policing:
- Generate server stubs and client SDKs directly from the spec (openapi-generator, NSwag) rather than hand-writing both — drift becomes a compile error instead of a runtime surprise.
- Consumer-driven contract tests (Pact or similar) let each consuming team encode what they actually depend on, and CI fails the provider's build if a change would break a real consumer — catching contract drift before it ships, not after a consumer's production incident.
When contract-first is overkill
For a single-team internal API with one consumer (your own frontend, same repo, same deploy), the coordination overhead of contract-first often isn't worth it — code-first with generated docs is fine. Contract-first earns its cost when multiple teams, or external consumers, build against the API independently and a mismatch is expensive to discover late.
The API Design module walks through this decision explicitly, then pairs the resulting contract with the global exception handling and enterprise auth prompts that turn a spec into a production-grade implementation.