API development for founders: the contract before the code
An API is a promise between systems. Define resources, permissions, errors, retries, and change policy before implementation turns accidental behavior into somebody else's dependency.
Founders often describe an API as the thing that connects two products. That is correct but incomplete. An API is a contract: a documented way for one system to ask another system to read information, create something, change something, or trigger an action.
Define the contract
HTTP provides the common transport for web APIs. A client sends a request containing a method, URL, headers, and sometimes a body. The server returns a status code, headers, and sometimes a body. The technical vocabulary matters because it gives every failure a location. A 401 is not the same problem as a 404, a 422, a timeout, or a 500.
Begin with resources and business actions. Customers, projects, invoices, appointments, and messages are resources. Approve, cancel, dispatch, refund, and reconcile are actions. Write down who may perform each action, the data required, the result returned, and the side effects produced. This becomes the first contract.
Use predictable methods and statuses. Reading should not change data. Retrying a request should not accidentally create duplicates. Invalid input should return a useful structured error. Unauthorized and forbidden requests should be distinguishable. Consumers should not have to inspect an English error sentence to decide what the software does next.
Document the contract in a machine-readable description. The OpenAPI Specification defines a language-agnostic interface for describing HTTP APIs so humans and tools can understand capabilities without reading source code. A good description includes paths, operations, parameters, schemas, examples, authentication, and error responses.
Design for retries and failure
Design idempotency for valuable writes. Payment providers and webhook systems retry. Mobile clients lose connections. Workers crash after the server completes an action but before the client receives the response. If repeating a request can charge twice, schedule twice, or create two jobs, the API needs an idempotency strategy and a stable record of prior execution.
Treat integrations as unreliable. Tokens expire, providers throttle, payloads change, webhooks arrive late or out of order, and the remote service may be down. Timeouts, bounded retries, dead-letter handling, reconciliation jobs, and operator alerts are part of the integration—not optional infrastructure added after the first incident.
Separate authentication from authorization. Authentication establishes identity. Authorization decides whether that identity may perform this action on this resource. An authenticated customer should not be able to read another customer's invoice by changing an identifier. Every resource access needs an ownership or role check at the server boundary.
Operate the promise
Version only when the contract must break, but plan for evolution from the first release. Additive fields are usually safer than renamed or removed fields. Deprecations need dates, telemetry, and a communication path. Once another system depends on behavior, changing that behavior is a product decision rather than a refactor.
Measure the API as an operating surface. Track request volume, success rate, latency, error categories, retries, provider failures, and the business actions produced. Logs should carry a request or correlation identifier so one customer event can be traced across services without exposing sensitive data.
The deliverable is not an endpoint that works in a demo. It is a contract another team can adopt confidently, an implementation that enforces the contract, tests that protect it, documentation with real examples, and an operating layer that tells you when reality stops matching the promise.
Founder and principal of Michai Media. Joshua builds and operates search, AI, automation, API, and software systems for businesses across the United States.
About the studio →