POST, PUT, PATCH & DELETE
Create, update, and delete resources using POST, PUT, PATCH, and DELETE methods with proper request bodies and validation.
CRUD Operations with REST APIs
After mastering GET requests, it's time to learn the full CRUD cycle: Create (POST), Read (GET), Update (PUT/PATCH), and Delete (DELETE). These are the building blocks of every REST API.
POST — Creating Resources
POST sends data to the server to create a new resource. The request body contains the data in JSON format, and the server typically responds with a 201 status code and the created resource (including a generated ID).
PUT vs PATCH
PUT replaces the entire resource — you send the complete object. PATCH updates only the specified fields — you send just what changed. In practice, PUT is used when you have the full object, PATCH when you want to modify a single field.
DELETE — Removing Resources
DELETE removes a resource from the server. A successful deletion typically returns 200 (with body) or 204 (no content). Always verify the resource is actually gone with a follow-up GET.
// POST — Create a new resource
const createResponse = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: 'API Testing with Fetch',
body: 'Learning to test APIs using the Fetch API',
userId: 1
})
});
const created = await createResponse.json();
console.assert(createResponse.status === 201, 'Should return 201 Created');
console.assert(created.title === 'API Testing with Fetch');
console.assert(created.id !== undefined, 'Should have generated ID');
console.log('Created post ID:', created.id);
// PUT — Replace entire resource
const putResponse = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 1,
title: 'Updated Title',
body: 'Completely replaced body content',
userId: 1
})
});
const updated = await putResponse.json();
console.assert(putResponse.status === 200);
console.assert(updated.title === 'Updated Title');
// PATCH — Partial update
const patchResponse = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'Patched Title Only' })
});
const patched = await patchResponse.json();
console.assert(patchResponse.status === 200);
console.assert(patched.title === 'Patched Title Only');
// DELETE — Remove resource
const deleteResponse = await fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE'
});
console.assert(deleteResponse.status === 200, 'Should return 200');
console.log('All CRUD operations passed!');
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import org.testng.annotations.Test;
public class CrudOperationsTest {
private static final String BASE_URI = "https://jsonplaceholder.typicode.com";
@Test
public void testPost_CreateResource() {
String requestBody = "{"
+ "\"title\": \"API Testing with RestAssured\","
+ "\"body\": \"Learning to test APIs using RestAssured\","
+ "\"userId\": 1"
+ "}";
given()
.baseUri(BASE_URI)
.contentType("application/json")
.body(requestBody)
.when()
.post("/posts")
.then()
.statusCode(201)
.body("title", equalTo("API Testing with RestAssured"))
.body("id", notNullValue());
}
@Test
public void testPut_ReplaceResource() {
String requestBody = "{"
+ "\"id\": 1,"
+ "\"title\": \"Updated Title\","
+ "\"body\": \"Completely replaced body content\","
+ "\"userId\": 1"
+ "}";
given()
.baseUri(BASE_URI)
.contentType("application/json")
.body(requestBody)
.when()
.put("/posts/1")
.then()
.statusCode(200)
.body("title", equalTo("Updated Title"));
}
@Test
public void testPatch_PartialUpdate() {
given()
.baseUri(BASE_URI)
.contentType("application/json")
.body("{ \"title\": \"Patched Title Only\" }")
.when()
.patch("/posts/1")
.then()
.statusCode(200)
.body("title", equalTo("Patched Title Only"));
}
@Test
public void testDelete_RemoveResource() {
given()
.baseUri(BASE_URI)
.when()
.delete("/posts/1")
.then()
.statusCode(200);
}
}
import requests
BASE_URL = 'https://jsonplaceholder.typicode.com'
def test_post_create_resource():
"""POST — Create a new resource"""
payload = {
'title': 'API Testing with Requests',
'body': 'Learning to test APIs using Python Requests',
'userId': 1
}
response = requests.post(f'{BASE_URL}/posts', json=payload)
assert response.status_code == 201, 'Should return 201 Created'
data = response.json()
assert data['title'] == payload['title']
assert 'id' in data, 'Should have generated ID'
print(f"Created post ID: {data['id']}")
def test_put_replace_resource():
"""PUT — Replace entire resource"""
payload = {
'id': 1,
'title': 'Updated Title',
'body': 'Completely replaced body content',
'userId': 1
}
response = requests.put(f'{BASE_URL}/posts/1', json=payload)
assert response.status_code == 200
assert response.json()['title'] == 'Updated Title'
def test_patch_partial_update():
"""PATCH — Partial update"""
response = requests.patch(
f'{BASE_URL}/posts/1',
json={'title': 'Patched Title Only'}
)
assert response.status_code == 200
assert response.json()['title'] == 'Patched Title Only'
def test_delete_remove_resource():
"""DELETE — Remove resource"""
response = requests.delete(f'{BASE_URL}/posts/1')
assert response.status_code == 200
Written by PV
© 2026 All Rights Reserved