What is an API?
Updated June 3, 2026When Stripe launched in 2011, its API was so clean and well-documented that developers could process their first payment in under 10 minutes. That wasn't an accident. Stripe's entire business model was the API. They understood something fundamental: the API is the product.
So what actually is an API?
API as a contract — client sends request, server returns defined response shape
What APIs Are and Why They Exist
API stands for Application Programming Interface. It's a defined contract between two pieces of software that specifies how they can talk to each other.
Think of it like a restaurant menu. You don't go into the kitchen and cook your own food — you look at the menu, place an order, and the kitchen handles the rest. The menu is the API: it tells you what's available, what inputs you need to provide, and what you'll get back.
APIs exist because:
- Encapsulation — You want to expose functionality without exposing implementation. Twitter lets you post tweets through their API without you needing to know anything about their internal database schemas.
- Interoperability — Two systems built in completely different languages can communicate through a well-defined API. Your Python backend can call Twilio's API (built on whatever they use) to send SMS messages.
- Scalability — Teams can work independently. The frontend team uses the API contract to build the UI while the backend team implements the actual logic — neither needs to wait for the other.
REST vs GraphQL vs gRPC comparison — endpoints, single endpoint query, binary RPC
REST, GraphQL, and gRPC
There are three dominant API paradigms in use today. Here's what you actually need to know about each.
REST (Representational State Transfer)
REST is not a protocol — it's an architectural style. RESTful APIs use HTTP as the transport, model resources as URLs, and use HTTP verbs (GET, POST, PUT, DELETE, PATCH) to express operations.
GET /users/123 → Fetch user 123
POST /users → Create a new user
PUT /users/123 → Replace user 123
PATCH /users/123 → Update parts of user 123
DELETE /users/123 → Delete user 123REST is stateless — each request contains everything the server needs to process it. This is what makes it scale so naturally: any server in a fleet can handle any request.
Best for: Public APIs (Twitter, GitHub, Stripe all use REST), CRUD services, mobile and web frontends.
Downside: You can end up with over-fetching (the endpoint returns more data than you need) or under-fetching (you need multiple endpoints to assemble one screen's worth of data).
Which property of REST APIs makes them scale naturally across a server fleet?
GraphQL
GraphQL is a query language for APIs. Instead of fixed endpoints, clients send a query describing exactly what data they want, and the server returns exactly that — nothing more, nothing less.
query {
user(id: "123") {
name
email
posts(last: 5) {
title
createdAt
}
}
}This single request returns the user's name, email, and their last 5 post titles — in one round trip, no over-fetching.
Best for: Complex frontends with diverse data needs (Facebook invented it for this reason), mobile apps where bandwidth is precious, teams where the frontend moves faster than the backend.
Downside: More complex to implement and cache than REST. N+1 query problems are real if you're not careful with batching (look up DataLoader).
GraphQL solves which specific pain point of REST APIs?
gRPC
gRPC is a high-performance RPC (Remote Procedure Call) framework from Google. It uses Protocol Buffers (a compact binary serialization format) and HTTP/2 (which supports multiplexing and bidirectional streaming).
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc StreamUserActivity(User) returns (stream Activity);
}Because it's binary (not JSON text), gRPC payloads are significantly smaller and faster to serialize/deserialize. It also generates client code automatically from the schema definition.
Best for: Internal service-to-service communication (microservices), high-throughput systems, streaming use cases.
Downside: Not human-readable (you can't curl a gRPC endpoint and read the response), browser support is limited without a proxy layer.
gRPC uses HTTP/2 and Protocol Buffers. True or False: this means gRPC responses are human-readable and easy to debug with curl.
API Contracts and Versioning
An API contract is a formal agreement about what the API provides. An API contract covers the available endpoints and methods, request parameters and their types, the response shape and status codes, and error formats.
Tools like OpenAPI/Swagger (for REST) and Protocol Buffers (for gRPC) let you define this contract as code, generate documentation automatically, and even generate client SDKs in multiple languages.
Versioning
APIs change. New fields get added, old ones get removed. The challenge is that once you release an API, external developers are depending on it — breaking changes break their applications.
The most common strategies:
URI versioning — The version is in the URL: /v1/users, /v2/users. Simple and explicit. GitHub and Stripe both use this approach.
Header versioning — The version is specified in a request header: API-Version: 2024-01-01. This keeps URLs clean. Stripe actually uses date-based header versioning for fine-grained version control.
The golden rule: Never remove or change the type of an existing field in a public API — only add new ones. Removing fields is a breaking change. Adding fields is (usually) not.
A public API currently returns a field called `created_at`. A new version needs to rename it to `createdAt`. What is the correct approach?
What Makes a Good API Design
The best APIs feel obvious in hindsight. Here's what separates good from great:
Consistent naming conventions: If you return created_at in one endpoint, don't return dateCreated in another. Pick a convention (snake_case or camelCase) and stick to it everywhere.
Meaningful error messages: An error response of {"error": "invalid input"} is useless. {"error": "email_invalid", "message": "The email field must be a valid email address", "field": "email"} tells the developer exactly what went wrong and how to fix it. Stripe's error responses are the gold standard here.
Sensible defaults and pagination: Never return an unbounded list. If someone queries GET /messages, default to the most recent 20 and provide cursor-based pagination for the rest.
Idempotency for mutations: Make it safe to retry requests. (We'll cover this in depth in the Idempotency chapter.)
Rate limiting with clear headers: Tell clients how many requests they have left: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. When you throttle them, return 429 Too Many Requests with a Retry-After header.
Returning a 429 status code with a `Retry-After` header is considered good API design for rate limiting.
The Twilio API is a great example of real-world API design done right. Each resource is clearly named, errors are human-readable, and their documentation includes working code samples in every major language.
Which API paradigm is best suited for high-throughput internal service-to-service communication in a microservices architecture?
Summary
An API is the contract between two systems — it defines what you can ask for and what you'll get back. REST dominates public APIs. gRPC dominates internal microservice communication. GraphQL wins where frontend data requirements are complex and varied.
A great API is consistent, predictable, versioned, and treats error messages as first-class features — not afterthoughts. Stripe and GitHub are worth studying purely from a design perspective, not just a technical one.
Saved on this device only
Sign in to sync progress across devices