API Expert

The API Expert agent specializes in API design, documentation, and best practices for building robust APIs.

Expertise Areas#

  • REST API Design - Resources, methods, status codes
  • GraphQL - Schemas, resolvers, subscriptions
  • tRPC - Type-safe APIs, procedures
  • OpenAPI/Swagger - Documentation, code generation
  • Versioning - Strategies, deprecation, migration
  • Rate Limiting - Throttling, quotas, fairness
  • Error Handling - Standard errors, problem details

Usage Examples#

API Design#

Use the api-expert agent to design a RESTful API for a task management application.

Response includes:

  • Resource design
  • Endpoint definitions
  • Request/response schemas
  • Authentication strategy

GraphQL Schema#

Use the api-expert agent to create a GraphQL schema for an e-commerce platform.

Response includes:

  • Type definitions
  • Query and mutation definitions
  • Subscription setup
  • Resolver patterns

API Documentation#

Use the api-expert agent to generate OpenAPI documentation for our existing API.

Response includes:

  • OpenAPI specification
  • Endpoint documentation
  • Schema definitions
  • Example requests/responses

REST API Best Practices#

Resource Naming#

Good: GET /users # List users GET /users/:id # Get user POST /users # Create user PUT /users/:id # Update user DELETE /users/:id # Delete user GET /users/:id/orders # Get user's orders Bad: GET /getUsers # Verb in URL POST /createUser # Verb in URL GET /user/:id # Inconsistent plural DELETE /users/:id/delete # Redundant verb

HTTP Status Codes#

CodeMeaningUse Case
200OKSuccessful GET, PUT
201CreatedSuccessful POST
204No ContentSuccessful DELETE
400Bad RequestValidation error
401UnauthorizedMissing/invalid auth
403ForbiddenInsufficient permissions
404Not FoundResource doesn't exist
409ConflictDuplicate resource
422UnprocessableBusiness logic error
429Too Many RequestsRate limited
500Server ErrorUnexpected error

Response Structure#

1// Success response 2{ 3 "data": { 4 "id": "123", 5 "name": "John Doe", 6 "email": "john@example.com" 7 }, 8 "meta": { 9 "requestId": "req_abc123" 10 } 11} 12 13// List response with pagination 14{ 15 "data": [ 16 { "id": "1", "name": "Item 1" }, 17 { "id": "2", "name": "Item 2" } 18 ], 19 "meta": { 20 "page": 1, 21 "perPage": 20, 22 "total": 100, 23 "totalPages": 5 24 }, 25 "links": { 26 "self": "/items?page=1", 27 "next": "/items?page=2", 28 "last": "/items?page=5" 29 } 30} 31 32// Error response (RFC 7807) 33{ 34 "type": "https://api.example.com/errors/validation", 35 "title": "Validation Error", 36 "status": 400, 37 "detail": "The request body contains invalid data", 38 "instance": "/users", 39 "errors": [ 40 { 41 "field": "email", 42 "message": "Invalid email format" 43 } 44 ] 45}

GraphQL Patterns#

Schema Design#

1type Query { 2 user(id: ID!): User 3 users(filter: UserFilter, pagination: PaginationInput): UserConnection! 4} 5 6type Mutation { 7 createUser(input: CreateUserInput!): CreateUserPayload! 8 updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload! 9 deleteUser(id: ID!): DeleteUserPayload! 10} 11 12type User { 13 id: ID! 14 email: String! 15 name: String 16 posts(first: Int, after: String): PostConnection! 17 createdAt: DateTime! 18} 19 20type UserConnection { 21 edges: [UserEdge!]! 22 pageInfo: PageInfo! 23 totalCount: Int! 24} 25 26type UserEdge { 27 node: User! 28 cursor: String! 29} 30 31input UserFilter { 32 search: String 33 status: UserStatus 34} 35 36input CreateUserInput { 37 email: String! 38 name: String 39 password: String! 40} 41 42type CreateUserPayload { 43 user: User 44 errors: [Error!] 45}

Resolver Patterns#

1const resolvers = { 2 Query: { 3 user: (_, { id }, context) => { 4 return context.dataSources.users.findById(id); 5 }, 6 users: async (_, { filter, pagination }, context) => { 7 return context.dataSources.users.findMany({ 8 ...filter, 9 ...pagination, 10 }); 11 }, 12 }, 13 14 User: { 15 // Field-level resolver with DataLoader 16 posts: (user, args, context) => { 17 return context.loaders.postsByUser.load(user.id); 18 }, 19 }, 20 21 Mutation: { 22 createUser: async (_, { input }, context) => { 23 try { 24 const user = await context.dataSources.users.create(input); 25 return { user, errors: null }; 26 } catch (error) { 27 return { user: null, errors: [formatError(error)] }; 28 } 29 }, 30 }, 31};

tRPC Patterns#

1import { initTRPC } from '@trpc/server'; 2import { z } from 'zod'; 3 4const t = initTRPC.context<Context>().create(); 5 6export const appRouter = t.router({ 7 user: t.router({ 8 list: t.procedure 9 .input(z.object({ 10 page: z.number().default(1), 11 perPage: z.number().default(20), 12 })) 13 .query(async ({ input, ctx }) => { 14 return ctx.prisma.user.findMany({ 15 skip: (input.page - 1) * input.perPage, 16 take: input.perPage, 17 }); 18 }), 19 20 create: t.procedure 21 .input(z.object({ 22 email: z.string().email(), 23 name: z.string().optional(), 24 })) 25 .mutation(async ({ input, ctx }) => { 26 return ctx.prisma.user.create({ data: input }); 27 }), 28 }), 29});

API Versioning#

1// URL versioning 2app.use('/api/v1', v1Router); 3app.use('/api/v2', v2Router); 4 5// Header versioning 6app.use((req, res, next) => { 7 const version = req.headers['api-version'] || 'v1'; 8 req.apiVersion = version; 9 next(); 10}); 11 12// Deprecation headers 13res.set('Deprecation', 'true'); 14res.set('Sunset', 'Sat, 31 Dec 2024 23:59:59 GMT'); 15res.set('Link', '</api/v2/users>; rel="successor-version"');

Sample Prompts#

TaskPrompt
Design"Design a REST API for a booking system"
GraphQL"Convert this REST API to GraphQL"
Documentation"Generate OpenAPI spec from this Express app"
Versioning"Plan API versioning strategy with deprecation"
Errors"Implement RFC 7807 error responses"

Configuration#

1// bootspring.config.js 2module.exports = { 3 agents: { 4 customInstructions: { 5 'api-expert': ` 6 - Follow REST best practices 7 - Use appropriate HTTP status codes 8 - Include comprehensive documentation 9 - Plan for versioning 10 - Consider rate limiting 11 `, 12 }, 13 }, 14 skills: { 15 preferred: { 16 api: 'rest', // or 'graphql', 'trpc' 17 }, 18 }, 19};