Skip to content

API Routes Guide

How Next.js API Routes Work

Next.js App Router uses Route Handlers — files named route.ts inside the app/api/ directory. Each file can export functions for different HTTP methods: GET, POST, PUT, PATCH, DELETE.

app/
  api/
    health/
      route.ts    →  GET /api/health
    drafts/
      route.ts    →  GET /api/drafts, POST /api/drafts
      [id]/
        route.ts  →  GET /api/drafts/:id, PATCH /api/drafts/:id, DELETE /api/drafts/:id
    uploads/
      presign/
        route.ts  →  POST /api/uploads/presign

HTTP Method Handlers

typescript
// app/api/drafts/route.ts
import { NextRequest, NextResponse } from 'next/server';

// GET — Retrieve data
export async function GET() {
  return NextResponse.json({ data: [] }, { status: 200 });
}

// POST — Create data
export async function POST(request: NextRequest) {
  const body = await request.json();
  return NextResponse.json({ data: body }, { status: 201 });
}

TypeScript Typing

Define types for your request and response data:

typescript
interface CreateUserRequest {
  name: string;
  email: string;
}

interface UserResponse {
  id: string;
  name: string;
  email: string;
  createdAt: string;
}

export async function POST(request: NextRequest) {
  const body: CreateUserRequest = await request.json();

  const user: UserResponse = {
    id: crypto.randomUUID(),
    name: body.name,
    email: body.email,
    createdAt: new Date().toISOString(),
  };

  return NextResponse.json(user, { status: 201 });
}

Error Handling

Always wrap your route handlers in try/catch and return appropriate status codes:

typescript
export async function GET() {
  try {
    const data = await fetchData();
    return NextResponse.json(data, { status: 200 });
  } catch (error) {
    console.error('Error fetching data:', error);
    return NextResponse.json(
      { error: 'Internal Server Error', message: 'Failed to fetch data' },
      { status: 500 }
    );
  }
}

Common HTTP Status Codes

CodeMeaningWhen to Use
200OKSuccessful GET, PUT, PATCH, DELETE
201CreatedSuccessful POST (new resource created)
400Bad RequestInvalid input / validation failure
401UnauthorizedNot logged in
403ForbiddenLogged in but insufficient permissions
404Not FoundResource doesn't exist
500Internal Server ErrorSomething went wrong on the server

Adding a New Route

  1. Create a new directory under app/api/: app/api/your-route/
  2. Create route.ts inside it
  3. Export the HTTP method handlers you need
  4. Add TypeScript types for your request/response data
  5. Add error handling with try/catch

Server Actions (Alternative)

Next.js also supports Server Actions — functions that run on the server and can be called directly from Client Components without creating an API endpoint:

typescript
// app/actions.ts
'use server';

export async function createUser(formData: FormData) {
  const name = formData.get('name') as string;
  // Insert into database...
  return { success: true };
}
tsx
// In a Client Component
<form action={createUser}>
  <input name="name" />
  <button type="submit">Create</button>
</form>

Server Actions are great for form submissions and mutations. Use API routes when you need a traditional REST API.

Routes in This Project

VideoSphere uses route handlers under app/api/. Common entry points:

MethodRoutePurpose
GET/api/healthHealth check
POST/api/draftsCreate a draft
GET/api/draftsList drafts
PATCH/api/drafts/[id]Update draft metadata
POST/api/uploads/presignGet presigned R2 upload URL
POST/api/uploads/[jobId]/completeConfirm R2 upload
POST/api/uploads/distributeStart platform distribution
POST/api/ai/generate-metadataGenerate title, description, tags

See app/api/README.md in the repository for route domains. Run pnpm docs:api for full TypeDoc output.

Useful Resources