All skills
Skillintermediate

API Tester

Test all API endpoints for correctness and robustness. Output to `.claude/audits/API_TEST_REPORT.md`.

Claude Code Knowledge Pack7/10/2026

Overview

API Tester

Test all API endpoints for correctness and robustness. Output to .claude/audits/API_TEST_REPORT.md.

Status Block (Required)

Every output MUST start with:

---
agent: api-tester
status: COMPLETE | PARTIAL | SKIPPED | ERROR
timestamp: [ISO timestamp]
duration: [seconds]
findings: [count]
mode: live | static
server_available: [true | false]
endpoints_discovered: [count]
endpoints_tested: [count]
errors: []
skipped_checks: []
---

Execution Modes

Mode Selection

# 1. Check if dev server is running
curl -s --max-time 2 http://localhost:3000/api/health 2>/dev/null && echo "SERVER: Available at :3000"
curl -s --max-time 2 http://localhost:3001/api/health 2>/dev/null && echo "SERVER: Available at :3001"
curl -s --max-time 2 http://localhost:8080/api/health 2>/dev/null && echo "SERVER: Available at :8080"

# 2. Try to detect port from package.json
grep -o '"dev":\\s*"[^"]*"' package.json 2>/dev/null | grep -o ':[0-9]*' | head -1

# 3. Check for common health endpoints
curl -s --max-time 2 http://localhost:3000/ 2>/dev/null && echo "SERVER: Root available"

If server available: Use Live Mode - Full endpoint testing with curl If server NOT available: Use Static Mode - Code analysis only

Process

  1. Discover - Find all API endpoints
  2. Analyze - Review route handler code
  3. Test - Call endpoints (live mode only)
  4. Report - Document findings

Discovery (Both Modes)

# Find API routes (Next.js App Router)
find src/app/api -name "route.ts" -o -name "route.js" 2>/dev/null

# Find API routes (Next.js Pages Router)
find src/pages/api pages/api -name "*.ts" -o -name "*.js" 2>/dev/null | grep -v ".d.ts"

# Find Express/Fastify routes
grep -rn "router\\.\\(get\\|post\\|put\\|delete\\|patch\\)\\|app\\.\\(get\\|post\\|put\\|delete\\|patch\\)" src --include="*.ts" --include="*.js" 2>/dev/null | head -30

# Find route handlers
grep -rn "export.*GET\\|export.*POST\\|export.*PUT\\|export.*DELETE\\|export.*PATCH" src/app --include="*.ts" --include="*.js" 2>/dev/null | head -30

Static Analysis (When Server Unavailable)

Analyze route code without making actual requests:

# Check for missing auth
grep -rn "export.*GET\\|export.*POST" src/app/api --include="*.ts" 2>/dev/null | while read line; do
  file=$(echo "$line" | cut -d: -f1)
  grep -L "getServerSession\\|auth\\|verify\\|middleware" "$file" 2>/dev/null
done | head -10

# Check for missing input validation
grep -rn "req.body\\|request.json\\(\\)" src/app/api --include="*.ts" 2>/dev/null | head -10

# Check for raw SQL/NoSQL (injection risk)
grep -rn "\\$queryRaw\\|\\$executeRaw\\|\\.query\\(" src/app/api --include="*.ts" 2>/dev/null | head -10

# Check error handling
grep -rn "catch\\|try" src/app/api --include="*.ts" 2>/dev/null | wc -l

# Check for rate limiting setup
grep -rn "rateLimit\\|rate-limit\\|limiter" src --include="*.ts" 2>/dev/null | head -5

# Check for CORS configuration
grep -rn "cors\\|Access-Control" src --include="*.ts" 2>/dev/null | head -5

Live Testing (When Server Available)

# Health check
curl -s http://localhost:3000/api/health | jq 2>/dev/null || echo "No health endpoint"

# GET endpoint
curl -s http://localhost:3000/api/users | jq 2>/dev/null | head -20

# POST with JSON
curl -s -X POST http://localhost:3000/api/users \\
  -H "Content-Type: application/json" \\
  -d '{"email":"test@example.com","name":"Test"}' | jq 2>/dev/null

# With auth token (if available)
curl -s http://localhost:3000/api/protected \\
  -H "Authorization: Bearer TOKEN" | jq 2>/dev/null

# Test validation (missing field)
curl -s -X POST http://localhost:3000/api/users \\
  -H "Content-Type: application/json" \\
  -d '{"email":"test@example.com"}' | jq 2>/dev/null

# Test 404
curl -s http://localhost:3000/api/users/nonexistent | jq 2>/dev/null

Test Categories

Happy Path

  • Valid request returns expected response
  • Correct status codes (200, 201, 204)
  • Response shape matches schema
  • Pagination works correctly

Authentication

  • Unauthorized returns 401
  • Invalid token returns 401
  • Expired token handled
  • Role-based access works

Validation

  • Missing required fields return 400
  • Invalid field types return 400
  • Empty strings handled
  • Boundary values work

Error Handling

  • 404 for non-existent resources
  • 500 errors have generic message
  • Errors don't expose internals
  • Rate limiting works

Edge Cases

  • Empty arrays handled
  • Null values handled
  • Special characters in input
  • Very long strings

Output

# API Test Report

---
agent: api-tester
status: [COMPLETE|PARTIAL|SKIPPED]
timestamp: [ISO timestamp]
duration: [X seconds]
findings: [X]
mode: [live|static]
server_available: [true|false]
endpoints_discovered: [X]
endpoints_tested: [X]
errors: [list any errors]
skipped_checks: [list checks that couldn't run]
---

## Execution Mode

**Mode:** [Live Testing | Static Analysis Only]
**Server Status:** [Available at localhost:3000 | Not Available]

⚠️ **Note:** [If static mode] This report is based on code analysis only. For complete testing, start the dev server and re-run.

## Summary
| Category | Passed | Failed | Skipped |
|----------|--------|--------|---------|
| Happy Path | X | X | X |
| Auth | X | X | X |
| Validation | X | X | X |
| Error Handling | X | X | X |

**Endpoints Discovered:** X
**Endpoints Tested:** X (live mode) | 0 (static mode)
**Pass Rate:** X%

## Endpoint Coverage

| Endpoint | Method | Auth | Tests | Status |
|----------|--------|------|-------|--------|
| /api/health | GET | No | 1 | PASS |
| /api/users | GET | Yes | 3 | PASS |
| /api/users | POST | Yes | 5 | FAIL |
| /api/users/:id | GET | Yes | 2 | PASS |
| /api/users/:id | PUT | Yes | 4 | PASS |
| /api/users/:id | DELETE | Yes | 2 | SKIP |

## Static Analysis Findings (Code Review)

### API-S001: Missing Authentication Check
**File:** `src/app/api/admin/route.ts`
**Issue:** No auth middleware or session check
**Risk:** Unauthorized access to admin functions
**Fix:** Add authentication check
```typescript

  const session = await getServerSession();
  if (!session) return new Response("Unauthorized", { status: 401 });
  // ...
}

API-S002: No Input Validation

File: src/app/api/users/route.ts:15 Issue: Request body used directly without validation Risk: Invalid data, injection attacks Fix: Add Zod/Yup validation

const schema = z.object({ email: z.string().email(), name: z.string() });
const data = schema.parse(await request.json());

API-S003: Raw Database Query

File: src/app/api/search/route.ts:23 Issue: Using $queryRaw with user input Risk: SQL injection Fix: Use parameterized queries or Prisma methods

Live Test Failures (If Server Available)

API-001: POST /api/users - Missing Validation

Request:

POST /api/users
{ "email": "" }

Expected: 400 Bad Request with error message Actual: 500 Internal Server Error Issue: Empty email causes database error instead of validation error Fix: Add validation before database operation

API-002: GET /api/users/:id - Exposes Stack Trace

Request:

GET /api/users/invalid-id

Expected: 404 with generic message Actual: 500 with full stack trace

{
  "error": "PrismaClientKnownRequestError...",
  "stack": "at Object..."
}

Fix: Catch errors and return generic message in production

API-003: POST /api/login - No Rate Limiting

Issue: Can send unlimited login attempts Risk: Brute force attacks possible Fix: Add rate limiting (e.g., 5 attempts per minute)

Passing Tests (If Live Mode)

GET /api/health

  • Returns 200
  • Response includes status: "ok"
  • Response time < 100ms

GET /api/users

  • Returns 200 with valid token
  • Returns 401 without token
  • Returns paginated results
  • Respects limit parameter

PUT /api/users/:id

  • Returns 200 on success
  • Returns 404 for non-existent user
  • Returns 403 when updating other user
  • Validates input fields

Skipped Tests

EndpointReason
DELETE /api/users/:idDestructive - manual test only
POST /api/paymentsRequires Stripe test mode
All endpointsServer not available (static mode)

Recommendations

  1. Add input validation - Use zod or yup schemas
  2. Standardize error responses - Consistent error format
  3. Add rate limiting - Protect auth endpoints
  4. Implement request logging - For debugging
  5. Add API documentation - OpenAPI/Swagger

Test Commands Reference

# Start dev server first
npm run dev

# Run all API tests
npm run test:api

# Test specific endpoint
curl -v http://localhost:3000/api/[endpoint]

# Load test (if hey/ab installed)
hey -n 100 -c 10 http://localhost:3000/api/health

## Execution Logging

After completing, append to `.claude/audits/EXECUTION_LOG.md`:

| [timestamp] | api-tester | [status] | [duration] | [findings] | [errors] |


## Output Verification

Before completing:
1. Verify `.claude/audits/API_TEST_REPORT.md` was created
2. Verify file has content beyond headers
3. If static mode, clearly note "Static Analysis Only - Server Not Available"
4. If no issues found, write "No API issues detected" (not empty file)

Test real endpoints if dev server is running. When server unavailable, perform thorough static analysis and clearly document the limitation.