Seven Waysto Talk
Every API is a decision about how two programs hold a conversation. There are only a handful of questions that decision answers, and seven names worth knowing. Learn the questions, and the names choose themselves.
The whole field in thirty seconds
An API is a contract for how two machines talk, and there are only a few axes that matter: who speaks first, whether the line stays open, whether you trade one question for one answer or a continuous stream, and whether the bytes are made for a human to read or for a machine to parse. REST borrows the web's own grammar and wins by default. gRPC drops to compact binary for traffic between your own services. GraphQL hands the client a pencil so it can draw exactly the data it wants. Webhooks flip the call so the server tells you. WebSockets keep one line open so the server can push. WebRTC builds a direct line between two people with no server in the middle. And SOAP is the one you reach for when the contract outranks your preferences. Same questions, seven stable answers.
The Shape of a Conversation
Right now, on the device in your hand, dozens of programs are mid sentence. The weather widget asked for a forecast. Your messages app is waiting to be told the moment a reply lands. A music app is pulling a playlist down in pieces. None of them invented how to talk. Each one picked a pattern that already existed, because the patterns are not infinite.
We treat APIs like a catalogue of competing products, as if choosing one were a matter of taste or fashion. It is not. An API is a decision about the structure of a conversation between two programs, and a conversation has a finite anatomy. Strip away the logos and the marketing, and every one of the seven famous styles is just a stable answer to the same small set of questions.
Here are the questions. Who speaks first? In most conversations one side asks and the other answers, but in some the server is the one who reaches out, and in a few either side may speak at any moment. Does the line stay open? You can hang up after every exchange and dial again next time, or you can keep a single connection alive and reuse it. What is the shape of the exchange? One question for one answer, a single request that triggers a stream of replies, or a continuous duplex where both sides talk over each other. What do the bytes look like? Text that a person can read at the cost of size and speed, or packed binary that only a machine will ever decode. Does anyone remember? A stateless exchange forgets you the instant it ends, which is precisely what lets you add a tenth server on a busy afternoon. And who sits in the middle? A server relaying every byte, or a direct path between two peers with nothing in between.
Keep those questions in your pocket. We will hold each of the seven styles up against them, one at a time, and ask the only three things that matter in practice: when the situation calls for it, why it is shaped the way it is, and how the mechanism actually works. By the end you will have a map, and the map will do the deciding for you.
REST, the Grammar of the Web
Start here, because almost everything starts here. REST stands for Representational State Transfer, which is an academic name for a simple move: stop inventing your own protocol and borrow the one the web already runs on.
- Initiates
- Client
- Connection
- Per request
- Shape
- Ask, answer
- Payload
- Text, usually JSON
- State
- None held
The web already had a grammar long before anyone needed an API. It had verbs, GET to read, POST to create, PUT to replace, DELETE to remove, and it had addresses, the URL. REST says model your domain as a set of resources, give each one an address, and use the verbs that already exist to act on them. You do not design a new language. You speak the one billions of documents already speak.
Why it is shaped this way
The quiet genius of REST is the word stateless. The server remembers nothing about you between calls. Every request carries everything it needs to be understood on its own. That sounds like a limitation, and it is the single most valuable property in the whole catalogue, because it means any server can answer any request. That is what lets you put ten identical servers behind a load balancer and add an eleventh when traffic spikes. State is the thing that makes scaling out painful, and REST refuses to hold it by design.
Where it costs you
The resource model is rigid, and that rigidity has a price. A single screen that needs a user, their last five orders, and the shipping status of each order becomes three or four round trips, or one bloated endpoint that returns far more than the screen will ever show. REST is honest plumbing. It is not a precision instrument, and the next two styles exist precisely because of that gap.
SOAP, the Formal Contract
If REST is a casual phone call, SOAP is a contract signed in triplicate. It stands for Simple Object Access Protocol, and despite the name it is anything but simple. It is what an API looks like when the consequences of a single wrong or lost message are measured in lawsuits, audits, or someone's medical record.
- Initiates
- Client
- Connection
- Per request
- Shape
- Ask, answer
- Payload
- XML envelope
- State
- Optional
Every SOAP message is wrapped in a strict XML structure: an envelope that contains a header and a body. The shape is not decoration. The header is where security tokens, routing rules, and reliability metadata travel, inside the message itself, independent of whatever transport carries it. The body holds the actual call. The whole interface is described up front in a formal contract, so a counterparty can generate code against it without ever talking to you.
Why it survives
Nobody chooses SOAP for a new consumer product, and yet it refuses to die, because it lives where regulation and trust boundaries live. Banks settling money between each other, insurance clearinghouses, government registries, hospital systems exchanging patient records. These systems change slowly, often by law, and they value a binding contract, a paper trail, and security baked into the protocol rather than bolted on afterward. When guaranteed delivery and compliance matter more than a pleasant afternoon for the developer, this is the shape that wins.
gRPC, Built for Machines
Here is a first principle that reorganizes everything: text is for humans, and your services are not humans. JSON spends bytes and processor time on every single message describing its own structure, the field names, the braces, the quotes, so that a person could in theory read it. Between two of your own services that no person will ever read, that is pure waste.
- Initiates
- Either side
- Connection
- Persistent, HTTP/2
- Shape
- Four kinds
- Payload
- Binary, Protobuf
- State
- Per call
gRPC answers the waste with Protocol Buffers. You define the schema once, the messages and the methods, and both sides compile against it. On the wire you then send only the values, packed into a compact binary layout, with the structure already known to both ends. The result is dramatically smaller and faster to parse, and the schema doubles as the contract. On top of that it rides HTTP/2, which carries many calls over one connection at the same time, so you stop paying the connection setup tax on every request.
The four shapes are the design act
The part people miss is that gRPC is not one conversation shape but four, and choosing among them is the real work. Unary is the familiar one ask for one answer. Server streaming is one request that opens a tap of replies, the right shape for a live feed of a driver's location. Client streaming is a tap flowing the other way, a stream of telemetry or a file sent in chunks. And bidirectional lets both ends speak at once, the shape of a live negotiation between two services.
Where it costs you
Binary is not friendly. You cannot read it by eye, you need code generation and tooling, and a browser cannot speak raw gRPC without a translating proxy. So gRPC lives inside your own walls, where you control both ends, where latency and throughput are real money, and where a typed contract between services is worth more than human readability you will never use.
GraphQL, Exactly What You Asked For
REST has a structural mismatch baked in. Its unit is the resource, and the server decides the shape of every response. The client, which actually knows what the screen needs, has no say. That mismatch produces two chronic diseases, and GraphQL is the cure for both.
- Initiates
- Client
- Connection
- Per request
- Shape
- Client shapes it
- Payload
- Text, JSON
- State
- None held
The first disease is over fetching: an endpoint hands back a fat object when the screen needed three fields of it. The second is under fetching: the screen needs data from several resources, so the client fires several requests and waits on a waterfall of round trips. GraphQL inverts the authority. The client sends one query describing the exact tree of data it wants, the server resolves precisely that tree, and the answer comes back in a single response. No waste, no waterfall.
There is a second, quieter gift. A GraphQL schema is self describing. The types and fields can be introspected, so a frontend engineer can discover everything available, and tools can autocomplete and validate a query, without booking a meeting with the backend team. The contract is machine readable and lives in one place.
Where it costs you
You do not delete complexity, you move it from the network onto the server. Arbitrary client queries make caching harder, because every shape is effectively a different request. They open the door to expensive deeply nested queries that you must defend against with depth and cost limits. And the resolver layer that turns a query into data is real engineering. GraphQL earns its keep when many different clients, web, phone, partners, all need different slices of one rich, interconnected graph, and the bottleneck really is round trips and over fetching.
Webhooks, the Reverse Call
Everything so far has the client asking and the server answering. Webhooks turn that around, and the reversal is the whole point.
- Initiates
- Server
- Connection
- Per event
- Shape
- One way notice
- Payload
- Text, JSON
- State
- None held
Without them, the only way to learn about something new is to keep asking. Your app walks to the mailbox every thirty seconds and checks. That is polling, and it is wasteful twice over: it burns requests that almost always come back empty, and the best case latency is your poll interval. The event you care about might be rare and might be urgent, and polling is bad at both. So invert it. Instead of you asking, the source tells you the instant something happens, by making an HTTP request to a URL you registered with it. The doorbell instead of the trip to the mailbox.
This is the natural glue between systems you do not own. You cannot hold a socket open to a payment provider forever, and the provider cannot poll you. But the provider can POST to your callback URL the moment a payment settles. That is why webhooks are sometimes called reverse APIs, and why they quietly power most cross company automation.
Where it costs you
You now run a public endpoint, and that comes with duties. Anyone can send a request to it, so you must verify a signature on every delivery. Deliveries can repeat, so your handler must be idempotent, safe to receive twice. And they can retry or arrive out of order, so you cannot assume a tidy sequence. The provider owns sending. You own receiving correctly.
WebSockets, the Open Line
Plain HTTP is call, answer, hang up. To talk again you dial again, and the server can never call you. For anything that changes continuously and unpredictably, a chat, a price, a game, that model fights the problem the whole way.
- Initiates
- Either side
- Connection
- Persistent
- Shape
- Full duplex
- Payload
- Text or binary
- State
- Per connection
A WebSocket starts as an ordinary HTTP request and then upgrades into something different: one connection that stays open, over which both ends can send a message the instant they have one, with almost none of the overhead of opening a fresh request each time. The crucial change from REST is direction. The server can push. The moment the price ticks, the server sends it, and the client never had to ask.
Where it costs you
A persistent connection is stateful, and state is what makes scaling hard. You have to track which server holds which open connection, usually with a shared message bus behind the scenes so that a message can find the right client wherever it landed. The connection survives poorly across flaky mobile networks without careful reconnect logic, and every open client ties up resources on the server. You take all of that on in exchange for one thing: the server can speak the instant it has something to say.
WebRTC, the Straight Line
The last one is the strangest, because it is barely an API at all. WebRTC is a whole framework, and its reason to exist is a single stubborn fact: for live audio and video between two people, every extra hop is latency you can hear and lag you can see. The lowest latency path is a straight line from one device to the other, with no server relaying a single byte.
- Initiates
- Either side
- Connection
- Persistent, direct
- Shape
- Full duplex
- Payload
- Binary media or data
- State
- Per session
When you are on a video call, your picture is not travelling to a company server and then on to the other person. Where it can, it goes straight from your device to theirs, peer to peer. The hard part is not sending the bytes once you have a path. The hard part is finding the path. Both of you sit behind home routers, neither device knows its own public address, and firewalls block uninvited traffic. Two machines that do not know each other's real location somehow have to meet in the open internet.
WebRTC solves this by separating the jobs. A signaling channel, which you provide, often over a WebSocket, lets the two peers exchange the metadata they need to connect. A STUN server tells each peer the public address it appears to have from the outside world. When a direct path genuinely cannot be made, a TURN server steps in to relay, trading away the low latency for a connection that at least works. Once a path is found, the media flows directly, and WebRTC handles the rest on its own: adaptive bitrate, codec negotiation, jitter buffering, packet loss concealment, all aimed at staying under the threshold where a person notices delay.
Where it costs you
It is genuinely the most complex thing in this guide. The signaling is yours to build. TURN relays cost real money and quietly reintroduce the hop you were trying to avoid. And pure peer to peer stops scaling the moment a call has more than a few people, at which point you give up the straight line for a media server that mixes and forwards. The reward is that it is built into every modern browser, with no plugin, and when it works it is the fastest path two devices can share.
Choosing, in Practice
Lay the seven out on the two axes that separate them most cleanly. Across the bottom, how tightly the two ends are bound together, from loose and public on the left to tightly coupled and internal on the right. Up the side, the shape of time, from a single exchange at the bottom to a continuous real time flow at the top. Almost every decision is really a question of where your problem sits on this map.
A working procedure, in the order you should actually run it. Start at REST. It is the default for a reason and it clears most of the field, because most of what you build is a domain you can model as resources, read and written by clients that never need to be told something they did not ask for. If both ends are yours and you are paying for every millisecond and every byte, drop to gRPC. If many different clients each want a different slice of one rich graph and the pain is round trips, climb to GraphQL. If you are wiring into a system you do not own and need to react to its events, you do not poll, you receive webhooks. If the server has to push continuously into a browser, open a WebSocket. If two clients need a direct low latency link for media or data, build it with WebRTC. And if you are integrating with a bank, a hospital, or a government, you will probably speak SOAP, because there the contract outranks your preferences.
| Style | Reach for it when | The cost you accept | Seen in |
|---|---|---|---|
| REST | A domain modelled as resources, read and written by clients | Rigid shape, over fetching, extra round trips | Most public web APIs |
| SOAP | Regulated, high trust integration across organizations | Heavy, verbose, slow to build against | Banking, healthcare, government |
| gRPC | Traffic between your own services, where speed is money | Binary, needs codegen, no plain browser support | Internal service meshes |
| GraphQL | Varied clients want varied slices of one rich graph | Server complexity, harder caching, query limits | Product platforms with many clients |
| Webhooks | React to events in a system you do not control | Public endpoint, signatures, idempotency, retries | Payments, repo events, order flows |
| WebSockets | The server must push continuously to a browser | Stateful, harder to scale, fragile on mobile | Chat, live dashboards, trading |
| WebRTC | Direct low latency media or data between two clients | Complex setup, relay costs, scaling limits | Video calls, voice, peer transfer |
The seven names are not a menu you order from by mood. They are the field's accumulated answers to a few plain questions about who talks, when, in what shape, through whom, and at what cost. Most arguments about which API style is best are really arguments about which problem you are solving, conducted by people who have not noticed they disagree about that first.