Siirry sisältöön

The REST Request, Taken Apart

Tämä sisältö ei ole vielä saatavilla valitsemallasi kielellä.

Module 1 of 6 in the chapter APIs, Contracts and Data Across the Wire, chapter 3 of the Integration Architect course. Each module stands on its own. Previous chapter: The Client and Server · Next: The Contract

The question this module answers: What is actually in a REST call, piece by piece, and what does each piece of the answer tell you?

In the last chapter, you made your first call. You typed an address, pressed Send, and an answer came back. Now we open that call up and look inside.

Today, the most common way for two systems to talk is REST, over the internet. It wasn’t always.

Systems used to talk to each other in many ways: straight over the network’s own protocols, TCP and UDP, on whatever ports they chose, and through technologies built just for server-to-server calls. But as companies locked their networks down behind firewalls, most of those ports were closed. The ones that stayed open were the ports for the web: 80, and 443 for secure traffic, and sometimes a second secure port such as 8443. Every browser needed them, so they had to stay open.

So integration moved onto the web’s own road. First came SOAP, which sent its requests over the web’s protocol, HTTP. Then came REST, which went further and used the web the way browsers already did. You call an address, just like landing on a page. But instead of answering with a web page in HTML, the server answers with data, most often in JSON. And the web’s own verbs, get, post, put, patch and delete, became the actions. That’s how they became the common language between systems across the internet.

REST was described by Roy Fielding in 2000, as an architectural style for the web (Representational State Transfer (opens in a new tab), chapter 5 of his dissertation). REST stands for representational state transfer. The name matters less than the idea: a REST call is a lot like asking for a web page. You go to an address, you say what you want to do, and the server answers. The longer story, and the older ways that still run in some companies, is chapter 16.

Every REST call is built from the same few pieces. There’s a verb, and then there are three places to put things: the address, the headers and the body. Learn those, and you can read any call.

To keep it concrete, we’ll take apart one call, from Steve Trucking’s own delivery API. The address uses a name set aside for examples, so you can’t call it, but every piece is real.

GET /v1/deliveries/D-1042 HTTP/1.1
Host: api.steve-trucking.example
Authorization: Bearer (the token)
Accept: application/json

The verb comes first. It says what you want to do. When I ask a class for the verbs, I get them all at once: get, post, put, patch. Let’s walk through them.

  • GET means I’m getting data. It only reads.
  • POST creates something new: it didn’t exist before.
  • PATCH changes a little piece: change the delivery’s status, and leave everything else alone.
  • PUT is a complete replacement: it puts the whole thing there, creating it if it didn’t exist, or replacing all of it if it did.
  • DELETE, the one people forget to name, removes it.

So: post is new, patch is a little piece, and put is the whole thing. If you know databases, the drawing below gives each verb its nearest database statement: GET is like a select, POST an insert, PATCH an update, PUT an upsert, and DELETE a delete.

The verbs Five panels, each with its nearest database statement. GET, read it, like a select: gets the data; no body; the answer may be cached. POST, create something new, like an insert: it didn't exist before; sends a body. PATCH, change a little piece, like an update: only the fields you send change; sends a body. PUT, replace the whole thing, like an upsert: creates it, or replaces it all; sends a body. DELETE, remove it, like a delete: no body needed. Underneath: the server decides which verbs it accepts; the contract tells you. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.52.0", "built": "2026-10-28", "id": "DGM-INT-AC-02", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "comparison/side-by-side 0.5.0", "theme": "stevetecharc 1.4.0"} GET read it Like a SELECT Gets the data No body The answer may be cached POST create something new Like an INSERT It didn't exist before Sends a body PATCH change a little piece Like an UPDATE Only the fields you send change Sends a body PUT replace the whole thing Like an UPSERT Creates it, or replaces it all Sends a body DELETE remove it Like a DELETE No body needed The server decides which verbs it accepts. The contract tells you. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

The verbs. Post is new, patch is a little piece, put is the whole thing.

Two more things about verbs. First, a GET may be cached. It only reads, so something between you and the server is allowed to keep a copy of the answer and hand it back next time. Whenever you do a GET, think that the answer might be a copy.

Second, you don’t choose the verb; the server does. Whoever builds the server decides which verbs it accepts for each address, and the specification tells you. Send a POST to an address that only takes a GET, and it fails. Got to get your verb right. That’s the contract, and it’s the next module.

The address says where you’re going, and it reads in two halves.

https://api.steve-trucking.example/v1/deliveries/D-1042

To the left of the first slash is the name: which server. You met names in Finding the Server. Read it from the right: example, then steve-trucking, then api. The part in front, api, is a subdomain, and each subdomain can point to a different server. Steve Trucking can have api. for its API, login. for signing in and www. for its website, each on its own servers. But the domain itself, steve-trucking.example with nothing in front, points to only one place.

To the right of the first slash is the path: what, on that server. One server can offer many things, so the path is its own map of what it has. Here, /v1 is the version of the API, /deliveries is the kind of thing, and /D-1042 is the one delivery you want.

Reading an address Two panels. The name, left of the first slash, which server: read from the right, example, steve-trucking, api; each subdomain can be its own server, such as api., login. and www.; the domain itself points to one place. The path, right of the first slash, what on that server: /v1, the version; /deliveries, the kind of thing; /D-1042, the one you want; after a question mark, the parameters. Underneath: the name finds the server; the path finds the thing on it. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.52.0", "built": "2026-10-28", "id": "DGM-INT-AC-04", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "comparison/side-by-side 0.5.0", "theme": "stevetecharc 1.4.0"} The name left of the first slash: which server Read from the right: example, steve-trucking, api Each subdomain can be its own server api., login., www. The domain itself points to one place The path right of the first slash: what, on that server /v1: the version /deliveries: the kind of thing /D-1042: the one you want After a ?: the parameters api.steve-trucking.example/v1/deliveries/D-1042: the name finds the server, the path finds the thing on it. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Reading an address: the name finds the server, and the path finds the thing on it.

After the path, you can add parameters: a question mark, then a name and a value, joined to the next one with an ampersand.

https://api.steve-trucking.example/v1/deliveries?status=Delivered&depot=North

Are spaces allowed in an address? They’re not. Spaces and other special characters have to be encoded: a space becomes %20. That’s called percent-encoding (RFC 3986 (opens in a new tab), section 2.1), and your API client usually does it for you. But encoding makes the address longer.

And addresses can’t grow forever. The HTTP standard recommends that everyone support addresses of at least 8,000 characters (RFC 9110 (opens in a new tab), section 4.1), but servers, gateways and tools along the way set their own limits, and some are much lower. I’ve seen queries with so many conditions that the address went past 2,000 characters and started to fail. So we don’t want an address that keeps on growing. When a query can get very long, some APIs take it in the body of a POST instead. Data 360’s Query API does exactly that: the SQL goes in the body (Migrate to Query API V3 (opens in a new tab), Salesforce Developers, checked 2026-11-01). It’s still a question, sent as a POST, because the question is too big for an address.

The second place to put things is the headers, and they’re really important. Headers aren’t the data. They’re about the call: who you are, what you’re calling with, and how the server should handle it.

What’s the most common thing in a header? Who you are. That’s where the token from Knocking on the Door goes, on every call:

Authorization: Bearer (the token)

“Bearer” means whoever bears, or carries, this token gets in. That’s why a token is treated like a password: anyone holding it is you, until it runs out. Chapter 12 goes much further.

The next two headers are about the format of the data:

  • Content-Type says what you’re sending: JSON, XML, a file.
  • Accept says what you want back.

The way in should equal the way out. If you send JSON, you should expect JSON back. Not always the case, though. I once sent JSON out and got XML back. So don’t assume: for every call, know what goes out and what comes back.

Then there’s what you’re calling with. The User-Agent header, the one you saw in chapter 2, names the browser or the tool making the call. Your API client adds it, and so does every browser. Servers use it to decide what to send back, and to see in their logs who’s calling.

And headers can hold more. I’ve found paging controls in headers, and set a query’s batch size in one. The headers are where a lot of things hide.

The third place is the body: the data itself. The body is optional.

A GET has no body. Everything a GET needs is in the address and the headers. The standard is clear that “A client SHOULD NOT generate content in a GET request” (RFC 9110 (opens in a new tab), section 9.3.1).

POST, PUT and PATCH do carry a body, and it can be large. Here’s Steve Trucking marking that delivery as delivered, with a PATCH. Notice the Content-Type header, because now there’s a body to describe:

PATCH /v1/deliveries/D-1042 HTTP/1.1
Host: api.steve-trucking.example
Authorization: Bearer (the token)
Content-Type: application/json
Accept: application/json
{
"status": "Delivered"
}

Only the status changes. That’s patch: a little piece.

Three places to put things Three panels. 1, the address, where you're going: the server, the version and the thing, such as /v1/deliveries/D-1042; parameters after the question mark, joined by ampersands; spaces and symbols encoded. 2, the headers, about the call: who you are, in Authorization; what you're sending, in Content-Type; what you want back, in Accept; sometimes more, like a batch size. 3, the body, what you're sending: optional; none on a GET; carried by POST, PUT and PATCH; can be large. Underneath: the verb comes first, and it decides whether there's a body. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.52.0", "built": "2026-10-28", "id": "DGM-INT-AC-01", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "comparison/side-by-side 0.5.0", "theme": "stevetecharc 1.4.0"} 1. The address where you're going The server, the version, the thing /v1/deliveries/D-1042 Parameters after the ?, joined by & Spaces and symbols are encoded 2. The headers about the call Who you are: Authorization What you're sending: Content-Type What you want back: Accept Sometimes more, like a batch size 3. The body what you're sending Optional None on a GET Carried by POST, PUT and PATCH Can be large The verb comes first, and it decides whether there's a body. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Three places to put things: the address, the headers and the body.

That’s the ask. Now the answer. The response has the same shape: a status, headers, and usually a body.

HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "D-1042",
"status": "Delivered",
"depot": "North"
}

The first thing to look at is the status. Always, always check the status code. It’s a three-digit number, and the first digit tells you most of what you need to know (RFC 9110 (opens in a new tab), section 15):

  • The 200s are good news. 200, you asked for something and got an answer. 201, you asked it to create something, and it did. 204, it did what you asked and has nothing to send back.
  • The 300s say go somewhere else. The answer is at another address. In calls between systems, you’ll rarely see them. But in signing in, they’re everywhere: single sign-on works by sending the browser from the app to the identity provider and back again, with redirects. Chapter 12 follows one.
  • The 400s are a problem with the client. It’s something the client needs to fix before it tries again. 400, you asked something that makes no sense. 401, you’re not authorized: who are you? 403, I know who you are, and it’s not for you. 404, I don’t have that. And 429, too many requests: slow down (RFC 6585 (opens in a new tab), section 4).
  • The 500s are a problem with the server. The server couldn’t fulfill the request: 500, something broke inside; 503, not available right now. The client can’t fix it. It can only hope the server sends back enough to say what happened, and decide whether to try again later.

That’s the shape of it. Every standard code, with whose it is to fix and whether to try again, is in the HTTP Status Codes reference.

Status codes, by the hundred Four panels. 200s, it worked, in green: 200 OK, here's your answer; 201 Created, it's made; 204 No Content, done, nothing to send. 300s, go somewhere else, in blue: the answer is at another address; rare between systems; everywhere in single sign-on. 400s, the client's problem, in amber: the client has to fix it; 400 Bad Request, that makes no sense; 401 Unauthorized, who are you; 403 Forbidden, not for you; 404 Not Found, nothing there; 429 Too Many Requests, slow down. 500s, the server's problem, in coral: 500 Internal Server Error, it broke; 503 Service Unavailable, not now; hope the body says why. Underneath: always check the status first, then read the body for the details. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.52.0", "built": "2026-10-28", "id": "DGM-INT-AC-03", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "comparison/side-by-side 0.5.0", "theme": "stevetecharc 1.4.0"} 200s: it worked 200 OK: here's your answer 201 Created: it's made 204 No Content: done, nothing to send 300s: go somewhere else The answer is at another address Rare between systems Everywhere in single sign-on 400s: the client's problem The client has to fix it 400 Bad Request: that makes no sense 401 Unauthorized: who are you? 403 Forbidden: not for you 404 Not Found: nothing there 429 Too Many Requests: slow down 500s: the server's problem 500 Internal Server Error: it broke 503 Service Unavailable: not now Hope the body says why Always check the status first. Then read the body for the details. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Status codes, by the hundred. The first digit tells you whose problem it is.

That’s the tango from chapter 2, in numbers. A 400 means the client has something to fix. A 500 means the server does. And no status at all means the call never got there. Whether you write code or build in low-code, you need to handle each of them: the 200s, the 400s and the 500s.

Then read the rest. The status tells you whether it worked; the body tells you the details, of the answer or of the error. And the response’s own Content-Type tells you what form that body is in. Check it, rather than assume it.

One last thing, and it’s one of the most important in the course. A 200 means the server did what the contract said. It doesn’t mean the data was right.

“The API returned 200” isn’t data quality. If you sent 10,000 records, did 10,000 arrive, or did three get rejected inside a successful answer? Did a retry send something twice? The status tells you the call worked. Whether the data is right is a separate question, and the architect has to ask it. The Data Architect course asks it in Before the Arrow.

  • For every call, the verb, and whether the server’s contract allows it.
  • What goes in the address, the headers and the body, and what never goes in an address: secrets, and personal data.
  • The format going out and the format coming back, written down, not assumed.
  • How the client handles each family of status: the 200s, the 400s, the 500s, and no answer at all.
  • How long the client waits for an answer, and what counts as success beyond the status code.

Beyond the exam: what AI changes. AI can write a request like this in seconds, from a sentence. That makes it more important, not less, to read one. When AI hands you a call, check the verb, check what’s in each of the three places, and check that the code checks the status. Module 6 puts AI to work on the contract.