Intermediate
Chapter 13 · 11 min read
API Chaining & Workflows
Chain multiple API calls together — create a resource, read it, update it, then delete it. Pass data between requests and test end-to-end flows.
Chaining API Calls
Real API testing rarely involves single isolated requests. Business workflows require chaining: create a user, then create their profile, then assign them to a team. Each step depends on data from the previous one.
Common Patterns
- CRUD chain — Create → Read → Update → Delete a single resource
- Data dependency — Use the ID from a POST response in subsequent GET/PUT/DELETE calls
- Setup/teardown — Create test data via API before tests, clean up after
- Business flow — Register → Login → Perform action → Verify state
api-chaining.test.js
const BASE = 'https://jsonplaceholder.typicode.com';
const headers = { 'Content-Type': 'application/json' };
// Full CRUD workflow chain
console.log('--- CRUD Workflow ---');
// 1. CREATE
const createResp = await fetch(`${BASE}/posts`, {
method: 'POST', headers,
body: JSON.stringify({
title: 'Chained Post',
body: 'Created in workflow',
userId: 1
})
});
const created = await createResp.json();
console.assert(createResp.status === 201);
const postId = created.id;
console.log(`1. Created post ID: ${postId}`);
// 2. READ — verify it exists
const readResp = await fetch(`${BASE}/posts/${postId}`);
const read = await readResp.json();
console.log(`2. Read post: "${read.title}"`);
// 3. UPDATE — modify the post
const updateResp = await fetch(`${BASE}/posts/${postId}`, {
method: 'PUT', headers,
body: JSON.stringify({
id: postId,
title: 'Updated Chained Post',
body: 'Modified in workflow',
userId: 1
})
});
const updated = await updateResp.json();
console.assert(updated.title === 'Updated Chained Post');
console.log(`3. Updated to: "${updated.title}"`);
// 4. DELETE — remove the post
const deleteResp = await fetch(`${BASE}/posts/${postId}`, {
method: 'DELETE'
});
console.assert(deleteResp.status === 200);
console.log(`4. Deleted post ${postId}`);
// Multi-resource workflow: User -> Posts -> Comments
console.log('\n--- Multi-Resource Workflow ---');
const userResp = await fetch(`${BASE}/users/1`);
const user = await userResp.json();
console.log(`User: ${user.name}`);
const userPosts = await fetch(`${BASE}/posts?userId=${user.id}`);
const posts = await userPosts.json();
console.log(`Posts by ${user.name}: ${posts.length}`);
const firstPostComments = await fetch(`${BASE}/posts/${posts[0].id}/comments`);
const comments = await firstPostComments.json();
console.log(`Comments on first post: ${comments.length}`);
console.log('All chaining tests passed!');
ApiChainingTest.java
import static io.restassured.RestAssured.*;
import io.restassured.response.Response;
import org.testng.annotations.Test;
import org.testng.Assert;
import java.util.List;
public class ApiChainingTest {
private static final String BASE = "https://jsonplaceholder.typicode.com";
@Test
public void testCrudWorkflow() {
// 1. CREATE
Response createResp = given().baseUri(BASE)
.contentType("application/json")
.body("{\"title\": \"Chained Post\", \"body\": \"Created\", \"userId\": 1}")
.when().post("/posts")
.then().statusCode(201).extract().response();
int postId = createResp.jsonPath().getInt("id");
System.out.println("1. Created post ID: " + postId);
// 2. READ
String title = given().baseUri(BASE)
.when().get("/posts/" + postId)
.then().statusCode(200)
.extract().jsonPath().getString("title");
System.out.println("2. Read: " + title);
// 3. UPDATE
given().baseUri(BASE)
.contentType("application/json")
.body("{\"id\": " + postId + ", \"title\": \"Updated\", \"body\": \"Modified\", \"userId\": 1}")
.when().put("/posts/" + postId)
.then().statusCode(200)
.body("title", org.hamcrest.Matchers.equalTo("Updated"));
System.out.println("3. Updated");
// 4. DELETE
given().baseUri(BASE)
.when().delete("/posts/" + postId)
.then().statusCode(200);
System.out.println("4. Deleted");
}
@Test
public void testMultiResourceWorkflow() {
// Get user
Response userResp = given().baseUri(BASE)
.when().get("/users/1")
.then().statusCode(200).extract().response();
String userName = userResp.jsonPath().getString("name");
// Get user's posts
List<Integer> postIds = given().baseUri(BASE)
.queryParam("userId", 1)
.when().get("/posts")
.then().statusCode(200)
.extract().jsonPath().getList("id");
System.out.println(userName + " has " + postIds.size() + " posts");
// Get comments on first post
int commentCount = given().baseUri(BASE)
.when().get("/posts/" + postIds.get(0) + "/comments")
.then().statusCode(200)
.extract().jsonPath().getList("$").size();
System.out.println("First post has " + commentCount + " comments");
}
}
test_api_chaining.py
import requests
BASE_URL = 'https://jsonplaceholder.typicode.com'
def test_crud_workflow():
"""Full CRUD chain: Create -> Read -> Update -> Delete"""
# 1. CREATE
create_resp = requests.post(
f'{BASE_URL}/posts',
json={'title': 'Chained Post', 'body': 'Created', 'userId': 1}
)
assert create_resp.status_code == 201
post_id = create_resp.json()['id']
print(f"1. Created post ID: {post_id}")
# 2. READ
read_resp = requests.get(f'{BASE_URL}/posts/{post_id}')
assert read_resp.status_code == 200
print(f"2. Read: {read_resp.json().get('title', 'N/A')}")
# 3. UPDATE
update_resp = requests.put(
f'{BASE_URL}/posts/{post_id}',
json={'id': post_id, 'title': 'Updated', 'body': 'Modified', 'userId': 1}
)
assert update_resp.status_code == 200
assert update_resp.json()['title'] == 'Updated'
print("3. Updated")
# 4. DELETE
delete_resp = requests.delete(f'{BASE_URL}/posts/{post_id}')
assert delete_resp.status_code == 200
print(f"4. Deleted post {post_id}")
def test_multi_resource_workflow():
"""Chain across multiple resource types"""
# Get user
user = requests.get(f'{BASE_URL}/users/1').json()
print(f"User: {user['name']}")
# Get user's posts
posts = requests.get(f'{BASE_URL}/posts', params={'userId': user['id']}).json()
print(f"Posts by {user['name']}: {len(posts)}")
# Get comments on first post
comments = requests.get(f'{BASE_URL}/posts/{posts[0]["id"]}/comments').json()
print(f"Comments on first post: {len(comments)}")
assert len(posts) > 0
assert len(comments) > 0
API Testing
Intermediate
API Chaining & Workflows
Written by PV
© 2026 All Rights Reserved