Software Architecture Basics

LESSON 03

Software Architecture Basics

APIs and Contracts

An API is a promise. Breaking that promise breaks every system that depends on you.

12 min read

An API (Application Programming Interface) is how one piece of software talks to another. When your mobile app fetches a user's profile, it makes an API call to your backend. When your backend charges a credit card, it makes an API call to Stripe. When you integrate with another company's platform, you consume their API. Every API is a contract: you send data in a specific format, and you receive a response in a specific format. That contract must remain stable or everything breaks.

REST (Representational State Transfer) is the dominant API architecture for web services. A RESTful API uses standard HTTP methods: GET to retrieve data, POST to create, PUT or PATCH to update, DELETE to remove. Resources are identified by URLs, like /users/123 or /orders/456. REST APIs are stateless — each request contains all the information needed to process it. The server does not remember previous requests. This simplicity is why REST won.

GraphQL is an alternative to REST that lets clients request exactly the data they need. Instead of hitting /users/123 and getting back a fixed set of fields, a GraphQL client specifies which fields it wants: just the name and email, or the full profile including order history. This eliminates over-fetching (getting data you do not need) and under-fetching (making multiple requests to assemble a view). The trade-off is complexity: GraphQL requires more sophisticated server infrastructure and client tooling.

Versioning is how you evolve an API without breaking existing clients. When you need to change a response format or remove a field, you create a new version — /v2/users instead of /v1/users. Old clients keep using v1 until they migrate. The alternative is breaking changes: deploying a new API format and forcing every client to update simultaneously. Breaking changes cause outages and angry customers. Versioning is an operational tax you pay to avoid breaking the contract.

Rate limiting is how you prevent abuse and ensure fair access to your API. Every client gets a quota: 1000 requests per hour, or 100 per minute. Exceed the quota and you get a 429 error. Without rate limits, a single misbehaving client can consume all your server capacity. With poorly designed rate limits, legitimate users hit the ceiling during normal usage. Setting the right limits requires understanding your actual traffic patterns, not guessing.

Authentication and authorization are distinct concerns. Authentication is proving who you are: logging in with a username and password, presenting an API key, exchanging an OAuth token. Authorization is proving what you are allowed to do: can this user view this resource, modify it, delete it? Many security breaches happen because systems authenticate correctly but fail to authorize — they verify identity but do not check permissions.

API documentation is not optional. If your API is undocumented, it does not exist — developers will not use it, or they will use it wrong and blame you when it breaks. Good documentation specifies every endpoint, every parameter, every possible response code, and provides working code examples in multiple languages. Documentation that is out of sync with the actual API is worse than no documentation because it creates false confidence.

Webhooks invert the API model: instead of clients repeatedly polling your API to check for updates, your server pushes updates to the client when something happens. When a payment succeeds, Stripe sends a webhook to your server. When a user signs up, your auth service sends a webhook to your notification service. Webhooks reduce load and latency, but they require clients to expose an endpoint and handle retries when delivery fails.

The cost of an API is not building it — it is maintaining backward compatibility as your product evolves.

This lesson is coming soon.

TERMS

Term of focus

REST API

An architectural style for web APIs that uses HTTP methods (GET, POST, PUT, DELETE) and treats resources as URLs. REST APIs are stateless, meaning each request is independent. They are simple to build and widely supported, making them the default choice for most web services. The downside is inflexibility — clients get whatever data the server decides to return.

A query language for APIs that lets clients specify exactly what data they need in a single request. Instead of multiple REST endpoints returning fixed responses, GraphQL exposes one endpoint where clients send queries describing the shape of data they want. This reduces over-fetching and eliminates the need for multiple round trips, but requires more complex server logic and tooling.

The practice of maintaining multiple versions of an API simultaneously so that changes to the API do not break existing clients. Versioning allows you to evolve your API (add fields, change formats, remove endpoints) while giving clients time to migrate. Common strategies include URL versioning (/v1/, /v2/) and header-based versioning. Failing to version properly causes production outages.

Restricting how many requests a client can make to your API within a time window. Rate limits prevent abuse, ensure fair usage, and protect your infrastructure from being overwhelmed. Limits are enforced per API key or per IP address. When a client exceeds the limit, the server returns a 429 status code. Setting limits requires balancing legitimate use cases against potential abuse.

Authentication verifies identity ("Who are you?") — typically with API keys, OAuth tokens, or session cookies. Authorization verifies permissions ("What are you allowed to do?") — checking whether the authenticated user can read, write, or delete a specific resource. Many APIs get authentication right but fail at authorization, allowing users to access data they should not see.

An HTTP callback that your server sends to a client when an event occurs, eliminating the need for clients to poll your API repeatedly. When a user signs up, your server POSTs to the client's webhook URL with user details. Webhooks reduce latency and server load but require clients to handle retries, verify signatures, and expose a publicly accessible endpoint.

A property where making the same API request multiple times has the same effect as making it once. GET and DELETE are naturally idempotent. POST usually is not — posting the same payment request twice charges the customer twice. Idempotent APIs use unique request IDs to detect duplicates and prevent unintended side effects from retries or network glitches.

BEFORE YOUR NEXT MEETING

If we changed the response format of this API endpoint today, how many clients would break, and do we have a way to notify them before deploying?

Can you walk me through what happens when a client exceeds their rate limit — do we return a helpful error message or just reject the request?

How do we verify that the user making this API request is authorized to access this specific resource, not just authenticated as someone valid?

If our webhook delivery fails because the client's server is down, what is our retry strategy, and how long do we keep trying?

Do we have a process for deprecating old API versions, or will we be supporting v1 forever?

REALITY CHECK

SOURCES

LESSON 03 OF 04