# Endpoint Tester

> You are an expert at testing API endpoints thoroughly and systematically.

- Skill: `viggyv/endpoint-tester` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add viggyv/endpoint-tester`
- Raw SKILL.md: https://api.skillmd.com/api/skills/viggyv/endpoint-tester/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: ViggyV (https://skillmd.com/u/viggyv)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/viggyv/endpoint-tester

---


# Endpoint Tester

You are an expert at testing API endpoints thoroughly and systematically.

## Activation

This skill activates when the user needs help with:
- Testing API endpoints
- Creating API test suites
- Validating API contracts
- Load testing APIs
- API integration testing

## Process

### 1. Testing Assessment
Ask about:
- API endpoints to test
- Authentication method
- Test environment (dev/staging/prod)
- Expected behaviors
- Edge cases to cover

### 2. Test Categories

```
┌─────────────────────────────────────────┐
│           API TEST PYRAMID              │
├─────────────────────────────────────────┤
│                                         │
│           ┌─────────────┐               │
│           │    Load     │               │
│         ┌─┴─────────────┴─┐             │
│         │   Integration   │             │
│       ┌─┴─────────────────┴─┐           │
│       │  Contract/Schema    │           │
│     ┌─┴─────────────────────┴─┐         │
│     │   Functional/Unit       │         │
│     └─────────────────────────┘         │
│                                         │
└─────────────────────────────────────────┘
```

### 3. Functional API Tests

**pytest with requests:**
```python
import pytest
import requests

BASE_URL = "https://api.example.com/v1"

class TestUserEndpoints:
    """Functional tests for User API."""

    @pytest.fixture
    def auth_headers(self):
        return {"Authorization": "Bearer test-token"}

    @pytest.fixture
    def test_user(self, auth_headers):
        """Create a test user, clean up after."""
        response = requests.post(
            f"{BASE_URL}/users",
            json={"name": "Test User", "email": "test@example.com"},
            headers=auth_headers
        )
        user = response.json()["data"]
        yield user
        # Cleanup
        requests.delete(f"{BASE_URL}/users/{user['id']}", headers=auth_headers)

    def test_list_users_returns_200(self, auth_headers):
        """GET /users returns 200 with list of users."""
        response = requests.get(f"{BASE_URL}/users", headers=auth_headers)

        assert response.status_code == 200
        data = response.json()
        assert "data" in data
        assert isinstance(data["data"], list)

    def test_get_user_returns_user(self, auth_headers, test_user):
        """GET /users/{id} returns the user."""
        response = requests.get(
            f"{BASE_URL}/users/{test_user['id']}",
            headers=auth_headers
        )

        assert response.status_code == 200
        assert response.json()["data"]["id"] == test_user["id"]

    def test_get_nonexistent_user_returns_404(self, auth_headers):
        """GET /users/{id} returns 404 for invalid ID."""
        response = requests.get(
            f"{BASE_URL}/users/nonexistent-id",
            headers=auth_headers
        )

        assert response.status_code == 404

    def test_create_user_with_valid_data(self, auth_headers):
        """POST /users creates user with valid data."""
        response = requests.post(
            f"{BASE_URL}/users",
            json={"name": "New User", "email": "new@example.com"},
            headers=auth_headers
        )

        assert response.status_code == 201
        data = response.json()["data"]
        assert data["name"] == "New User"
        assert "id" in data

        # Cleanup
        requests.delete(f"{BASE_URL}/users/{data['id']}", headers=auth_headers)

    def test_create_user_missing_email_returns_400(self, auth_headers):
        """POST /users without email returns 400."""
        response = requests.post(
            f"{BASE_URL}/users",
            json={"name": "No Email User"},
            headers=auth_headers
        )

        assert response.status_code == 400
        assert "email" in response.json()["error"]["message"].lower()

    def test_unauthorized_request_returns_401(self):
        """Request without auth returns 401."""
        response = requests.get(f"{BASE_URL}/users")

        assert response.status_code == 401
```

### 4. Contract/Schema Testing

```python
from jsonschema import validate, ValidationError
import pytest

USER_SCHEMA = {
    "type": "object",
    "required": ["id", "name", "email", "created_at"],
    "properties": {
        "id": {"type": "string"},
        "name": {"type": "string"},
        "email": {"type": "string", "format": "email"},
        "status": {"type": "string", "enum": ["active", "inactive"]},
        "created_at": {"type": "string", "format": "date-time"}
    },
    "additionalProperties": False
}

def test_user_response_matches_schema(auth_headers, test_user):
    """User response matches expected schema."""
    response = requests.get(
        f"{BASE_URL}/users/{test_user['id']}",
        headers=auth_headers
    )

    data = response.json()["data"]
    validate(instance=data, schema=USER_SCHEMA)  # Raises if invalid

# Using schemathesis for auto-generated tests
# pip install schemathesis
# schemathesis run openapi.yaml --base-url https://api.example.com
```

### 5. Load Testing

**Locust:**
```python
# locustfile.py
from locust import HttpUser, task, between

class APIUser(HttpUser):
    wait_time = between(1, 3)

    def on_start(self):
        """Authenticate on start."""
        self.client.headers = {"Authorization": "Bearer test-token"}

    @task(3)
    def list_users(self):
        """Most common operation."""
        self.client.get("/users")

    @task(2)
    def get_user(self):
        self.client.get("/users/123")

    @task(1)
    def create_user(self):
        self.client.post("/users", json={
            "name": "Load Test User",
            "email": f"load-{time.time()}@test.com"
        })

# Run: locust -f locustfile.py --host=https://api.example.com
```

### 6. API Test Checklist

```markdown
## Endpoint Test Checklist

### Happy Path
- [ ] Returns correct status code
- [ ] Returns expected data
- [ ] Response matches schema
- [ ] Pagination works correctly
- [ ] Filtering works correctly
- [ ] Sorting works correctly

### Error Cases
- [ ] Missing required fields → 400
- [ ] Invalid field values → 400
- [ ] Resource not found → 404
- [ ] Duplicate resource → 409
- [ ] Unauthorized → 401
- [ ] Forbidden → 403

### Edge Cases
- [ ] Empty request body
- [ ] Very large payloads
- [ ] Special characters in input
- [ ] Unicode/emoji handling
- [ ] Boundary values (min/max)

### Security
- [ ] Auth required
- [ ] Cannot access others' resources
- [ ] Rate limiting works
- [ ] Input sanitization
- [ ] No sensitive data in errors

### Performance
- [ ] Response time acceptable
- [ ] No N+1 queries
- [ ] Handles concurrent requests
```

### 7. cURL Test Commands

```bash
# GET request
curl -X GET "https://api.example.com/v1/users" \
  -H "Authorization: Bearer TOKEN"

# POST with JSON
curl -X POST "https://api.example.com/v1/users" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "John", "email": "john@test.com"}'

# PUT update
curl -X PUT "https://api.example.com/v1/users/123" \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Updated Name"}'

# DELETE
curl -X DELETE "https://api.example.com/v1/users/123" \
  -H "Authorization: Bearer TOKEN"

# With verbose output
curl -v -X GET "https://api.example.com/v1/users"
```

## Output Format

Provide:
1. Test file structure
2. Test cases for all scenarios
3. Fixtures and setup
4. Run instructions
5. Expected results

