Beginner Chapter 4 · 12 min read

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.

crud-operations.test.js
// 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!');
CrudOperationsTest.java
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);
    }
}
test_crud_operations.py
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

API Testing Beginner POST, PUT, PATCH & DELETE

Written by PV

© 2026 All Rights Reserved