DEV Community

Cover image for You Know REST. Here Are the Five Other API Types That Actually Run the Internet.
Nishant Gaurav
Nishant Gaurav

Posted on

You Know REST. Here Are the Five Other API Types That Actually Run the Internet.

Most developers learn REST first and then assume it's the answer to every problem. It isn't. REST is one tool in a set of six, and the reason the others exist is that REST genuinely fails in specific situations: real-time communication, internal microservice performance, strict enterprise security, and flexible data fetching. Each API type on this list was invented to solve a problem REST couldn't.

If you've built with REST before, this article will give you a complete mental model of when to reach for something different and why.


What an API Is (One Paragraph, Then We Move On)

An API is a middleman between two systems. When you search "biryani" on Zomato, your app doesn't have that data stored locally. It sends a request to Zomato's server, and the server sends back a response with the results. The interface that defines how that request and response happen is the API. Think of it as a waiter in a restaurant: you don't walk into the kitchen yourself, you tell the waiter what you want, and the waiter brings it back. The waiter is the API.

Now, there are six different kinds of waiters.


REST: The Standard, and Its Limits

REST (Representational State Transfer) works over HTTP and is built on two things: a URL that tells you where the resource is, and a method that tells you what to do with it.

The four methods you use constantly: GET to fetch data, POST to create something new, PUT to replace or update existing data, and DELETE to remove it. Every request is stateless, meaning the server doesn't remember anything about you between calls. Each request carries everything the server needs to respond.

GET https://api.zomato.com/v1/restaurants?search=biryani
Authorization: Bearer <token>
Enter fullscreen mode Exit fullscreen mode

The server checks your identity, queries the database, and returns a JSON response.

When to use it: Public APIs, CRUD applications, any situation where the client and server are separate systems that need a clean, well-documented contract. REST is the default for good reason: it's simple, stateless, widely understood, and works over standard HTTP.

When not to use it: Real-time features (chat, live tracking), situations where you need data from multiple resources in a single call, or internal microservice communication where performance matters more than readability.


GraphQL: Ask for Exactly What You Need

REST has a well-known problem called over-fetching. You hit a /user endpoint and get back name, photo, age, branch, salary, and twenty other fields, when all you needed was the name and photo. The alternative is under-fetching: you need data from multiple resources, so you make multiple REST calls and stitch the results together in your client.

GraphQL fixes both problems with one endpoint and a query language that lets the client specify exactly what it wants.

# Instead of hitting /employees/123 and getting everything,
# you describe precisely what you need in the request body
query {
  employee(id: "123") {
    name
    photo
  }
}
Enter fullscreen mode Exit fullscreen mode

The response contains exactly those two fields, nothing more. If you also need salary, you add it to the query. No new endpoint required.

GraphQL has three operation types. A query reads data (equivalent to GET). A mutation writes or modifies data (equivalent to POST, PUT, DELETE). A subscription opens a real-time data stream for live updates, similar to WebSockets.

When to use it: Complex frontends that need flexible data fetching, mobile applications where bandwidth matters, and any scenario where multiple client types (web, mobile, third-party) consume the same API but need different data shapes.

When not to use it: Simple CRUD APIs where REST endpoints are straightforward. GraphQL adds implementation complexity on the server side, caching is harder than with REST, and it's overkill when your data requirements are predictable and stable.


WebSockets: The Persistent Connection

Here's the REST problem for real-time: to know if a new WhatsApp message has arrived, your client would have to ask the server every second: "Any new messages?" "Any new messages?" Across a million users, that's a million requests per second of pure overhead, most of which return "nothing new."

WebSockets solve this by replacing the request-response cycle with a persistent, two-way connection. The connection starts as a standard HTTP request but includes a special header asking to upgrade:

GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Enter fullscreen mode Exit fullscreen mode

When the server agrees, the HTTP connection is replaced by a WebSocket connection. From that point, both sides can send messages to each other at any time without either side needing to ask. The connection stays open until one side explicitly closes it.

A WebSocket connection has four states: Connecting (handshake in progress), Open (messages can flow freely), Closing (teardown initiated), and Closed (connection terminated). Sending a message on a closed connection crashes the server, which is a common beginner mistake.

When to use it: Live chat, multiplayer games, collaborative editing (like Google Docs), live sports scores, real-time notifications, anything where the server needs to push data to the client without being asked.

When not to use it: Standard data fetching where you only need data when the user requests something. WebSockets maintain persistent connections, which consume server resources. Using them where REST would suffice wastes that resource.


Webhooks: The Server Calls You

REST and WebSockets are both client-initiated. The client connects, the client asks, the server responds. Webhooks flip this entirely: the server calls you when something happens.

The pattern is simple. You give a third-party service a URL. You say: when a payment is completed, send a POST request to this URL. When the payment happens, Razorpay (or Stripe, or any payment provider) hits your URL automatically. You don't poll. You don't maintain a connection. You just wait to be called.

# What you give Razorpay in setup:
Webhook URL: https://yourapp.com/webhooks/payment

# What Razorpay sends when payment completes:
POST https://yourapp.com/webhooks/payment
{
  "event": "payment.captured",
  "payload": { "amount": 50000, "order_id": "order_abc" },
  "signature": "sha256_hash_here"
}
Enter fullscreen mode Exit fullscreen mode

The signature is critical. Since your webhook URL is a public endpoint that anyone can hit, a bad actor could fake payment events and trigger order fulfillment without actually paying. The signature is a hash that proves the request genuinely came from Razorpay. Your server verifies it before processing anything.

When to use it: Payment confirmations, order status updates, CI/CD triggers (GitHub calling your server when code is pushed), any event-driven integration where you need to react to something that happens in an external system.

When not to use it: Situations where you need immediate confirmation within the same user interaction. Webhooks are asynchronous and fire after the fact. If you need synchronous confirmation (the user is waiting on screen), REST is still the right tool.


gRPC: Binary Speed for Internal Services

A large application isn't one server. Zomato has an order service, a payment service, a notification service, a restaurant service, all running separately and calling each other thousands of times per second. Using REST for this internal traffic means serializing and deserializing JSON constantly. JSON is human-readable, which is convenient when you're debugging. It's also relatively expensive to parse at high frequency.

gRPC (created by Google for their own internal infrastructure) replaces JSON with Protocol Buffers (Protobuf), a binary format that's significantly more compact and faster to encode and decode. The same data that REST sends as readable JSON is sent by gRPC as a compact binary blob that machines process much faster.

// You define your data structure once in a .proto file
message OrderRequest {
  string order_id = 1;
  string user_id = 2;
  float amount = 3;
}
Enter fullscreen mode Exit fullscreen mode

Beyond the format difference, gRPC runs on HTTP/2, which supports multiplexing: thousands of simultaneous requests over a single connection, compared to HTTP/1.1 which handles one at a time. gRPC also supports four call patterns: Unary (one request, one response, like REST), Server Streaming (one request, many responses, useful for live order tracking), Client Streaming (many requests, one response, useful for chunked file uploads), and Bidirectional Streaming (many requests, many responses, for real-time collaborative features).

When to use it: Internal microservice communication where performance and type safety matter. Any system making high-frequency service-to-service calls where JSON parsing overhead adds up.

When not to use it: Public APIs where clients are browsers or third-party developers. Protobuf is binary and not human-readable, making debugging harder. Browser support also requires additional setup. REST is still cleaner for anything consumer-facing.


SOAP: Strict, Verbose, and Still Powering Banks

SOAP (Simple Object Access Protocol) was built in 1998 and predates REST. Most developers encounter it only when integrating with banking systems, insurance platforms, or large enterprise software, because those industries adopted SOAP early and haven't moved off it.

SOAP is strict and verbose. Every message is XML wrapped in a defined envelope structure. Where REST is flexible about format and structure, SOAP enforces a rigid schema that both sides must follow exactly.

<!-- Every SOAP message follows this envelope structure -->
<Envelope>
  <Header>
    <Security><!-- authentication goes here --></Security>
  </Header>
  <Body>
    <GetAccountBalance>
      <AccountId>ACC123</AccountId>
    </GetAccountBalance>
  </Body>
</Envelope>
Enter fullscreen mode Exit fullscreen mode

The verbosity is the point. SOAP's WS-Security standard provides authentication, digital signatures, and encryption simultaneously in a single message. For financial transactions where a message being tampered with mid-transit has serious consequences, that level of built-in security is worth the overhead.

When to use it: Integrating with banking APIs, payment gateways that require SOAP, government systems, insurance platforms, or any legacy enterprise system that exposes a SOAP interface. You'll rarely choose SOAP for a new system, but you'll need to understand it to work with systems that use it.

When not to use it: New projects where you control both sides. SOAP is slower to implement, harder to debug (XML is verbose), and offers no advantages over REST or gRPC for modern applications where you're not constrained by legacy compatibility.


The Decision Map

Here's how to choose:

Scenario API Type
Standard web app, public API REST
Mobile app needing flexible data GraphQL
Live chat, multiplayer, real-time push WebSocket
Payment confirmations, CI/CD triggers Webhook
Internal microservices, high performance gRPC
Banking, enterprise legacy integration SOAP


What You Now Understand

REST is the default. Everything else exists because REST fails in a specific situation: GraphQL when data requirements are flexible, WebSockets when the connection needs to stay open, Webhooks when you need to react to events rather than poll for them, gRPC when JSON is too slow for internal traffic, and SOAP when enterprise security requirements demand it.

The next time you start building an integration, the question isn't "how do I use REST for this?" The question is "which communication pattern fits what this system actually needs to do?" The answer determines the tool.

Pick one type you haven't used yet. Find its public documentation or a small open-source project that uses it. Read one real implementation before you need to build with it.

Top comments (0)