HTTP Methods Explained: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

HTTP Methods Explained: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

HTTP methods are the verbs of an API: they tell the server what you want to do with a resource. Mix them up and you get bugs like a “GET” that deletes data or a retry that charges a customer twice. In this lesson you will learn all seven methods testers use, the difference between PUT and PATCH, what “safe” and “idempotent” really mean, and you will run each method on a live object you create yourself.

Quick answerGET reads data, POST creates a new resource, PUT replaces a resource completely (or creates it at a known URL), PATCH updates only some fields, DELETE removes a resource, HEAD returns only the headers of a GET, and OPTIONS lists the methods an endpoint allows. GET, HEAD and OPTIONS are safe (no changes); GET, HEAD, OPTIONS, PUT and DELETE are idempotent (repeating them gives the same result); POST and PATCH are not idempotent.
Advertisement

Real-Life Example: Managing Your Address Book in a Shopping App

Every method in one screen Opening “My addresses” sends GET /addresses. Adding a new office address sends POST /addresses. Editing the whole address form and saving sends PUT /addresses/7. Only marking it as “default” sends PATCH /addresses/7 with {"is_default": true}. Removing it sends DELETE /addresses/7.

This mapping of methods to actions is called CRUD: Create (POST), Read (GET), Update (PUT/PATCH) and Delete (DELETE).

All HTTP Methods at a Glance

MethodPurposeHas body?SafeIdempotentTypical success code
GETRead a resource or listNoYesYes200 OK
POSTCreate a new resource / trigger an actionYesNoNo201 Created (or 200/202)
PUTReplace the whole resource, or create at a known idYesNoYes200 OK / 201 Created / 204
PATCHPartial updateYesNoNot guaranteed200 OK / 204
DELETERemove a resourceUsually noNoYes204 No Content / 200
HEADSame as GET but headers onlyNoYesYes200 OK
OPTIONSWhich methods are allowed (also CORS pre-flight)NoYesYes200 / 204

Two rarer methods: TRACE (echoes the request, should be disabled in production for security) and CONNECT (used by proxies for HTTPS tunnels).

Advertisement

GET: Read Data

GET retrieves data and must never change anything on the server. Parameters go in the URL path or query string.

GEThttps://sqatools.in/wp-json/sqa-api/v1/users?role=admin&sort=age&order=desc
curl -i \
  "https://sqatools.in/wp-json/sqa-api/v1/users?role=admin&sort=age&order=desc"

Test ideas: correct data and count; filters and sorting; 404 for a missing id; 400 for an invalid id (/users/abc); calling it twice changes nothing; sensitive data not exposed; response time.

Real bug pattern A GET link like /unsubscribe?user=42 or /orders/9/cancel that changes data is dangerous: browsers prefetch links, crawlers follow them and caches replay them. Testers should flag any GET that modifies state.

POST: Create a New Resource

POST sends data in the body; the server decides the new id. A correct create returns 201 Created and a Location header.

POSThttps://sqatools.in/wp-json/sqa-api/v1/objects
curl -i \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"name":"Office address","data":{"city":"Pune","pin":"411001"},"ttl":300}' \
  "https://sqatools.in/wp-json/sqa-api/v1/objects"

Test ideas: 201 + Location; body echoes what you sent; required fields missing → 422; extra unknown fields; client trying to set the id (the practice API rejects it with 422); duplicate submission.

Why POST is not idempotent Press “Pay” twice on a slow network and two POST /payments requests may arrive, charging the customer twice. Payment APIs (Razorpay, Stripe) solve it with an Idempotency-Key header: the same key returns the first result instead of creating a second payment. Testing duplicate POSTs is a must for any money-related API.
Advertisement

PUT: Replace (or Create at a Known URL)

PUT sends the complete new version of a resource to its URL. Any field you leave out is removed or reset. If the resource does not exist, many APIs create it (called an upsert).

On the practice API you choose the id. The first PUT returns 201 Created; repeating the same PUT returns 200 OK with the same content, which is what idempotent means.

PUThttps://sqatools.in/wp-json/sqa-api/v1/objects/my-address-01
curl -i \
  -X PUT \
  -H "Content-Type: application/json" \
  -d '{"name":"Home address","data":{"city":"Mumbai","pin":"400001"},"ttl":300}' \
  "https://sqatools.in/wp-json/sqa-api/v1/objects/my-address-01"

Test ideas: full replacement (omitted fields disappear); name missing → 422 (PUT needs the full representation); id in body different from id in URL → 422; repeat the call → same state; version increments.

Advertisement

PATCH: Update Only Some Fields

PATCH sends only the fields that change. The practice API uses JSON Merge Patch rules: fields you send are merged in, and a field set to null is removed.

curl -i -X PATCH "https://sqatools.in/wp-json/sqa-api/v1/objects/my-address-01" \
  -H "Content-Type: application/json" \
  -d '{"data":{"pin":"400002"}}'

Result: city stays “Mumbai”, pin becomes “400002”, version goes up by 1, and the ETag changes from "v1" to "v2".

Test ideas: only sent fields change; null removes a key; empty body {} → 422 “nothing to update”; PATCH on a missing id → 404; read-only fields (id, created_at) cannot be patched.

Advertisement

PUT vs PATCH: The Most Asked Interview Question

PUTPATCH
SendsThe entire resourceOnly the changes
Missing fieldsRemoved or set to defaultLeft unchanged
IdempotentYes, alwaysNot guaranteed (e.g. {"op":"increment"})
Can createYes, at a client-chosen URLUsually no (404 if missing)
Real exampleSaving the whole edit-profile formToggling “dark mode” or “default address”

Example: the stored object is {"name":"Home","data":{"city":"Mumbai","pin":"400001"}}.

  • PUT {"name":"Home","data":{"pin":"400002"}} → city is gone.
  • PATCH {"data":{"pin":"400002"}} → city is kept.

DELETE: Remove a Resource

DELETE removes the resource. The common success code is 204 No Content (empty body).

DELETEhttps://sqatools.in/wp-json/sqa-api/v1/objects/my-address-01
curl -i \
  -X DELETE \
  "https://sqatools.in/wp-json/sqa-api/v1/objects/my-address-01"

Press Send twice. The first call returns 204, the second 404. Is that still idempotent? Yes: idempotency is about the server state (the object is gone either way), not about the status code.

Test ideas: 204 then GET returns 404; deleting twice; deleting without permission → 403; deleting a resource that has children (an order with payments); soft delete vs hard delete; DELETE on read-only resources → 405 (try DELETE /products/101).

Advertisement

HEAD and OPTIONS: The Methods Testers Forget

HEAD

Returns exactly the headers a GET would return, but no body. Used to check if a resource exists, its size (Content-Length) or its version (ETag) without downloading it, for example before downloading a 2 GB file.

HEADhttps://sqatools.in/wp-json/sqa-api/v1/users/1
curl -I \
  "https://sqatools.in/wp-json/sqa-api/v1/users/1"

OPTIONS

Asks which methods are allowed. The answer comes in the Allow header. Browsers also send OPTIONS automatically as a CORS pre-flight before cross-origin PUT/DELETE requests.

OPTIONShttps://sqatools.in/wp-json/sqa-api/v1/users
curl -i \
  -X OPTIONS \
  "https://sqatools.in/wp-json/sqa-api/v1/users"

405 Method Not Allowed

When you use a method an endpoint does not support, the correct answer is 405 with an Allow header listing valid methods. On the practice API, POST /users returns: “This endpoint supports GET, HEAD only.” A 404 or 500 here would be a bug.

Advertisement

Safe vs Idempotent, Explained Simply

  • Safe = read-only. Calling it does not change data. (GET, HEAD, OPTIONS)
  • Idempotent = calling it once or 10 times leaves the server in the same state. (All safe methods + PUT + DELETE)
Lift button analogy Pressing the lift call button 5 times still calls the lift once: idempotent. Ordering “one coffee” 5 times gets you 5 coffees: not idempotent (that’s POST).

Why testers care: networks fail, and clients and gateways retry. Retrying idempotent requests is safe; retrying POST without an idempotency key can create duplicates.

All Methods in One Playwright Test

import { test, expect } from '@playwright/test';

const BASE = 'https://sqatools.in/wp-json/sqa-api/v1';

test('HTTP methods on one object', async ({ request }) => {
  const id = `pw-${Date.now()}`;
  const url = `${BASE}/objects/${id}`;

  // PUT creates (201), PUT again is idempotent (200, same data)
  const body = { name: 'Home', data: { city: 'Mumbai', pin: '400001' }, ttl: 120 };
  expect((await request.put(url, { data: body })).status()).toBe(201);
  expect((await request.put(url, { data: body })).status()).toBe(200);

  // PATCH changes one field and keeps the rest
  const patched = await (await request.patch(url, { data: { data: { pin: '400002' } } })).json();
  expect(patched.data).toEqual({ city: 'Mumbai', pin: '400002' });

  // HEAD: headers only, no body
  const head = await request.head(url);
  expect(head.status()).toBe(200);
  expect((await head.body()).length).toBe(0);

  // DELETE twice: 204 then 404 (state is the same: gone)
  expect((await request.delete(url)).status()).toBe(204);
  expect((await request.delete(url)).status()).toBe(404);
});

test('unsupported method returns 405 with Allow header', async ({ request }) => {
  const res = await request.post(`${BASE}/users`, { data: {} });
  expect(res.status()).toBe(405);
  expect(res.headers()['allow']).toBeTruthy();
});
Advertisement

Interview Questions: HTTP Methods

What is the difference between PUT and PATCH?

PUT replaces the entire resource with the representation you send, so omitted fields are removed, and it is idempotent. PATCH applies a partial update, changing only the fields you send, and is not guaranteed to be idempotent.

What is the difference between GET and POST?

GET reads data, sends parameters in the URL, is safe, idempotent and cacheable. POST sends data in the body to create a resource or trigger processing, changes server state and is not idempotent. Sensitive data should never go in GET query strings because URLs are logged.

What does idempotent mean? Which methods are idempotent?

An idempotent request leaves the server in the same state whether it is sent once or many times. GET, HEAD, OPTIONS, PUT and DELETE are idempotent; POST is not and PATCH is not guaranteed to be.

DELETE returns 204 the first time and 404 the second. Is it still idempotent?

Yes. Idempotency refers to the server state, not the response code. After either call the resource does not exist.

What is the difference between PUT and POST?

POST creates a resource at a URL chosen by the server and is not idempotent. PUT creates or replaces a resource at a URL chosen by the client and is idempotent.

What is the use of the HEAD method?

HEAD returns the same headers as GET without the body. It is used to check existence, size, content type or ETag of a resource without downloading it.

What is the use of the OPTIONS method?

OPTIONS returns the allowed methods for a resource in the Allow header and is used by browsers as a CORS pre-flight request before cross-origin calls.

What status code should an API return for an unsupported method?

405 Method Not Allowed, with an Allow header listing the supported methods.

Can a GET request have a body?

The HTTP specification does not define meaning for a GET body, and many servers, proxies and tools ignore or reject it. APIs should use query parameters for GET; if you see an API requiring a GET body, flag it as a design risk.

How do you prevent duplicate orders when a POST is retried?

Use an Idempotency-Key header generated by the client for each logical operation; the server stores the first result for that key and returns it for retries. Testers verify that sending the same key twice creates only one order.

Advertisement
View the full API testing syllabus