# Create API Endpoint ## Task Overview Create a new API endpoint in Next.js with proper TypeScript typing, validation, and error handling. ## Prerequisites - Next.js project with App Router - TypeScript configured - Understanding of HTTP methods and status codes ## Steps ### 1. Create API Route File Create `src/app/api/{endpoint}/route.ts`: ```typescript import { NextRequest, NextResponse } from 'next/server'; // Define request/response types interface RequestBody { // Define your request body structure } interface ResponseData { // Define your response structure } export async function GET(request: NextRequest) { try { // Handle GET request logic const data: ResponseData = { // Your response data }; return NextResponse.json(data, { status: 200 }); } catch (error) { console.error('API Error:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } } export async function POST(request: NextRequest) { try { const body: RequestBody = await request.json(); // Validate request body if (!body) { return NextResponse.json({ error: 'Request body is required' }, { status: 400 }); } // Handle POST request logic const data: ResponseData = { // Your response data }; return NextResponse.json(data, { status: 201 }); } catch (error) { console.error('API Error:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } } ``` ### 2. Add Request Validation (Optional) Install and use Zod for validation: ```bash npm install zod ``` ```typescript import { z } from 'zod'; const requestSchema = z.object({ name: z.string().min(1), email: z.string().email(), }); export async function POST(request: NextRequest) { try { const body = await request.json(); const validatedData = requestSchema.parse(body); // Use validatedData safely } catch (error) { if (error instanceof z.ZodError) { return NextResponse.json( { error: 'Invalid request data', details: error.errors }, { status: 400 }, ); } // Handle other errors } } ``` ### 3. Create API Client Helper Create `src/lib/api-client.ts`: ```typescript class ApiError extends Error { constructor( public status: number, message: string, ) { super(message); this.name = 'ApiError'; } } export async function apiCall(url: string, options?: RequestInit): Promise { const response = await fetch(url, { headers: { 'Content-Type': 'application/json', ...options?.headers, }, ...options, }); if (!response.ok) { throw new ApiError(response.status, `HTTP error! status: ${response.status}`); } return response.json(); } ``` ### 4. Use in Components ```typescript 'use client' import { useState } from 'react' import { apiCall } from '@/lib/api-client' export function ExampleComponent() { const [loading, setLoading] = useState(false) const [data, setData] = useState(null) const handleSubmit = async () => { setLoading(true) try { const result = await apiCall('/api/example', { method: 'POST', body: JSON.stringify({ /* your data */ }), }) setData(result) } catch (error) { console.error('Error:', error) } finally { setLoading(false) } } return ( // Your component JSX ) } ``` ## Validation Checklist - [ ] API route file created in correct location - [ ] Proper TypeScript types defined - [ ] Error handling implemented - [ ] Request validation added (if needed) - [ ] API tested with different HTTP methods - [ ] Client-side integration working - [ ] Error cases handled gracefully ## Best Practices - Use proper HTTP status codes - Implement consistent error response format - Add request validation for security - Log errors for debugging - Consider rate limiting for production - Document API endpoints