Documentation

REST API

Comprehensive REST API with 50+ documented endpoints, OpenAPI specification, and Swagger UI.

Overview

The AI SaaS Starter Kit provides a complete REST API for managing users, blogs, categories, subscriptions, and payments. All endpoints are documented with Swagger/OpenAPI and include authentication, validation, and error handling.

Interactive API Documentation

Explore and test all API endpoints with Swagger UI

Open Swagger UI →

Authentication

Session-Based Auth

The API uses NextAuth session cookies for authentication:

// Sign in first
POST /api/auth/signin

// Session cookie is automatically set
// Subsequent requests include the cookie automatically

Making Authenticated Requests

fetch('/api/users', {
  credentials: 'include', // Include session cookie
  headers: {
    'Content-Type': 'application/json',
  },
})

API Endpoints

Authentication

POST/api/auth/register

Register a new user with email and password

GET/api/auth/session

Get current user session

Users

GET/api/users

List all users (Admin only, with pagination and search)

POST/api/users

Create a new user (Admin only)

GET/api/users/:id

Get user details by ID

PUT/api/users/:id

Update user details

DELETE/api/users/:id

Delete a user

POST/api/users/:id/roles

Assign role to user (Super Admin only)

DELETE/api/users/:id/roles

Remove role from user (Super Admin only)

Blogs

GET/api/blogs

List all blog posts (public: published only)

POST/api/blogs

Create a new blog post (Admin only)

GET/api/blogs/:id

Get blog post by ID or slug

PUT/api/blogs/:id

Update blog post (Admin only)

DELETE/api/blogs/:id

Delete blog post (Admin only)

Categories

GET/api/categories

List all categories (public)

POST/api/categories

Create a new category (Admin only)

GET/api/categories/:id

Get category by ID or slug

PUT/api/categories/:id

Update category (Admin only)

DELETE/api/categories/:id

Delete category (Admin only, if no posts)

Subscriptions

GET/api/subscriptions

List subscriptions (own or all for admin)

GET/api/subscriptions/:id

Get subscription details

DELETE/api/subscriptions/:id

Cancel subscription

Payments

GET/api/payments

List payments (own or all for admin)

GET/api/payments/:id

Get payment details

Plans

GET/api/plans

List all subscription plans (public)

Request/Response Format

Example Request

// Create a blog post
POST /api/blogs
Content-Type: application/json

{
  "title": "Getting Started with Next.js 15",
  "slug": "getting-started-nextjs-15",
  "content": "Next.js 15 brings exciting new features...",
  "excerpt": "A comprehensive guide to Next.js 15",
  "featuredImage": "https://example.com/image.jpg",
  "published": true,
  "categoryIds": ["clx123..."]
}

Success Response

HTTP/1.1 201 Created
Content-Type: application/json

{
  "message": "Blog post created successfully",
  "blog": {
    "id": "clx456...",
    "title": "Getting Started with Next.js 15",
    "slug": "getting-started-nextjs-15"
  }
}

Error Response

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "A blog post with this slug already exists"
}

Pagination

List endpoints support pagination with query parameters:

GET /api/users?page=1&perPage=10

// Response
{
  "users": [...],
  "pagination": {
    "total": 42,
    "page": 1,
    "perPage": 10,
    "totalPages": 5
  }
}

Query Parameters

  • page - Page number (default: 1)
  • perPage - Items per page (default: 10, max: 100)
  • search - Search query
  • filter - Filter by specific fields

Filtering

// Filter users by role
GET /api/users?role=ADMIN

// Filter blogs by category
GET /api/blogs?category=clx123...

// Filter subscriptions by status
GET /api/subscriptions?status=active

// Combine filters
GET /api/payments?userId=clx456...&status=succeeded

Searching

// Search users by name or email
GET /api/users?search=john

// Search blogs by title or content
GET /api/blogs?search=nextjs

// Search categories by name
GET /api/categories?search=technology

Error Codes

CodeMeaning
200Success
201Created
400Bad Request (validation error)
401Unauthorized (not signed in)
403Forbidden (insufficient permissions)
404Not Found
500Internal Server Error

Rate Limiting

Consider implementing rate limiting for production:

// Example with upstash/ratelimit
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "10 s"),
});

// In API route
const { success } = await ratelimit.limit(userId);
if (!success) {
  return NextResponse.json(
    { error: "Rate limit exceeded" },
    { status: 429 }
  );
}

CORS

If you need to allow cross-origin requests:

// Add to API route
export async function GET(req: Request) {
  const headers = new Headers();
  headers.set("Access-Control-Allow-Origin", "*");
  headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
  headers.set("Access-Control-Allow-Headers", "Content-Type");

  // Your response
  return NextResponse.json(data, { headers });
}

Webhook Security

Stripe webhooks include signature verification:

// POST /api/webhooks/stripe
const signature = req.headers.get("stripe-signature");

const event = stripe.webhooks.constructEvent(
  body,
  signature!,
  process.env.STRIPE_WEBHOOK_SECRET!
);

Best Practices

  • Always validate input with Zod schemas
  • Use proper HTTP status codes
  • Implement authentication checks first
  • Return consistent error formats
  • Log all errors for debugging
  • Use database transactions for multiple operations
  • Implement idempotency for critical operations

Testing APIs

With cURL

curl -X POST http://localhost:3000/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"name":"John Doe","email":"john@example.com","password":"password123"}'

With JavaScript

const response = await fetch('/api/blogs', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    title: 'My Blog Post',
    slug: 'my-blog-post',
    content: 'Content here...',
    published: true,
  }),
});

const data = await response.json();

OpenAPI Specification

The complete OpenAPI/Swagger specification is automatically generated from JSDoc comments and available at:

  • /api-docs - Interactive Swagger UI
  • /api/swagger - JSON specification

You can import the spec into tools like Postman or Insomnia for API testing.