TL;DR HTTP is the language of the web; its verbs (methods) are the grammar that lets your client and server understand each other. Pick the right verb, send the right headers, and your API sings. Ignore the rules, and gremlins appear. This article explains the why and how - from raw request bytes to practical visual-programming workflows in Divooka.
We talked about the basics of using and designing REST APIs. Now we zoom in on the nuts & bolts:
<Request / Status Line>
<Header 1: value>
<Header 2: value>
...
<BLANK LINE>
<Optional Body>
That blank line (\r\n\r\n
) is the secret sauce: it tells everyone “headers are done; body begins.”
When working with HTTP methods, it helps to know three key properties that affect how requests behave—especially when you’re building flows, retrying actions, or caching responses.
These methods are read-only - they don’t change anything on the server. You can call them as often as you like without risk.
GET
, HEAD
, OPTIONS
These methods may change things, but doing them multiple times has the same effect as doing them once.
GET
, PUT
, DELETE
, HEAD
, OPTIONS
These are methods where the response can be safely stored (cached) by a browser or proxy server.
GET
(most common), sometimes HEAD
Quick Summary:
Property | What It Means | Common Methods |
---|---|---|
Safe | Doesn’t change data | GET , HEAD , OPTIONS |
Idempotent | Same result no matter how many times it’s sent | GET , PUT , DELETE , HEAD , OPTIONS |
Cacheable | Response can be stored for reuse | GET (default), HEAD |
Looking at the Raw Text helps us:
\r\n
separators) sent over TCP.Example: A simple GET request for a JSON resource
GET /api/users/123 HTTP/1.1
Host: api.example.com
Accept: application/json
User-Agent: Divooka/1.0
Authorization: Bearer <token>
Line-by-line breakdown:
1. GET /api/users/123 HTTP/1.1
* Request Line: <METHOD> <PATH> <HTTP-VERSION>
.
* Here, GET
is asking for the user with ID 123.
* HTTP/1.1
tells the server which version of the protocol we speak.
2. Host: api.example.com
* Required in HTTP/1.1 so the server knows which virtual host you want—especially important if one server hosts multiple domains.
3. Accept: application/json
* “I’d like JSON back, please.” If omitted, server usually defaults to HTML or its own default format.
4. User-Agent: MyVisualTool/1.0
* Identifies the client. Postman or Divooka would send something like PostmanRuntime/7.28.4
instead.
5. Authorization: Bearer <token>
* Common way to send a JWT or OAuth 2.0 token.
6. (Blank line)
* CRLF CRLF separator: Two consecutive \r\n
sequences mark the end of headers. Without this, the server will keep waiting for more header lines!
7. (No body follows, because GET doesn’t usually send one.)
Example: Server’s response to that GET
HTTP/1.1 200 OK
Date: Mon, 02 Jun 2025 14:35:22 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 111
Cache-Control: no-cache, no-store
ETag: "5f4dcc3b..."
{
"id": 123,
"name": "Alice",
"email": "alice@example.com",
"created_at": "2025-05-20T08:15:00Z"
}
Notes Content-Length
must equal 111 bytes (the exact JSON payload). If the server streams with chunked encoding, it omits Content-Length
and sends size-prefixed chunks instead.
Line-by-line breakdown:
1. HTTP/1.1 200 OK
* Status Line: <HTTP-VERSION> <STATUS_CODE> <REASON_PHRASE>
.
* Here, 200 OK
means “Success, and here’s the payload.”
2. Date: Mon, 02 Jun 2025 14:35:22 GMT
* The server’s clock. Handy if you need to compare timestamp headers or debug timeouts.
3. Content-Type: application/json; charset=utf-8
* Tells clients how to interpret the body. If your Divooka flow expected text/html, you’d know something’s off.
4. Content-Length:1117
* Exact byte length of the body that follows. Without this (or chunked encoding), clients won’t know where the body ends.
5. Cache-Control: no-cache, no-store
* Instructs intermediaries (browsers, CDNs) not to cache this response.
6. ETag: "5f4dcc3b5aa765d61d8327deb882cf99"
* An identifier for this specific version of the resource. Later, clients can send If-None-Match: "<etag>"
in a GET to check if data changed.
7. (Blank line)
* Signals “headers are done.” The next bytes belong to the body.
8. Body: Raw JSON payload, exactly 97 bytes long (including whitespace and line breaks).
{
"id": 123,
"name": "Alice",
"email": "[alice@example.com](mailto:alice@example.com)",
"created\_at": "2025-05-20T08:15:00Z"
}
Below is a more elaborate example showing how a POST /contacts
with a JSON payload looks in pure text. Notice the Content-Length
header must match the byte count of the body (including braces, quotes, newlines).
POST /api/contacts HTTP/1.1
Host: api.example.com
User-Agent: MyVisualTool/1.0
Content-Type: application/json
Content-Length: 84
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6...
{
"first_name": "Bob",
"last_name": "Smith",
"email": "bob.smith@example.com"
}
Contnt-Length: 85
, the server would wait for one extra byte or might reject your request.Some servers send large bodies in pieces (“chunks”) so they don’t need to know Content-Length
up front. Chunked responses look like this:
HTTP/1.1 200 OK
Date: Mon, 02 Jun 2025 15:00:00 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
1f <– hex length of first chunk: 31 bytes
{"page":1,"per_page":10,"total":42}
2a <– hex length of next chunk: 42 bytes
{"data":[{"id":1,...},{"id":2,...},...]}
0 <– “0” means “no more chunks”
1f
) followed by \r\n
. That tells you “31 bytes coming next.”\r\n
.2a
= 42 bytes), etc.0\r\n\r\n
signals “that’s all, thanks.”Content-Length
header. Instead, the client must reassemble chunks until it sees a zero‐length chunk.Oops | Symptom | Fix |
---|---|---|
Forgetting the blank line | “400 Bad Request” instantly | Add \r\n\r\n after headers |
Wrong Content-Length |
Connection hangs or truncates | Let your client/tool calculate it |
Mixed line endings (\n only) |
Some servers reject | Always use \r\n in raw mode |
CRUD stands for:
CRUD | Typical Method | Why This Pairing Works |
---|---|---|
Create | POST | Non-idempotent; server chooses new URI |
Read | GET (or HEAD) | Safe and cacheable |
Update-whole | PUT | Idempotent full replacement |
Update-partial | PATCH | Idempotent field-level change |
Delete | DELETE | Idempotent removal |
/auth/login
, POST /auth/logout
/payments/{id}/capture
/users/bulk_delete
with a JSON array of IDsEvery section below follows the same pattern:
Semantics • Idempotence / Safety • Typical Status Codes • Divooka Example • Common Pitfalls
{{base}}/users?active=true
→ connect to Preview JSON.Location
header) or 200 OK./users
, body {"name": "Bob"}
./users/123
with the complete user object (as JSON)./users/123
with {"email": "new@x.com"}
.DELETE
→ feed status into Branch: if 204 show “gone”, else log error.Content-Length
, Last-Modified
)./videos/intro.mp4
→ if Content-Length
> 10 MB, stream thumbnail instead.Allow
header & CORS rules.Access-Control-Request-Method
)./users
→ parse Allow
, enable/disable buttons dynamically.PROPFIND
, REPORT
. Divooka can send any token in the method field.Code | Verb(s) | Meaning | Divooka Tip |
---|---|---|---|
200 OK | GET/PUT/PATCH | Success with body | View in JSON Viewer |
201 Created | POST | Resource made; see Location |
Extract header to variable |
204 No Content | PUT/PATCH/DELETE | Success, no body | Skip JSON parsing |
301/302 | Any | Redirect, changes GET/POST rules | Auto-follow? Toggle in node |
307/308 | Any | Redirect, preserve method | Good for PUT → PUT |
400 | Any | Bad syntax/body | Show error toast |
401/403 | Any | Auth fail / forbidden | Refresh token logic |
404 | Any | Not found | Retry? Probably not |
405 | Any | Method not allowed | You picked wrong verb |
500/503 | Any | Server fault / overload | Add retry/backoff loop |
Content-Type
and Accept
– Autodetect is a myth./v2/users
) or header (Accept-Version
), don’t overload methods mid-flight._links
with method hints).If-None-Match
, If-Match
to save bandwidth & avoid lost updates.Below are three realistic workflows-each broken into clear steps-that show how different HTTP methods work together in a single flow. Think of each step as a node in Divooka: the method you pick drives what happens next. After these scenarios, there’s a quick look at how you might map one of them into a simple visual pipeline.
Imagine a new user signing up on your site. You need to prevent cross-site attacks, create the account, confirm their email, and finally let them update their profile. Here’s how it plays out:
Fetch a CSRF token (GET /csrf-token).
First, your client sends a GET /csrf-token
request. The server responds with a token in the body (for example, { "csrf_token": "abc123" }
). In Divooka, that might be a GET node connected to a “store token” node that saves csrf_token
into a variable.
Submit the registration form (POST /register).
Next, the client does a POST /register
with a JSON body like:
{
"username": "jane_doe",
"email": "jane@example.com",
"password": "s3cur3",
"csrf_token": "abc123"
}
If everything’s valid, the server returns status 201 (Created) and maybe a message saying “Please verify your email.” In Divooka, you’d use a POST node, include X-CSRF-Token
or put it in the JSON, and then route the response to a “check status” node. If it’s 201, move on; if it’s 400, show an error.
Poll for email verification (GET /verify?token=…).
After registration, the user clicks the link in their email (something like /verify?token=xyz
). Your client can simulate polling by repeatedly sending GET /verify?token=xyz
. Each time, the server might reply:
200 OK { "verified": false }
until the user clicks the real link200 OK { "verified": true }
once they’ve clickedresponse.body.verified
; if false
, wait a few seconds and retry (up to a limit); if true
, proceed.Update the new user’s profile (PATCH /users/{id}).
Once the account is verified, the client sends PATCH /users/123
(assuming the server gave back id = 123
) with, for example:
{ "display_name": "Jane Doe", "avatar_url": "https://..." }
This partial update lets the user personalize their account. The server returns 200 OK
and the updated user object. In Divooka, a PATCH node picks up the stored id
and sends the JSON patch. If it succeeds, you show “Welcome, Jane!”-if not, an error handler kicks in.
Suppose you run an e-commerce site and need to keep your warehouse in sync. You want to list all items, update stock levels, delete sold-out products, and add new ones in batch. Here’s a straightforward way:
Retrieve the current items (GET /items).
The client sends GET /items
, and the server returns a JSON array:
[
{ "id": 101, "name": "Widget A", "quantity": 5 },
{ "id": 102, "name": "Widget B", "quantity": 0 },
{ "id": 103, "name": "Widget C", "quantity": 12 }
]
In Divooka, a GET node feeds into a “For Each” node that iterates over each item in response.body
.
Update quantities where needed (PUT /items/{id}).
For any item whose stock changed-for example, Widget A went from 5 to 3-you send:
PUT /items/101
{
"id": 101,
"name": "Widget A",
"quantity": 3
}
Using Divooka, each loop iteration checks if quantity
needs adjusting; if yes, it calls a PUT node with the full item object. The server replies 200 OK
or 204 No Content
upon success.
Delete sold-out items (DELETE /items/{id}).
If quantity
is 0 (like Widget B), the client dispatches DELETE /items/102
. The server responds 204 No Content
meaning “Item gone.” In Divooka, the same For Each loop can contain a conditional: if quantity == 0
, call the DELETE node; otherwise, skip it.
Bulk-add new items (POST /items/bulk).
Finally, to add several new products at once, send one request:
POST /items/bulk
{
"items": [
{ "name": "Widget D", "quantity": 20 },
{ "name": "Widget E", "quantity": 15 }
]
}
The server returns 201 Created
with a list of new IDs:
{ "created": [ { "id": 104 }, { "id": 105 } ] }
In Divooka, that’s a single POST node with a JSON Builder that loops over your “newItems” list. After success, you might log a summary or show a “Bulk add complete” message.
When services get busy, you don’t want your entire flow to crash. Instead, handle 503 Service Unavailable
by retrying, then alert if it still fails. Here’s a simple pattern:
Initial request (GET /health-check).
Start with a GET /health-check
. The server normally returns 200 OK { "status": "healthy" }
. In Divooka, route the response into a “Switch” node that checks statusCode
.
If you see 503, pause and retry.
If statusCode == 503
, use a “Delay” node set to 5000 ms (5 seconds), then loop back to the same GET node. Keep a counter of retries-stop after 3 attempts. In Divooka, that might look like a small sub-flow with a variable retryCount
that increments each time you hit 503.
If still failing after retries, send an alert (POST /alerts).
When retryCount
hits 3 and you’re still receiving 503, switch to a POST /alerts
node, with body:
{
"message": "Health check still failing after 3 retries.",
"timestamp": "2025-06-02T15:00:00Z"
}
The server responds 201 Created
. In Divooka, you can connect that to a “Notification” node to email or log the issue.
If any GET succeeds (200), continue your normal flow.
As soon as you see 200 OK
from GET /health-check
, you break out of retries and proceed with other tasks (e.g., a scheduled data fetch or a critical update). In Divooka, that’s just another branch out of the Switch node for statusCode == 200
.
Below is a rough sketch of how Scenario B might look in Divooka. Each box represents a node, and arrows show data flow. The method (GET/PUT/DELETE/POST) in each node drives whether you’re fetching, updating, removing, or creating.
[Start]
↓
[GET /items] ← Fetch list of items
↓
┌───────────────┐
│For Each item │────────────────────────────────────────────────────╮
└───────────────┘ │
↓ │
[Check quantity] │
↓ │
[quantity > 0?] ─ No─▶[DELETE /items/{id}] ──→(Log “Deleted”) │
↓ Yes │
[quantity changed?] ─ No─▶(Skip update) │
↓ Yes │
[PUT /items/{id}] ──→(Log “Updated”) │
↓ │
⤵─────────────────────────────────────────────────────────────────┘
↓
[Collect results]
↓
[POST /items/bulk] ← Add new items
↓
[Show “Done” Message]
↓
[End]
For Each item
).quantity == 0
.
quantity
has changed.
Practical Notes
DELETE
only when quantity == 0
, PUT
only when a change is needed, POST
only for batch creation.quantity
), and wire it up.Switch
, Delay
, and retry counters from Scenario C, you can handle errors gracefully: retry a few times, then alert.Use these examples as templates. Swap in your own endpoints, adjust headers, and let Divooka do the heavy lifting of inserting the correct blank lines, computing Content-Length
, and routing success vs. failure paths. When you need to debug, step into the program flow and see intermediate results or use low level nodes and paste in the exact HTTP text to watch how headers and bodies fly over the wire.
Method | Safe | Idempotent | Success Codes | Typical Use |
---|---|---|---|---|
GET | ✔ | ✔ | 200, 304 | Read data |
HEAD | ✔ | ✔ | 200 | Read headers |
POST | ✘ | ✘ | 201, 200 | Create / action |
PUT | ✘ | ✔ | 200, 204 | Replace resource |
PATCH | ✘ | ✔ | 200, 204 | Partial update |
DELETE | ✘ | ✔ | 204, 200 | Remove resource |
OPTIONS | ✔ | ✔ | 200 | Discover / CORS |
Content-Length
, but knowing what’s underneath turns you from user into wizard.Idempotency-Key
header on a POST, then hit “Run” five times. Note what your server does.