ShieldThemes Web Development
+1 (415) 555-0142 Get a quote →
← Journal/Engineering

Write the API contract before the front end exists

Agreeing on an API contract up front lets front-end and back-end teams work in parallel. How we write, review and enforce contracts on client projects.

Maya Okafor
Maya Okafor
Head of Engineering · Feb 12, 2025 · 5 min read
Write the API contract before the front end exists

On most projects we inherit, the API was designed by whoever built the first screen that needed it. Endpoints were added one at a time, named according to the mood of the week, and shaped around what one page happened to display. By the time a mobile app or a partner integration arrives, the API is a collection of special cases that nobody wants to change because nobody knows what depends on them. We now start almost every build that has a separate front end, a mobile client or an external consumer by writing the API contract first. It costs a few days at the start and saves weeks later.

What contract-first means in practice

A contract is a machine-readable description of every endpoint: its path, method, parameters, request body, response shapes, error formats and authentication. For HTTP APIs we write it in OpenAPI; for event-driven systems, an equivalent schema for each message. The important part is not the format. It is that the contract is written, reviewed and agreed before implementation begins, and that it remains the source of truth afterwards.

That order changes the conversation. Instead of front-end developers discovering the API by reading controller code, both sides negotiate a document. Arguments about naming, pagination and error handling happen once, in review, rather than repeatedly in pull requests.

How we write the first version

We start from the user journeys defined in discovery rather than from the database schema. For each journey, we list the data the client needs and the actions it performs, then group those into resources. A simple example for an orders resource:

paths:
  /orders/{orderId}:
    get:
      summary: Fetch a single order
      parameters:
        - name: orderId
          in: path
          required: true
          schema: { type: string, format: uuid }
      responses:
        "200":
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Order" }
        "404":
          $ref: "#/components/responses/NotFound"

Alongside the endpoints, we settle a handful of conventions that apply everywhere:

  • One error format for the whole API, with a stable machine-readable code and a human message.
  • One pagination style, usually cursor-based for anything that can grow large.
  • Consistent naming: plural resource names, one casing style for fields, ISO 8601 timestamps in UTC.
  • Identifiers that do not leak database internals, typically UUIDs or prefixed opaque strings.
  • A versioning policy agreed before version two is needed.

Reviewing with the people who will consume it

A contract review is most useful when the consumers lead it. The front-end developer, the mobile engineer and, where relevant, the partner's integration team read the spec against their screens and workflows, and ask where the data they need will come from. Typical findings in a first review include a list endpoint missing the one field the table displays, an action that requires three sequential calls where one would do, and error cases nobody had considered, such as what happens when an item goes out of stock between cart and checkout.

A contract review is the cheapest place to change an API. After launch, every change is a migration for someone.

We timebox reviews to a couple of sessions per major area. The goal is a contract that is good enough to build against, not perfect. It will change during implementation, but through the same reviewed process.

Parallel work with mocks

Once the contract is agreed, front-end and back-end work can proceed at the same time. We generate a mock server from the spec that returns realistic example responses, including error cases, and the front-end team builds against that from day one. On a recent SaaS build, this let the interface team finish most of the dashboard screens before the corresponding back-end endpoints existed, and integration week consisted mainly of pointing the client at a different base URL.

Generated types are the other big win. Tools can produce TypeScript types, API client code and server-side request validators from the same spec, so a field renamed in the contract becomes a compile error in every consumer rather than a runtime bug in production.

Enforcing the contract

A contract that drifts from the implementation is worse than no contract, because people trust it. We enforce it at three points:

  1. Request and response validation in tests. The integration suite validates every response against the schema. An endpoint that returns an unexpected field or type fails the build.
  2. Breaking change detection in CI. A job compares the proposed spec with the one on the main branch and fails the pull request if it removes fields, tightens types or changes required parameters without a version bump.
  3. Published documentation. The spec renders into browsable reference docs on every deploy, so consumers always read the current contract.

The breaking change check is the one that pays for itself fastest. It turns an accidental change into a visible decision, which is usually enough to prevent it.

When not to bother

Contract-first is not free. For a server-rendered application where the only consumer is the same codebase, a formal spec adds ceremony without much benefit. It earns its keep when there is more than one consumer, when teams work in parallel, when a mobile app cannot be updated instantly, or when an external partner integrates with you. In those cases, a few days of design at the start is a small price for an API that stays coherent into its third and fourth year.

Our API development work starts from a reviewed contract as standard, and it fits naturally with React front-ends built against generated types and mocks from the first sprint. For larger products, the same discipline carries into our SaaS platform builds, where public APIs are part of the product.

Start with a contract, not a guess

If you are planning an API, or trying to tame one that grew by accident, we can help you get the contract right. Share your use cases and we will send a fixed-price proposal within 24 hours. Tell us about your project.

Maya Okafor
WRITTEN BY
Maya Okafor
Maya leads engineering at ShieldThemes. She has shipped more than 120 WordPress and Laravel platforms and writes about architecture that survives its second year.
All articles by Maya Okafor →
Want this on your project?
Get a fixed-price quote from a senior lead within 24 hours.
Request a quote →

Keep reading

How we shipped a support agent that resolves 62% of tickets
AI · 5 min
How we shipped a support agent that resolves 62% of tickets
What to learn in the two weeks before a website redesign
Design · 5 min
What to learn in the two weeks before a website redesign
Migrating to Shopify Plus without losing a single ranking
Shopify · 5 min
Migrating to Shopify Plus without losing a single ranking