From Analysis to System Design

Interface & API Specification

18 min Lesson 4 of 10

Interface & API Specification

Once a system has been decomposed into modules and components, every point where two pieces of software meet becomes a design risk. If the meeting point is not precisely defined in writing before a single line of code is written, both sides will make different assumptions and the integration will fail. That formal written definition of a meeting point is called an interface specification. When the meeting point is exposed over a network (HTTP, messaging, sockets), the specification is commonly called an API specification.

This lesson teaches you how to author these contracts: what they must contain, how to structure them, and how to validate them against the requirements you captured earlier in the project.

What an Interface Specification Covers

A complete interface specification answers six questions:

  1. Who calls whom? — identify the caller (client) and the provider (server or module).
  2. How is the call made? — the protocol, transport, and invocation pattern (synchronous request/response, async message, callback, event).
  3. What does the caller send? — input parameters: names, data types, constraints, and whether each is mandatory or optional.
  4. What does the provider return? — output fields: names, types, and meaning of each value in the successful response.
  5. What can go wrong? — error cases: codes, messages, and the conditions that trigger each one.
  6. What are the non-functional expectations? — latency SLA, throughput limit, authentication method, idempotency guarantee.
Specification, not implementation. An interface spec describes the contract, not the code behind it. A good spec can be fulfilled by multiple implementations — a mock, a prototype, and the final production service all satisfy the same spec. Write the spec before any implementation begins.

Anatomy of a REST API Endpoint Specification

Modern systems commonly expose REST APIs over HTTP. The structure below specifies a single endpoint from a clinic booking system where the front-end scheduling module calls the appointment service:

POST /api/v1/appointments Authorization: Bearer {access_token} Content-Type: application/json REQUEST BODY Field | Type | Required | Constraints ------------------|---------|----------|-------------------------------------------- patient_id | integer | yes | Must exist in patients table doctor_id | integer | yes | Must exist in doctors table appointment_date | string | yes | ISO 8601 date: YYYY-MM-DD appointment_time | string | yes | HH:MM (24-h), within doctor working hours reason | string | no | Max 500 characters SUCCESS RESPONSE 201 Created { "appointment_id": 4821, "status": "confirmed", "confirmation_code": "APT-20240915-4821" } ERROR RESPONSES HTTP | error_code | Condition -----|------------------------|------------------------------------------- 400 | INVALID_DATE_FORMAT | appointment_date not ISO 8601 409 | SLOT_UNAVAILABLE | Doctor already booked at that time 422 | OUTSIDE_WORKING_HOURS | Time falls outside doctor schedule 404 | DOCTOR_NOT_FOUND | doctor_id does not exist 401 | UNAUTHORIZED | Missing or expired access token

Notice that every error case has a distinct error_code string. Generic messages like "error": "something went wrong" force the calling developer to guess; explicit codes allow the caller to handle each case programmatically — retry on 409, redirect to login on 401, show a field validation message on 400.

The Interface Diagram: Visualising Contracts Between Components

A diagram that maps all the interfaces in a subsystem is invaluable during design reviews. Each component is shown as a box; each interface is an annotated arrow carrying the call name and protocol. The diagram below shows the four main interfaces inside the booking subsystem of the clinic platform:

Interface diagram — Clinic Booking Subsystem Clinic Booking Subsystem — Interface Map Scheduling UI Web Frontend Appointment Service REST API Notification Service Message Queue Availability DB Read Replica Patient Record Service gRPC IF-1: POST /appointments REST · JSON · HTTPS IF-2: Event Async · Queue IF-3: GET /slots REST · JSON IF-4: GetPatient gRPC · Protobuf Sync REST Async Event Sync DB Query Sync gRPC
Interface map for the clinic booking subsystem showing four labelled interfaces (IF-1 to IF-4), their callers, providers, and protocols.

Each interface receives a unique identifier that can be referenced in traceability tables, design reviews, and test plans. Solid lines indicate synchronous calls; the dashed line for IF-2 indicates an asynchronous event published to a message queue — the publisher does not block waiting for a response.

Specifying Asynchronous and Event-Driven Interfaces

In an event-driven design the provider publishes an event and does not wait for a response. The specification must therefore document the event shape rather than a response schema:

EVENT: AppointmentCreated Channel: appointments.created (RabbitMQ exchange, topic type) Publisher: Appointment Service Subscribers: Notification Service, Analytics Service PAYLOAD Field | Type | Description -----------------|----------|---------------------------------------- event_id | UUID | Unique identifier (used for deduplication) event_type | string | Always "appointment.created" appointment_id | integer | The newly created appointment patient_id | integer | The patient who booked doctor_id | integer | The assigned doctor appointment_at | ISO 8601 | Full datetime of the appointment published_at | ISO 8601 | Timestamp the event was published GUARANTEES - At-least-once delivery (subscribers must be idempotent on event_id) - Events older than 7 days may be discarded from the dead-letter queue
Idempotency keys in async interfaces. Because a message queue may deliver the same event more than once during retries, every async payload should carry a unique event_id. Subscribers check whether they have already processed that ID before acting. Document this requirement explicitly in the spec — it is easy to overlook and hard to fix after deployment.

API Specification Standards and Tooling

Writing specs in free-form prose is error-prone and hard to keep in sync with reality. Industry-standard machine-readable formats solve this:

  • OpenAPI 3.x (formerly Swagger) — the dominant standard for REST APIs. A YAML or JSON file that describes every endpoint, request body, response schema, and error code. Tools such as Swagger UI render it as interactive documentation; code generators produce client stubs in dozens of languages.
  • AsyncAPI — the event-driven counterpart to OpenAPI. Describes channels, message payloads, and bindings for Kafka, RabbitMQ, and MQTT.
  • Protocol Buffers (.proto files) — the schema language for gRPC interfaces. Strictly typed; the compiler enforces the contract and generates client/server code in multiple languages.
  • GraphQL Schema Definition Language (SDL) — for GraphQL APIs, the SDL file is the spec; queries are validated against it at build time.
Spec drift kills integration. A spec that is written once and never updated becomes a liability. Treat the specification as living documentation: update it whenever a field is added, renamed, or removed, and version the API (e.g. /api/v1/ vs /api/v2/) when breaking changes are introduced. Consumer teams must be notified of breaking changes before deployment.

The Interface Register: Tracking All Contracts in a Project

On a project with dozens of components, a single table — the interface register — gives the project manager and architect a complete picture of integration dependencies. Each row is one interface:

Interface Register table for the online store project Interface Register — Online Store Project ID Caller Provider Operation Protocol Pattern Status IF-01 Cart UI Product Service GET /products/{id} REST / HTTPS Sync Approved IF-02 Checkout UI Order Service POST /orders REST / HTTPS Sync Approved IF-03 Order Service Payment Gateway POST /v1/charges REST / HTTPS Sync In Review IF-04 Order Service Inventory Service StockReserved event RabbitMQ Async Approved IF-05 Inventory Service Supplier API POST /reorder REST / HTTPS Sync Draft IF-06 Shipping Service Courier API POST /shipments REST / HTTPS Sync In Review Approved In Review Draft
Interface register for an online store: each row is one interface with its caller, provider, operation, protocol, invocation pattern, and approval status.

The status column (Draft / In Review / Approved) makes it immediately visible which interfaces are still unresolved risks. A project cannot enter the build phase until every interface it depends on reaches Approved status.

From Requirements to Interface Spec

Every interface specification should trace back to one or more functional requirements. For the clinic booking endpoint POST /api/v1/appointments, the traceability chain looks like this:

  • FR-12: The system shall allow patients to book available appointment slots with a specific doctor.
  • FR-13: The system shall prevent double-booking of a doctor at the same time slot.
  • NFR-04: The booking API shall respond within 800 ms at the 95th percentile under normal load.

Each requirement drives a specific part of the spec: FR-12 drives the request body fields; FR-13 drives the SLOT_UNAVAILABLE 409 error; NFR-04 drives the latency SLA documented in the non-functional section. When a requirement changes, the analyst knows exactly which interface spec must be updated — and which development team must be notified.

Mock servers accelerate parallel development. Once an interface spec is approved, teams on both sides can work independently: the provider team builds the real service, while the consumer team builds against a mock server that returns the specified responses. This eliminates the classic integration bottleneck where one team must wait for the other to finish before they can test.

A well-written interface specification is one of the most leverage-rich artefacts in system analysis. It eliminates integration surprises, enables parallel development, forms the basis for integration test cases, and serves as the authoritative reference when disputes arise between teams months into the build.