API Test Suite Builder
alirezarezvani/claude-skills
A skill your agent uses when the user asks to generate API tests, create integration test suites, test REST endpoints, or build contract tests.
Comprehensive RESTful API testing patterns covering HTTP methods, status codes, request/response validation, authentication, error handling, and contract testing.
$ npx skills add PramodDutta/qaskills --skill api-testing-rest -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install PramodDutta/qaskills api-testing-rest --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/PramodDutta/qaskills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packs/qa-essentials/skills/api-testing-rest .claude/skills/api-testing-rest && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "api-testing-rest" agent skill from https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-rest into .claude/skills/api-testing-rest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-testing-rest", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-restType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add PramodDutta/qaskills --skill api-testing-rest -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install PramodDutta/qaskills api-testing-rest --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PramodDutta/qaskills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/packs/qa-essentials/skills/api-testing-rest .agents/skills/api-testing-rest && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "api-testing-rest" agent skill from https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-rest into .agents/skills/api-testing-rest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-testing-rest", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add PramodDutta/qaskills --skill api-testing-rest -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install PramodDutta/qaskills api-testing-rest --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PramodDutta/qaskills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/packs/qa-essentials/skills/api-testing-rest .cursor/skills/api-testing-rest && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "api-testing-rest" agent skill from https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-rest into .cursor/skills/api-testing-rest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-testing-rest", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/PramodDutta/qaskills.git --path packs/qa-essentials/skills/api-testing-rest--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add PramodDutta/qaskills --skill api-testing-rest -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install PramodDutta/qaskills api-testing-rest --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PramodDutta/qaskills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/packs/qa-essentials/skills/api-testing-rest .gemini/skills/api-testing-rest && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "api-testing-rest" agent skill from https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-rest into .gemini/skills/api-testing-rest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-testing-rest", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install PramodDutta/qaskills api-testing-restInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add PramodDutta/qaskills --skill api-testing-rest -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/PramodDutta/qaskills.git skills-src && mkdir -p .github/skills && cp -r skills-src/packs/qa-essentials/skills/api-testing-rest .github/skills/api-testing-rest && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "api-testing-rest" agent skill from https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-rest into .github/skills/api-testing-rest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-testing-rest", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add PramodDutta/qaskills --skill api-testing-rest -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install PramodDutta/qaskills api-testing-rest --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PramodDutta/qaskills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/packs/qa-essentials/skills/api-testing-rest .opencode/skills/api-testing-rest && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "api-testing-rest" agent skill from https://github.com/PramodDutta/qaskills/tree/main/packs/qa-essentials/skills/api-testing-rest into .opencode/skills/api-testing-rest/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "api-testing-rest", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
api-testing-restComprehensive RESTful API testing patterns covering HTTP methods, status codes, request/response validation, authentication, error handling, and contract testing.
API Testing REST is an agent skill from PramodDutta/qaskills. Comprehensive RESTful API testing patterns covering HTTP methods, status codes, request/response validation, authentication, error handling, and contract testing.
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering API testing, REST APIs and Integration testing. The repository describes itself as: QA Skills Directory QA Skills is a curated directory of testing-specific skills for AI coding agents (Claude Code, Cursor, Copilot, etc.). The licence is MIT.
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 1d2a092. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript, python and java).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
API Testing REST loads about 4.9k tokens when it runs. Until then it costs about 45 tokens; SKILL.md has 334 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from PramodDutta/qaskills at commit 1d2a092, republished under its MIT licence (© PramodDutta). 334 words, ~4,915 tokens.
.claude/skills/api-testing-rest/SKILL.md (or your agent's skills folder).You are an expert QA engineer specializing in REST API testing. When the user asks you to write, review, or design API tests, follow these detailed instructions.
GET - Retrieve resource(s), safe and idempotent
POST - Create new resource, not idempotent
PUT - Replace entire resource, idempotent
PATCH - Partial update, idempotent
DELETE - Remove resource, idempotent
HEAD - Same as GET but no response body
OPTIONS - Get supported methods for resourceSuccess (2xx):
200 OK - Successful GET, PUT, PATCH, DELETE
201 Created - Successful POST, resource created
204 No Content - Successful DELETE (no body returned)
Client Error (4xx):
400 Bad Request - Invalid request body or parameters
401 Unauthorized - Missing or invalid authentication
403 Forbidden - Authenticated but not authorized
404 Not Found - Resource doesn't exist
409 Conflict - Resource conflict (duplicate email)
422 Unprocessable - Validation error
Server Error (5xx):
500 Internal Error - Server error
503 Service Unavailable - Service down or overloaded// api-client.ts
import axios from 'axios';
export class ApiClient {
private baseURL = 'https://api.example.com';
private authToken: string | null = null;
setAuthToken(token: string) {
this.authToken = token;
}
private getHeaders() {
return {
'Content-Type': 'application/json',
...(this.authToken && { Authorization: `Bearer ${this.authToken}` }),
};
}
async get(endpoint: string, params = {}) {
const response = await axios.get(`${this.baseURL}${endpoint}`, {
headers: this.getHeaders(),
params,
});
return response;
}
async post(endpoint: string, data: any) {
const response = await axios.post(`${this.baseURL}${endpoint}`, data, {
headers: this.getHeaders(),
});
return response;
}
async put(endpoint: string, data: any) {
const response = await axios.put(`${this.baseURL}${endpoint}`, data, {
headers: this.getHeaders(),
});
return response;
}
async delete(endpoint: string) {
const response = await axios.delete(`${this.baseURL}${endpoint}`, {
headers: this.getHeaders(),
});
return response;
}
}// users.api.test.ts
import { describe, it, expect, beforeAll } from 'vitest';
import { ApiClient } from './api-client';
describe('Users API', () => {
const api = new ApiClient();
let createdUserId: string;
beforeAll(async () => {
// Authenticate before running tests
const authResponse = await api.post('/auth/login', {
email: 'test@example.com',
password: 'password123',
});
api.setAuthToken(authResponse.data.token);
});
describe('POST /api/users', () => {
it('should create a new user', async () => {
const userData = {
email: 'newuser@example.com',
name: 'New User',
role: 'user',
};
const response = await api.post('/api/users', userData);
// Assert status code
expect(response.status).toBe(201);
// Assert response structure
expect(response.data).toHaveProperty('id');
expect(response.data).toHaveProperty('email', userData.email);
expect(response.data).toHaveProperty('name', userData.name);
expect(response.data).toHaveProperty('createdAt');
// Assert response types
expect(typeof response.data.id).toBe('string');
expect(response.data.createdAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
// Save for cleanup
createdUserId = response.data.id;
});
it('should return 400 for invalid email', async () => {
try {
await api.post('/api/users', {
email: 'invalid-email',
name: 'Test',
});
fail('Should have thrown an error');
} catch (error: any) {
expect(error.response.status).toBe(400);
expect(error.response.data).toHaveProperty('error');
expect(error.response.data.error).toContain('email');
}
});
it('should return 409 for duplicate email', async () => {
const userData = {
email: 'duplicate@example.com',
name: 'Duplicate User',
};
// Create first user
await api.post('/api/users', userData);
// Attempt to create duplicate
try {
await api.post('/api/users', userData);
fail('Should have thrown an error');
} catch (error: any) {
expect(error.response.status).toBe(409);
expect(error.response.data.error).toContain('already exists');
}
});
});
describe('GET /api/users/:id', () => {
it('should retrieve user by ID', async () => {
const response = await api.get(`/api/users/${createdUserId}`);
expect(response.status).toBe(200);
expect(response.data.id).toBe(createdUserId);
expect(response.data).toHaveProperty('email');
expect(response.data).toHaveProperty('name');
});
it('should return 404 for non-existent user', async () => {
try {
await api.get('/api/users/non-existent-id');
fail('Should have thrown an error');
} catch (error: any) {
expect(error.response.status).toBe(404);
}
});
});
describe('GET /api/users', () => {
it('should list all users', async () => {
const response = await api.get('/api/users');
expect(response.status).toBe(200);
expect(Array.isArray(response.data)).toBe(true);
expect(response.data.length).toBeGreaterThan(0);
// Validate structure of first user
const firstUser = response.data[0];
expect(firstUser).toHaveProperty('id');
expect(firstUser).toHaveProperty('email');
expect(firstUser).toHaveProperty('name');
});
it('should support pagination', async () => {
const response = await api.get('/api/users', {
page: 1,
limit: 10,
});
expect(response.status).toBe(200);
expect(response.data).toHaveProperty('items');
expect(response.data).toHaveProperty('total');
expect(response.data).toHaveProperty('page', 1);
expect(response.data).toHaveProperty('limit', 10);
expect(response.data.items.length).toBeLessThanOrEqual(10);
});
it('should support filtering', async () => {
const response = await api.get('/api/users', {
role: 'admin',
});
expect(response.status).toBe(200);
expect(Array.isArray(response.data)).toBe(true);
// All users should be admins
response.data.forEach((user: any) => {
expect(user.role).toBe('admin');
});
});
});
describe('PUT /api/users/:id', () => {
it('should update user completely', async () => {
const updatedData = {
email: 'updated@example.com',
name: 'Updated Name',
role: 'admin',
};
const response = await api.put(`/api/users/${createdUserId}`, updatedData);
expect(response.status).toBe(200);
expect(response.data.email).toBe(updatedData.email);
expect(response.data.name).toBe(updatedData.name);
expect(response.data.role).toBe(updatedData.role);
});
it('should return 404 for non-existent user', async () => {
try {
await api.put('/api/users/non-existent', { name: 'Test' });
fail('Should have thrown an error');
} catch (error: any) {
expect(error.response.status).toBe(404);
}
});
});
describe('DELETE /api/users/:id', () => {
it('should delete user', async () => {
const response = await api.delete(`/api/users/${createdUserId}`);
expect(response.status).toBe(204);
// Verify deletion
try {
await api.get(`/api/users/${createdUserId}`);
fail('User should be deleted');
} catch (error: any) {
expect(error.response.status).toBe(404);
}
});
it('should return 404 when deleting non-existent user', async () => {
try {
await api.delete('/api/users/non-existent');
fail('Should have thrown an error');
} catch (error: any) {
expect(error.response.status).toBe(404);
}
});
});
});# api_client.py
import requests
from typing import Dict, Any, Optional
class ApiClient:
def __init__(self, base_url: str):
self.base_url = base_url
self.session = requests.Session()
self.auth_token: Optional[str] = None
def set_auth_token(self, token: str):
"""Set authentication token for all requests."""
self.auth_token = token
self.session.headers.update({'Authorization': f'Bearer {token}'})
def get(self, endpoint: str, params: Optional[Dict] = None) -> requests.Response:
"""Perform GET request."""
url = f"{self.base_url}{endpoint}"
return self.session.get(url, params=params)
def post(self, endpoint: str, data: Dict[str, Any]) -> requests.Response:
"""Perform POST request."""
url = f"{self.base_url}{endpoint}"
return self.session.post(url, json=data)
def put(self, endpoint: str, data: Dict[str, Any]) -> requests.Response:
"""Perform PUT request."""
url = f"{self.base_url}{endpoint}"
return self.session.put(url, json=data)
def delete(self, endpoint: str) -> requests.Response:
"""Perform DELETE request."""
url = f"{self.base_url}{endpoint}"
return self.session.delete(url)# test_users_api.py
import pytest
from api_client import ApiClient
@pytest.fixture(scope="module")
def api_client():
"""Create API client and authenticate."""
client = ApiClient("https://api.example.com")
# Authenticate
response = client.post("/auth/login", {
"email": "test@example.com",
"password": "password123"
})
assert response.status_code == 200
client.set_auth_token(response.json()["token"])
return client
@pytest.fixture
def created_user(api_client):
"""Create a test user and clean up after test."""
response = api_client.post("/api/users", {
"email": "testuser@example.com",
"name": "Test User",
})
user_id = response.json()["id"]
yield user_id
# Cleanup
api_client.delete(f"/api/users/{user_id}")
class TestUsersAPI:
"""Test suite for Users API."""
def test_create_user_success(self, api_client):
"""Should create a new user with valid data."""
# Arrange
user_data = {
"email": "newuser@example.com",
"name": "New User",
"role": "user",
}
# Act
response = api_client.post("/api/users", user_data)
# Assert
assert response.status_code == 201
data = response.json()
assert "id" in data
assert data["email"] == user_data["email"]
assert data["name"] == user_data["name"]
assert "createdAt" in data
# Cleanup
api_client.delete(f"/api/users/{data['id']}")
def test_create_user_invalid_email(self, api_client):
"""Should return 400 for invalid email."""
response = api_client.post("/api/users", {
"email": "invalid-email",
"name": "Test User",
})
assert response.status_code == 400
assert "error" in response.json()
def test_get_user_by_id(self, api_client, created_user):
"""Should retrieve user by ID."""
response = api_client.get(f"/api/users/{created_user}")
assert response.status_code == 200
data = response.json()
assert data["id"] == created_user
assert "email" in data
assert "name" in data
def test_get_user_not_found(self, api_client):
"""Should return 404 for non-existent user."""
response = api_client.get("/api/users/non-existent-id")
assert response.status_code == 404
def test_list_users(self, api_client):
"""Should list all users."""
response = api_client.get("/api/users")
assert response.status_code == 200
data = response.json()
assert isinstance(data, list)
assert len(data) > 0
assert "id" in data[0]
assert "email" in data[0]
def test_update_user(self, api_client, created_user):
"""Should update user data."""
updated_data = {
"email": "updated@example.com",
"name": "Updated Name",
}
response = api_client.put(f"/api/users/{created_user}", updated_data)
assert response.status_code == 200
data = response.json()
assert data["email"] == updated_data["email"]
assert data["name"] == updated_data["name"]
def test_delete_user(self, api_client, created_user):
"""Should delete user."""
response = api_client.delete(f"/api/users/{created_user}")
assert response.status_code == 204
# Verify deletion
get_response = api_client.get(f"/api/users/{created_user}")
assert get_response.status_code == 404// UserApiTest.java
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.*;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserApiTest {
private static String authToken;
private static String createdUserId;
@BeforeAll
public static void setup() {
RestAssured.baseURI = "https://api.example.com";
// Authenticate
Response authResponse = given()
.contentType("application/json")
.body("{ \"email\": \"test@example.com\", \"password\": \"password123\" }")
.when()
.post("/auth/login")
.then()
.statusCode(200)
.extract().response();
authToken = authResponse.jsonPath().getString("token");
}
@Test
@Order(1)
public void testCreateUser() {
String requestBody = """
{
"email": "newuser@example.com",
"name": "New User",
"role": "user"
}
""";
Response response = given()
.header("Authorization", "Bearer " + authToken)
.contentType("application/json")
.body(requestBody)
.when()
.post("/api/users")
.then()
.statusCode(201)
.body("id", notNullValue())
.body("email", equalTo("newuser@example.com"))
.body("name", equalTo("New User"))
.body("createdAt", matchesPattern("\\d{4}-\\d{2}-\\d{2}T.*"))
.extract().response();
createdUserId = response.jsonPath().getString("id");
}
@Test
@Order(2)
public void testGetUser() {
given()
.header("Authorization", "Bearer " + authToken)
.when()
.get("/api/users/" + createdUserId)
.then()
.statusCode(200)
.body("id", equalTo(createdUserId))
.body("email", notNullValue())
.body("name", notNullValue());
}
@Test
@Order(3)
public void testUpdateUser() {
String updateBody = """
{
"email": "updated@example.com",
"name": "Updated Name"
}
""";
given()
.header("Authorization", "Bearer " + authToken)
.contentType("application/json")
.body(updateBody)
.when()
.put("/api/users/" + createdUserId)
.then()
.statusCode(200)
.body("email", equalTo("updated@example.com"))
.body("name", equalTo("Updated Name"));
}
@Test
@Order(4)
public void testDeleteUser() {
given()
.header("Authorization", "Bearer " + authToken)
.when()
.delete("/api/users/" + createdUserId)
.then()
.statusCode(204);
// Verify deletion
given()
.header("Authorization", "Bearer " + authToken)
.when()
.get("/api/users/" + createdUserId)
.then()
.statusCode(404);
}
}import Ajv from 'ajv';
const userSchema = {
type: 'object',
required: ['id', 'email', 'name', 'createdAt'],
properties: {
id: { type: 'string', pattern: '^[a-zA-Z0-9-]+$' },
email: { type: 'string', format: 'email' },
name: { type: 'string', minLength: 1 },
role: { type: 'string', enum: ['user', 'admin', 'moderator'] },
createdAt: { type: 'string', format: 'date-time' },
},
additionalProperties: false,
};
test('should match user schema', async () => {
const response = await api.get('/api/users/123');
const ajv = new Ajv();
const validate = ajv.compile(userSchema);
const valid = validate(response.data);
expect(valid).toBe(true);
if (!valid) {
console.error(validate.errors);
}
});REST API testing ensures your backend contract is solid and reliable. Test thoroughly, validate rigorously.
© PramodDutta, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in packs/qa-essentials/skills/api-testing-rest of PramodDutta/qaskills.
Open the folder on GitHubat commit 1d2a092
API Testing REST next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| API Testing REST this skillPramodDutta/qaskills | 232 | — | ~4.9k | Automated safety check: Pass | MIT | |
| API Test Suite Builderalirezarezvani/claude-skills | 28k | 1 repos | ~1.6k | Automated safety check: Pass | MIT | |
| Rust API Test Harnesshashgraph-online/awesome-codex-plugins | 1.2k | — | ~1.7k | Automated safety check: Pass | MIT | |
| 423 Frameworks Quarkus Testing Acceptance Testsjabrena/plinth | 446 | — | ~1.3k | Automated safety check: Pass | Apache-2.0 | |
| Integration Tests for pRESTprest/prest | 4.6k | — | ~1.1k | Automated safety check: Pass | MIT | |
| Reasoning Serialization Teststailcallhq/forgecode | 7.6k | — | ~1k | Automated safety check: Pass | Apache-2.0 |
alirezarezvani/claude-skills
A skill your agent uses when the user asks to generate API tests, create integration test suites, test REST endpoints, or build contract tests.
hashgraph-online/awesome-codex-plugins
A skill your agent uses when adding, changing, testing, or debugging Rust HTTP APIs and services, especially when Codex needs black-box integration tests, random-port app startup, real database test…
jabrena/plinth
A skill your agent uses when you need to implement acceptance tests from maintainer-sanitized Gherkin scenario facts for Quarkus applications — including @acceptance scenarios, @QuarkusTest…
prest/prest
Guides writing and reviewing pREST Docker-based integration tests so every HTTP request is explained by step comments or table-driven descriptions.
tailcallhq/forgecode
Checks that ReasoningConfig fields are serialized into the right provider-specific JSON for OpenRouter, Anthropic, GitHub Copilot and Codex requests.
lobehub/lobehub
Runs the official OpenResponses compliance test suite against a local or remote Response API endpoint and helps diagnose schema and authentication failures.
PramodDutta/qaskills
A skill your agent uses when adding or editing QA skills in seed-skills/ or getting them onto the live qaskills.sh catalog, e.g.
PramodDutta/qaskills
A skill your agent uses when publishing SEO blog articles to qaskills.sh, e.g.
PramodDutta/qaskills
A skill your agent uses when deploying qaskills.sh to production, verifying whether a deploy landed, or when a push to main did not show up on the live site, e.g.
PramodDutta/qaskills
The complete QA skill for Claude Code — turn Claude into an expert QA engineer that picks the right test type, writes reliable Playwright, Cypress, and pytest tests, eliminates flaky tests, enforces…
PramodDutta/qaskills
End-to-end testing skill using Cypress for web applications, covering custom commands, network intercepts, fixtures, cy.session, and component testing patterns.
PramodDutta/qaskills
Make Claude Code write and maintain end-to-end tests like a senior SDET — Playwright and Cypress flows with stable locators, the Page Object Model, fixtures, reused auth state, network mocking, and…
Categories
Comprehensive RESTful API testing patterns covering HTTP methods, status codes, request/response validation, authentication, error handling, and contract testing. API Testing REST is an agent skill from PramodDutta/qaskills. Comprehensive RESTful API testing patterns covering HTTP methods, status codes, request/response validation, authentication, error handling, and contract testing.
API Testing REST fits situations like: tasks that involve API testing; tasks that involve REST APIs; tasks that involve Integration testing.
Run `npx skills add PramodDutta/qaskills --skill api-testing-rest -a claude-code`. Or copy the skill folder (packs/qa-essentials/skills/api-testing-rest in PramodDutta/qaskills) into .claude/skills/api-testing-rest in your project. Claude Code loads it when a task matches its description.
Run `npx skills add PramodDutta/qaskills --skill api-testing-rest -a codex`. Or copy the skill folder (packs/qa-essentials/skills/api-testing-rest in PramodDutta/qaskills) into .agents/skills/api-testing-rest in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add PramodDutta/qaskills --skill api-testing-rest -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/api-testing-rest, .gemini/skills/api-testing-rest, .github/skills/api-testing-rest and .opencode/skills/api-testing-rest in your project.
SKILL.md names no scripts, command-line tools or credentials: API Testing REST is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
API Testing REST is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with API Testing REST: API Test Suite Builder (alirezarezvani/claude-skills, 28k stars), Rust API Test Harness (hashgraph-online/awesome-codex-plugins, 1.2k stars), 423 Frameworks Quarkus Testing Acceptance Tests (jabrena/plinth, 446 stars) and Integration Tests for pREST (prest/prest, 4.6k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
PramodDutta (a GitHub user) maintains it in PramodDutta/qaskills, which has 232 GitHub stars. The repository holds 11 skills in this directory. The repository was last updated on October 4, 2026.
Source: PramodDutta/qaskills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.