Skip to main content
Career Paths
Concepts
Api First Design
The Simplified Tech

Role-based learning paths to help you master cloud engineering with clarity and confidence.

Product

  • Career Paths
  • Interview Prep
  • Scenarios
  • AI Features
  • Cloud Comparison
  • Pricing

Community

  • Join Discord

Account

  • Dashboard
  • Credits
  • Updates
  • Sign in
  • Sign up
  • Contact Support

Stay updated

Get the latest learning tips and updates. No spam, ever.

Terms of ServicePrivacy Policy

© 2026 TheSimplifiedTech. All rights reserved.

BackBack
Interactive Explainer

API-First Design

Design the API contract before writing a single line of implementation. The principle behind Stripe, GitHub, and Twilio.

🎯Key Takeaways
API-first: design the contract (OpenAPI/protobuf/GraphQL schema) before writing implementation. It is a product decision, not a technical detail.
API-first enables parallel development — consumers mock the spec while the backend implements it.
Contract tests in CI ensure the implementation never drifts from the published spec.
Breaking changes (field removed/renamed, type changed) require a version bump. Additive changes (new optional field) are non-breaking.
Stripe's date-pinned versioning model is the gold standard: old clients never break, new clients get the latest API.

API-First Design

Design the API contract before writing a single line of implementation. The principle behind Stripe, GitHub, and Twilio.

~6 min read
Be the first to complete!
What you'll learn
  • API-first: design the contract (OpenAPI/protobuf/GraphQL schema) before writing implementation. It is a product decision, not a technical detail.
  • API-first enables parallel development — consumers mock the spec while the backend implements it.
  • Contract tests in CI ensure the implementation never drifts from the published spec.
  • Breaking changes (field removed/renamed, type changed) require a version bump. Additive changes (new optional field) are non-breaking.
  • Stripe's date-pinned versioning model is the gold standard: old clients never break, new clients get the latest API.

Lesson outline

The $40 billion API company story

In 2010, a 22-year-old developer named Patrick Collison was frustrated with Stripe's competition. Payment APIs were terrible — weeks of approval, mountains of documentation, cryptic XML, and constant integration failures.

Stripe's first decision was unusual: before writing any implementation, they designed the API. They wrote example code showing how a developer would integrate Stripe. The API had to be so intuitive that the integration docs could fit on a single page.

That API-first decision — design the developer experience before building the system — is a significant part of why Stripe became a $95 billion company.

What is API-first design?

API-first means the API contract (schema, endpoints, request/response shapes, error codes) is designed, reviewed, and agreed upon BEFORE any backend implementation begins. The API is treated as a product — not an implementation detail.

Implementation-first vs API-first: the difference in outcomes

ScenarioImplementation-firstAPI-first
Mobile and backend teams work in parallelMobile blocks waiting for backend to finishMobile mocks the API spec and builds; both finish simultaneously
API field naminguser_id int (whatever the DB schema uses)Discussed, agreed as uuid string (matches consumer expectations)
Breaking API changesDiscovered in integration testing after weeks of workContract tests catch violations in CI before they are merged
External developer experienceInconsistent, undocumented, changes break clientsVersioned, documented, SDK auto-generated from spec
Onboarding new team membersRead the source code to understand what the API doesRead the OpenAPI spec — the spec IS the documentation

The API-first workflow in practice

How to do API-first design

→

01

Write the API spec first — OpenAPI (REST), protobuf (gRPC), or GraphQL schema. Define endpoints, request/response shapes, error codes, and pagination.

→

02

Review the spec with all consumers — mobile team, frontend team, third-party partners. Negotiate field names, response shapes, and error handling before any code is written.

→

03

Commit the spec to source control — version it like code. Treat spec changes as PRs requiring review.

→

04

Generate mocks from the spec — tools like Prism or Mockoon serve the spec as a real HTTP server. Consumers start building immediately.

→

05

Implement against the spec — the backend treats the spec as the acceptance test. Every endpoint must match the contract exactly.

06

Add contract tests to CI — tools like Dredd or Schemathesis verify that the running service still matches the published spec on every commit. Breaking changes fail the build.

1

Write the API spec first — OpenAPI (REST), protobuf (gRPC), or GraphQL schema. Define endpoints, request/response shapes, error codes, and pagination.

2

Review the spec with all consumers — mobile team, frontend team, third-party partners. Negotiate field names, response shapes, and error handling before any code is written.

3

Commit the spec to source control — version it like code. Treat spec changes as PRs requiring review.

4

Generate mocks from the spec — tools like Prism or Mockoon serve the spec as a real HTTP server. Consumers start building immediately.

5

Implement against the spec — the backend treats the spec as the acceptance test. Every endpoint must match the contract exactly.

6

Add contract tests to CI — tools like Dredd or Schemathesis verify that the running service still matches the published spec on every commit. Breaking changes fail the build.

A minimal OpenAPI spec example

openapi: 3.0.0 info: title: Payment API version: 1.0.0 paths: /payments: post: summary: Create a payment requestBody: required: true content: application/json: schema: type: object required: [amount, currency, source] properties: amount: type: integer description: Amount in smallest currency unit (cents) currency: type: string enum: [usd, eur, gbp] source: type: string description: Payment method token responses: '201': description: Payment created successfully '422': description: Validation error

contract-test.ts
1// Dredd contract test — fails CI if implementation breaks the spec
2import Dredd from 'dredd';
3
4const dredd = new Dredd({
The OpenAPI spec is checked into source control and is the acceptance test
5 path: ['./api/openapi.yaml'], // the spec is the source of truth
6 endpoint: 'http://localhost:3000',
7 reporter: 'dot',
8});
9
10dredd.run((err, stats) => {
11 if (stats.failures > 0 || stats.errors > 0) {
Fails the CI build if any endpoint response does not match the spec
12 console.error('Contract test FAILED — implementation does not match spec');
13 process.exit(1); // fails CI build
14 }
15 console.log('All contract tests passed');
16});

API versioning: the contract you make with consumers

Once an API is published, consumers depend on it. Breaking that contract — removing a field, changing a type, renaming an endpoint — breaks consumers. API-first design forces you to think about versioning from day one.

Versioning strategies

  • URL versioning: /v1/payments, /v2/payments — Simple and explicit. Clients know exactly which version they are using. Works well for major breaking changes. Downside: code duplication when versions are mostly similar.
  • Header versioning: Accept: application/vnd.api+json;version=2 — Cleaner URLs. Harder to test in a browser. Used by GitHub API.
  • Date-based versioning: Stripe-Version: 2024-01-01 — Stripe's approach. Every breaking change creates a new version date. Clients pin to the version they tested against. New clients get the latest. Old clients never break.
  • Additive-only (non-breaking) changes — Adding fields to responses, adding optional request fields, adding new endpoints — these do not require new versions. Semantic versioning rule: only remove or rename fields when bumping the major version.

The Stripe versioning model is the gold standard

Stripe has APIs from 2013 that still work. They pin every API consumer to the version date they first integrated with. When Stripe changes the API, old integrations never break. The cost: Stripe maintains a version translation layer. The benefit: zero client churn, legendary developer experience.

Quick check

Which type of API change is "non-breaking" and does not require a version bump?

REST vs gRPC vs GraphQL: choosing the right contract format

ProtocolBest forContract formatCode generation
REST / OpenAPIPublic APIs, web/mobile clients, simple CRUDOpenAPI YAML/JSONAuto-generate SDKs, docs, mocks
gRPC / ProtobufInternal microservice communication, streaming, high performance.proto filesAuto-generate client/server code in any language
GraphQLFlexible client-driven data fetching, BFF pattern, complex nested dataSDL schemaType-safe clients, auto-generated resolvers
AsyncAPIEvent-driven systems, message queues, KafkaAsyncAPI YAMLAuto-generate producers/consumers

The API-first principle applies to all of them. The protocol changes; the principle does not: design the contract, get alignment, then implement.

How this might come up in interviews

Backend and platform engineering interviews — often asked when discussing distributed systems, microservices, or developer experience design.

Common questions:

  • What is API-first design and why does it matter?
  • What is an OpenAPI spec and how do you use it?
  • How do you prevent breaking API changes from reaching consumers?
  • When would you choose gRPC over REST?
  • How does Stripe handle API versioning?

Key takeaways

  • API-first: design the contract (OpenAPI/protobuf/GraphQL schema) before writing implementation. It is a product decision, not a technical detail.
  • API-first enables parallel development — consumers mock the spec while the backend implements it.
  • Contract tests in CI ensure the implementation never drifts from the published spec.
  • Breaking changes (field removed/renamed, type changed) require a version bump. Additive changes (new optional field) are non-breaking.
  • Stripe's date-pinned versioning model is the gold standard: old clients never break, new clients get the latest API.
Before you move on: can you answer these?

What is the deliverable of API-first design?

A machine-readable contract: an OpenAPI spec, a .proto file (gRPC), or a GraphQL schema — checked into source control and agreed upon by all consumers before implementation begins.

Why do contract tests matter in CI/CD?

They automatically verify that the running implementation still matches the published spec on every commit. They catch breaking changes before they reach consumers.

Ready to see how this works in the cloud?

Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.

View role-based paths

Sign in to track your progress and mark lessons complete.

Discussion

Questions? Discuss in the community or start a thread below.

Join Discord

In-app Q&A

Sign in to start or join a thread.