REST and GraphQL APIs via Claude Code
Your product team just scoped a new integration. The partner needs a REST API with twelve endpoints, OAuth2 authentication, rate limiting, and webhook delivery. You need it production-ready in two weeks. The traditional approach means three days of boilerplate before you write a single line of business logic — route scaffolding, validation schemas, error handlers, auth middleware, and the OpenAPI spec that the partner will use to integrate.
Claude Code compresses that scaffolding to a single session. You describe the API design, Claude generates the routes with validation and error handling that match your existing patterns, and you test endpoints with curl right from the same terminal. The key is knowing how to guide the generation so you get production-quality code instead of a demo.
What You’ll Walk Away With
Section titled “What You’ll Walk Away With”- A workflow for designing and implementing APIs entirely from the terminal
- Prompts that generate endpoints with proper validation, auth, and error handling
- The inline curl testing technique for rapid API development
- Patterns for generating OpenAPI specs from your route handlers
The API Development Workflow
Section titled “The API Development Workflow”-
Design the API contract first
Before writing any code, have Claude produce an API design document. This catches design issues before you commit to an implementation.
-
Review the design before implementing
Read the API design. Check that the resources are correct, the naming is consistent, and the error codes make sense. It is much cheaper to change a design document than to refactor implemented code.
-
Implement the routes matching your existing patterns
Read the existing route handlers in src/routes/ to learn ourpatterns. Then implement the partner API routes following thesame structure:- Same middleware chain (auth, rate limit, validation)- Same error response format- Same logging approach- Same test patternsStart with the products endpoints. I'll review before youmove to orders. -
Test inline with curl
This is where the terminal-native workflow shines. You do not need Postman or a separate tool — test right from the Claude session.
Start the dev server, then test the products endpoint:curl -X GET http://localhost:3000/api/v1/products \-H "Authorization: Bearer test-token" \-H "Content-Type: application/json"Show me the response. Then test with invalid auth,missing parameters, and an empty result set. -
Generate the OpenAPI spec
Now that the routes are implemented and tested, generate anOpenAPI 3.0 spec from the actual route handlers and Zod schemas.Save it to docs/partner-api.yaml.
Implementing REST Endpoints
Section titled “Implementing REST Endpoints”The validation-first approach
Section titled “The validation-first approach”Good APIs validate input before anything else. Claude can generate Zod (or equivalent) schemas directly from your API design.
Create Zod schemas for the partner API:
1. ProductQuerySchema - validates query parameters for GET /products (category: string, minPrice: number, maxPrice: number, page: number, limit: number)
2. CreateOrderSchema - validates the POST /orders body (customerId: string, items: array of {productId, quantity}, shippingAddress: object, notes: optional string)
3. WebhookConfigSchema - validates POST /webhooks body (url: valid URL, events: array of event types, secret: string)
Put them in src/schemas/partner.schema.ts following the patternsin our existing schema files.Error handling that is consistent
Section titled “Error handling that is consistent”Authentication and authorization
Section titled “Authentication and authorization”Implement OAuth2 client credentials authentication for thepartner API. Read our existing auth middleware insrc/middleware/auth.ts for patterns.
The partner auth flow:1. Partner requests token: POST /oauth/token with client_id and client_secret2. We return a JWT with scopes: products:read, orders:write, webhooks:manage3. Each endpoint checks the required scope4. Tokens expire after 1 hour
Create the middleware and apply it to the partner routes.Include tests that verify:- Valid token with correct scope passes- Valid token with wrong scope gets 403- Expired token gets 401- Missing token gets 401Implementing GraphQL APIs
Section titled “Implementing GraphQL APIs”For projects using GraphQL, Claude generates schemas, resolvers, and the DataLoader patterns needed to avoid N+1 queries.
We're adding a GraphQL API alongside our REST endpoints.Read the existing REST route handlers and database models.
Generate:1. GraphQL schema (SDL) with types matching our models2. Resolvers that call our existing service layer3. DataLoaders for User, Product, and Order to prevent N+14. Authentication context that integrates with our JWT auth
Use Apollo Server and follow the patterns from the GraphQLexample in our docs. Include connection types for paginatedlists (Relay cursor-based pagination).Preventing N+1 queries
Section titled “Preventing N+1 queries”Our GraphQL API has N+1 problems. When querying orders,each order loads its user individually. Read the resolvercode in src/graphql/resolvers/.
Create DataLoaders for:1. UserLoader - batch load users by ID2. ProductLoader - batch load products by ID3. OrderItemsLoader - batch load order items by order ID
Wire them into the Apollo context. Show me the before/afterquery count for a query that fetches 20 orders with theirusers and items.Testing APIs from the Terminal
Section titled “Testing APIs from the Terminal”Inline curl testing
Section titled “Inline curl testing”The fastest way to test an API during development is curl from the same terminal session where Claude is running.
Test the complete order creation flow:
1. Create a product:curl -X POST http://localhost:3000/api/v1/products \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "Widget", "price": 29.99, "category": "tools"}'
2. Create an order using the product ID from step 1:curl -X POST http://localhost:3000/api/v1/orders \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"customerId": "cust-123", "items": [{"productId": "PRODUCT_ID", "quantity": 2}]}'
3. Verify the order was created:curl -X GET http://localhost:3000/api/v1/orders/ORDER_ID \ -H "Authorization: Bearer $TOKEN"
Show me each response.Automated API test generation
Section titled “Automated API test generation”Generate API integration tests for the partner endpoints.Use supertest (or the test client for our framework).Follow the test patterns in tests/routes/.
For each endpoint, test:- Successful request with valid input- Validation error with invalid input- Authentication required (no token)- Authorization denied (wrong scope)- Not found (invalid ID)- Conflict (duplicate creation)- Rate limit exceeded
Include a test helper that creates an authenticated test clientwith partner credentials.Rate Limiting and Pagination
Section titled “Rate Limiting and Pagination”Rate limiting implementation
Section titled “Rate limiting implementation”Add rate limiting to the partner API. Read our existing ratelimiter in src/middleware/rateLimit.ts.
Configuration:- Standard tier: 100 requests per minute per API key- Elevated tier: 1000 requests per minute per API key- Include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on every response- Return 429 with Retry-After header when exceeded
The tier is determined by the partner's plan stored in thedatabase. Cache the plan lookup in Redis with a 5-minute TTL.Cursor-based pagination
Section titled “Cursor-based pagination”Implement cursor-based pagination for all list endpoints.Read our existing pagination helper in src/lib/pagination.ts.
The response format should be:{ "data": [...], "pagination": { "cursor": "encoded-cursor", "hasMore": true, "totalCount": 1234 }}
The cursor encodes the sort field and ID for consistentordering. Support both forward and backward pagination.Add tests that verify pagination works correctly withfilters applied.Webhook Implementation
Section titled “Webhook Implementation”Implement webhook delivery for order status changes.
1. Partners register webhooks: POST /webhooks - URL, events to subscribe, signing secret
2. When an order status changes, queue webhook deliveries to all subscribers of that event
3. Webhook payload format: { "event": "order.status_changed", "data": { order }, "timestamp": "ISO" }
4. Sign each payload with HMAC-SHA256 using the partner's secret Include the signature in X-Webhook-Signature header
5. Retry failed deliveries: 3 attempts with exponential backoff (30s, 5min, 30min)
6. Log all delivery attempts for debugging
Follow our existing job queue patterns in src/jobs/.Include tests that verify signing, retry behavior, andthe delivery endpoint receiving correct payloads.When This Breaks
Section titled “When This Breaks”Generated endpoints have inconsistent response formats. Claude sometimes uses different error shapes across endpoints. Define the format once and enforce it: “All error responses must use the ErrorResponse type defined in src/types/api.ts. Do not create ad-hoc error objects.”
Validation is too loose or too strict. Review the Zod schemas Claude generates against your actual data. Common issues: string fields missing max length, number fields without reasonable bounds, optional fields that should be required. Tell Claude: “For every field in the schema, add reasonable constraints. Strings need maxLength, numbers need min/max, arrays need maxItems.”
Auth middleware is applied inconsistently. Some endpoints require auth, others do not. Create a convention: “All routes under /api/v1/partner/ require the partnerAuth middleware. Health checks and the OAuth token endpoint are the only exceptions. Verify this by listing all routes and their middleware.”
API performs well in tests but slowly in production. The test database is small. Add a performance test: “Generate a test that creates 10,000 products, then benchmarks the list endpoint with various filter combinations. Show me response times and query counts.”
The OpenAPI spec drifts from the implementation. Generate the spec from code, not the other way around. Add a CI check: “Compare the OpenAPI spec with the actual route handlers. Fail the build if they disagree.”
What’s Next
Section titled “What’s Next”Your API is implemented with proper validation, auth, and error handling. Now make sure the database layer underneath it is designed for the queries your API actually runs.