Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Give agents more agency

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    CuriousLearner

    api-tester

    CuriousLearner/api-tester
    DevOps
    20

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Quick API endpoint testing with comprehensive request/response validation.

    SKILL.md

    API Tester Skill

    Quick API endpoint testing with comprehensive request/response validation.

    Instructions

    You are an API testing expert. When invoked:

    1. Test API Endpoints:

      • Validate HTTP methods (GET, POST, PUT, PATCH, DELETE)
      • Test request headers and body formats
      • Verify response status codes
      • Validate response schema and data types
      • Check authentication and authorization
    2. Generate Test Cases:

      • Create curl commands for testing
      • Generate Postman collections
      • Write automated test scripts
      • Test edge cases and error scenarios
      • Validate API contracts
    3. Performance Testing:

      • Load testing with concurrent requests
      • Response time benchmarking
      • Rate limit verification
      • Timeout handling
      • Connection pooling tests
    4. Security Testing:

      • Authentication/authorization checks
      • Input validation testing
      • SQL injection prevention
      • XSS prevention
      • CORS configuration

    Usage Examples

    @api-tester
    @api-tester --endpoint /api/users
    @api-tester --method POST
    @api-tester --load-test
    @api-tester --generate-collection
    

    REST API Testing

    GET Request Examples

    Basic GET Request

    # curl
    curl -X GET https://api.example.com/api/users \
      -H "Content-Type: application/json"
    
    # With authentication
    curl -X GET https://api.example.com/api/users \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json"
    
    # With query parameters
    curl -X GET "https://api.example.com/api/users?page=1&limit=10&sort=created_at" \
      -H "Authorization: Bearer YOUR_TOKEN"
    
    # Verbose output (includes headers)
    curl -v -X GET https://api.example.com/api/users
    

    JavaScript/Node.js

    // Using fetch
    async function getUsers() {
      const response = await fetch('https://api.example.com/api/users', {
        method: 'GET',
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
          'Content-Type': 'application/json'
        }
      });
    
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
    
      const data = await response.json();
      return data;
    }
    
    // Using axios
    const axios = require('axios');
    
    async function getUsers() {
      try {
        const response = await axios.get('https://api.example.com/api/users', {
          headers: {
            'Authorization': 'Bearer YOUR_TOKEN'
          },
          params: {
            page: 1,
            limit: 10
          }
        });
        return response.data;
      } catch (error) {
        console.error('Error:', error.response?.data || error.message);
        throw error;
      }
    }
    

    Python

    import requests
    
    # Basic GET request
    response = requests.get('https://api.example.com/api/users')
    print(response.json())
    
    # With authentication and parameters
    headers = {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Content-Type': 'application/json'
    }
    
    params = {
        'page': 1,
        'limit': 10,
        'sort': 'created_at'
    }
    
    response = requests.get(
        'https://api.example.com/api/users',
        headers=headers,
        params=params
    )
    
    if response.status_code == 200:
        data = response.json()
        print(data)
    else:
        print(f"Error: {response.status_code}")
        print(response.text)
    

    POST Request Examples

    Create Resource

    # curl
    curl -X POST https://api.example.com/api/users \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "John Doe",
        "email": "john@example.com",
        "role": "user"
      }'
    
    # From file
    curl -X POST https://api.example.com/api/users \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d @user.json
    

    JavaScript/Node.js

    // Using fetch
    async function createUser(userData) {
      const response = await fetch('https://api.example.com/api/users', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(userData)
      });
    
      const data = await response.json();
      return data;
    }
    
    // Usage
    const newUser = {
      name: 'John Doe',
      email: 'john@example.com',
      role: 'user'
    };
    
    createUser(newUser)
      .then(user => console.log('Created:', user))
      .catch(error => console.error('Error:', error));
    
    // Using axios with error handling
    async function createUser(userData) {
      try {
        const response = await axios.post(
          'https://api.example.com/api/users',
          userData,
          {
            headers: {
              'Authorization': 'Bearer YOUR_TOKEN'
            }
          }
        );
        return response.data;
      } catch (error) {
        if (error.response) {
          // Server responded with error
          console.error('Error:', error.response.status);
          console.error('Message:', error.response.data);
        } else if (error.request) {
          // No response received
          console.error('No response from server');
        } else {
          console.error('Error:', error.message);
        }
        throw error;
      }
    }
    

    Python

    import requests
    
    # Create user
    user_data = {
        'name': 'John Doe',
        'email': 'john@example.com',
        'role': 'user'
    }
    
    headers = {
        'Authorization': 'Bearer YOUR_TOKEN',
        'Content-Type': 'application/json'
    }
    
    response = requests.post(
        'https://api.example.com/api/users',
        json=user_data,
        headers=headers
    )
    
    if response.status_code == 201:
        print('User created:', response.json())
    else:
        print(f'Error: {response.status_code}')
        print(response.json())
    

    PUT/PATCH Request Examples

    # PUT - Replace entire resource
    curl -X PUT https://api.example.com/api/users/123 \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "John Updated",
        "email": "john.updated@example.com",
        "role": "admin"
      }'
    
    # PATCH - Partial update
    curl -X PATCH https://api.example.com/api/users/123 \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "role": "admin"
      }'
    

    DELETE Request Examples

    # Delete resource
    curl -X DELETE https://api.example.com/api/users/123 \
      -H "Authorization: Bearer YOUR_TOKEN"
    
    # Delete with confirmation
    curl -X DELETE https://api.example.com/api/users/123 \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "X-Confirm-Delete: true"
    

    Authentication Examples

    Bearer Token (JWT)

    # Get token
    curl -X POST https://api.example.com/auth/login \
      -H "Content-Type: application/json" \
      -d '{
        "email": "user@example.com",
        "password": "password123"
      }'
    
    # Use token
    curl -X GET https://api.example.com/api/users \
      -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    

    API Key

    # In header
    curl -X GET https://api.example.com/api/users \
      -H "X-API-Key: your-api-key-here"
    
    # In query parameter
    curl -X GET "https://api.example.com/api/users?api_key=your-api-key-here"
    

    Basic Auth

    # Username and password
    curl -X GET https://api.example.com/api/users \
      -u username:password
    
    # Base64 encoded
    curl -X GET https://api.example.com/api/users \
      -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ="
    

    OAuth 2.0

    // Get access token
    async function getAccessToken() {
      const response = await fetch('https://oauth.example.com/token', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: new URLSearchParams({
          grant_type: 'client_credentials',
          client_id: 'YOUR_CLIENT_ID',
          client_secret: 'YOUR_CLIENT_SECRET'
        })
      });
    
      const data = await response.json();
      return data.access_token;
    }
    
    // Use access token
    async function callAPI() {
      const token = await getAccessToken();
    
      const response = await fetch('https://api.example.com/api/users', {
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
    
      return response.json();
    }
    

    GraphQL Testing

    Basic Query

    # curl
    curl -X POST https://api.example.com/graphql \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "query": "{ users { id name email } }"
      }'
    
    # With variables
    curl -X POST https://api.example.com/graphql \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "query": "query GetUser($id: ID!) { user(id: $id) { id name email } }",
        "variables": { "id": "123" }
      }'
    

    GraphQL Mutations

    // Create user mutation
    async function createUser(name, email) {
      const query = `
        mutation CreateUser($name: String!, $email: String!) {
          createUser(input: { name: $name, email: $email }) {
            id
            name
            email
            createdAt
          }
        }
      `;
    
      const response = await fetch('https://api.example.com/graphql', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_TOKEN',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          query,
          variables: { name, email }
        })
      });
    
      const data = await response.json();
      return data.data.createUser;
    }
    

    Automated Testing

    Jest Test Suite

    const axios = require('axios');
    
    describe('User API Tests', () => {
      const API_URL = 'https://api.example.com';
      const token = 'YOUR_TEST_TOKEN';
    
      const api = axios.create({
        baseURL: API_URL,
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
    
      describe('GET /api/users', () => {
        test('should return list of 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);
        });
    
        test('should return user by ID', async () => {
          const response = await api.get('/api/users/123');
    
          expect(response.status).toBe(200);
          expect(response.data).toHaveProperty('id', '123');
          expect(response.data).toHaveProperty('name');
          expect(response.data).toHaveProperty('email');
        });
    
        test('should return 404 for non-existent user', async () => {
          try {
            await api.get('/api/users/999999');
          } catch (error) {
            expect(error.response.status).toBe(404);
          }
        });
      });
    
      describe('POST /api/users', () => {
        test('should create new user', async () => {
          const newUser = {
            name: 'Test User',
            email: 'test@example.com'
          };
    
          const response = await api.post('/api/users', newUser);
    
          expect(response.status).toBe(201);
          expect(response.data).toHaveProperty('id');
          expect(response.data.name).toBe(newUser.name);
          expect(response.data.email).toBe(newUser.email);
        });
    
        test('should validate required fields', async () => {
          const invalidUser = { name: 'Test' }; // missing email
    
          try {
            await api.post('/api/users', invalidUser);
          } catch (error) {
            expect(error.response.status).toBe(400);
            expect(error.response.data).toHaveProperty('error');
          }
        });
    
        test('should prevent duplicate emails', async () => {
          const user = {
            name: 'Duplicate',
            email: 'existing@example.com'
          };
    
          try {
            await api.post('/api/users', user);
          } catch (error) {
            expect(error.response.status).toBe(409);
          }
        });
      });
    
      describe('Authentication', () => {
        test('should reject requests without token', async () => {
          const noAuthAPI = axios.create({ baseURL: API_URL });
    
          try {
            await noAuthAPI.get('/api/users');
          } catch (error) {
            expect(error.response.status).toBe(401);
          }
        });
    
        test('should reject invalid token', async () => {
          const badAuthAPI = axios.create({
            baseURL: API_URL,
            headers: { 'Authorization': 'Bearer invalid-token' }
          });
    
          try {
            await badAuthAPI.get('/api/users');
          } catch (error) {
            expect(error.response.status).toBe(401);
          }
        });
      });
    });
    

    Python pytest

    import pytest
    import requests
    
    API_URL = 'https://api.example.com'
    TOKEN = 'YOUR_TEST_TOKEN'
    
    @pytest.fixture
    def headers():
        return {
            'Authorization': f'Bearer {TOKEN}',
            'Content-Type': 'application/json'
        }
    
    def test_get_users(headers):
        response = requests.get(f'{API_URL}/api/users', headers=headers)
    
        assert response.status_code == 200
        assert isinstance(response.json(), list)
        assert len(response.json()) > 0
    
    def test_get_user_by_id(headers):
        response = requests.get(f'{API_URL}/api/users/123', headers=headers)
    
        assert response.status_code == 200
        data = response.json()
        assert data['id'] == '123'
        assert 'name' in data
        assert 'email' in data
    
    def test_create_user(headers):
        user_data = {
            'name': 'Test User',
            'email': 'test@example.com'
        }
    
        response = requests.post(
            f'{API_URL}/api/users',
            json=user_data,
            headers=headers
        )
    
        assert response.status_code == 201
        data = response.json()
        assert 'id' in data
        assert data['name'] == user_data['name']
    
    def test_unauthorized_access():
        response = requests.get(f'{API_URL}/api/users')
        assert response.status_code == 401
    

    Postman Collection

    Collection Structure

    {
      "info": {
        "name": "API Test Collection",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
      },
      "auth": {
        "type": "bearer",
        "bearer": [
          {
            "key": "token",
            "value": "{{access_token}}",
            "type": "string"
          }
        ]
      },
      "item": [
        {
          "name": "Users",
          "item": [
            {
              "name": "Get All Users",
              "request": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/api/users?page=1&limit=10",
                  "host": ["{{base_url}}"],
                  "path": ["api", "users"],
                  "query": [
                    { "key": "page", "value": "1" },
                    { "key": "limit", "value": "10" }
                  ]
                }
              },
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status code is 200', function () {",
                      "    pm.response.to.have.status(200);",
                      "});",
                      "",
                      "pm.test('Response is array', function () {",
                      "    var jsonData = pm.response.json();",
                      "    pm.expect(jsonData).to.be.an('array');",
                      "});"
                    ]
                  }
                }
              ]
            },
            {
              "name": "Create User",
              "request": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"name\": \"{{$randomFullName}}\",\n  \"email\": \"{{$randomEmail}}\",\n  \"role\": \"user\"\n}"
                },
                "url": {
                  "raw": "{{base_url}}/api/users",
                  "host": ["{{base_url}}"],
                  "path": ["api", "users"]
                }
              },
              "event": [
                {
                  "listen": "test",
                  "script": {
                    "exec": [
                      "pm.test('Status code is 201', function () {",
                      "    pm.response.to.have.status(201);",
                      "});",
                      "",
                      "pm.test('User has ID', function () {",
                      "    var jsonData = pm.response.json();",
                      "    pm.expect(jsonData).to.have.property('id');",
                      "    pm.environment.set('user_id', jsonData.id);",
                      "});"
                    ]
                  }
                }
              ]
            }
          ]
        }
      ],
      "variable": [
        {
          "key": "base_url",
          "value": "https://api.example.com"
        }
      ]
    }
    

    Load Testing

    Using Apache Bench

    # 1000 requests, 10 concurrent
    ab -n 1000 -c 10 -H "Authorization: Bearer TOKEN" \
      https://api.example.com/api/users
    
    # POST request with JSON
    ab -n 1000 -c 10 -p data.json -T application/json \
      -H "Authorization: Bearer TOKEN" \
      https://api.example.com/api/users
    

    Using Artillery

    # artillery.yml
    config:
      target: 'https://api.example.com'
      phases:
        - duration: 60
          arrivalRate: 10
          name: Warm up
        - duration: 300
          arrivalRate: 50
          name: Sustained load
      defaults:
        headers:
          Authorization: 'Bearer YOUR_TOKEN'
    
    scenarios:
      - name: "Get users"
        flow:
          - get:
              url: "/api/users"
              expect:
                - statusCode: 200
          - think: 1
          - post:
              url: "/api/users"
              json:
                name: "Test User"
                email: "test@example.com"
              expect:
                - statusCode: 201
    
    # Run load test
    artillery run artillery.yml
    
    # Generate HTML report
    artillery run artillery.yml --output report.json
    artillery report report.json --output report.html
    

    Response Validation

    Schema Validation

    const Ajv = require('ajv');
    const ajv = new Ajv();
    
    // Define schema
    const userSchema = {
      type: 'object',
      properties: {
        id: { type: 'string' },
        name: { type: 'string' },
        email: { type: 'string', format: 'email' },
        role: { type: 'string', enum: ['user', 'admin'] },
        createdAt: { type: 'string', format: 'date-time' }
      },
      required: ['id', 'name', 'email', 'role']
    };
    
    const validate = ajv.compile(userSchema);
    
    // Validate response
    async function testUserAPI() {
      const response = await fetch('https://api.example.com/api/users/123');
      const data = await response.json();
    
      const valid = validate(data);
      if (!valid) {
        console.error('Validation errors:', validate.errors);
      } else {
        console.log('Response is valid!');
      }
    }
    

    Best Practices

    Request Best Practices

    • Always set appropriate Content-Type headers
    • Use proper HTTP methods (GET for reads, POST for creates, etc.)
    • Include authentication tokens securely
    • Handle timeouts and retries
    • Validate input before sending
    • Use HTTPS for production APIs

    Response Handling

    • Check status codes before parsing
    • Handle errors gracefully
    • Validate response schema
    • Log requests and responses for debugging
    • Implement exponential backoff for retries

    Security Testing

    • Test with invalid tokens
    • Test without authentication
    • Attempt SQL injection in parameters
    • Test XSS in input fields
    • Verify CORS settings
    • Test rate limiting

    Error Scenarios to Test

    • Invalid authentication
    • Missing required fields
    • Invalid data types
    • Duplicate resources
    • Not found (404)
    • Server errors (500)
    • Rate limit exceeded (429)
    • Network timeouts

    Common HTTP Status Codes

    200 OK - Request successful
    201 Created - Resource created
    204 No Content - Success, no response body
    400 Bad Request - Invalid request
    401 Unauthorized - Missing/invalid authentication
    403 Forbidden - Not allowed to access
    404 Not Found - Resource doesn't exist
    409 Conflict - Resource already exists
    422 Unprocessable Entity - Validation failed
    429 Too Many Requests - Rate limit exceeded
    500 Internal Server Error - Server error
    502 Bad Gateway - Upstream server error
    503 Service Unavailable - Server overloaded
    

    Notes

    • Always test in development/staging before production
    • Use environment variables for API URLs and tokens
    • Document all test cases and expected results
    • Automate testing in CI/CD pipeline
    • Monitor API performance and error rates
    • Keep Postman collections updated
    • Test edge cases and error scenarios
    • Validate both success and failure paths
    • Use proper authentication methods
    • Never commit API keys or tokens to version control
    Recommended Servers
    Context7
    Context7
    VAT Validator MCP
    VAT Validator MCP
    Blockscout MCP Server
    Blockscout MCP Server
    Repository
    curiouslearner/devkit
    Files