Next Starter Kit
API Reference

API Reference

Complete reference for all API endpoints

API Reference

Complete reference for all API endpoints in the starter kit.

Base URL

Development: http://localhost:3000/api
Production: https://yourdomain.com/api

Authentication

Most API routes require authentication. Include credentials in requests:

// Client-side (automatic with fetch from same origin)
const response = await fetch("/api/protected-route");

// Server-side
import { auth } from "@/lib/auth";

const session = await auth.api.getSession({
  headers: request.headers,
});

Response Format

All responses follow this format:

// Success
{
  data: T,  // Response data
  success: true
}

// Error
{
  error: string,  // Error message
  success: false
}

Rate Limiting

Rate limits apply to sensitive endpoints:

EndpointLimit
/api/auth/*5 requests / 15 min
/api/contact3 requests / 15 min
General API100 requests / 15 min

Authentication Endpoints

Sign In

POST /api/auth/sign-in

Headers:

Content-Type: application/json

Body:

{
  "email": "user@example.com",
  "password": "password123"
}

Response (200):

{
  "session": {
    "token": "...",
    "user": {
      "id": "...",
      "email": "user@example.com",
      "name": "John Doe",
      "role": "user"
    }
  }
}

Sign Up

POST /api/auth/sign-up

Body:

{
  "email": "newuser@example.com",
  "password": "securepassword",
  "name": "New User"
}

Response (201):

{
  "user": {
    "id": "...",
    "email": "newuser@example.com",
    "emailVerified": false
  },
  "message": "Verification email sent"
}

Sign Out

POST /api/auth/sign-out

Response (200):

{
  "success": true
}

Blog Endpoints

Get All Posts

GET /api/blog

Query Parameters:

  • page (number): Page number (default: 1)
  • limit (number): Items per page (default: 10)
  • category (string): Filter by category slug
  • tag (string): Filter by tag slug
  • search (string): Search in title/content
  • status (string): published or draft (admin only)

Response (200):

{
  "posts": [
    {
      "id": 1,
      "title": "My Post",
      "slug": "my-post",
      "excerpt": "Short summary...",
      "content": "Full content...",
      "featuredImage": "https://...",
      "published": true,
      "publishedAt": "2024-01-01T00:00:00Z",
      "viewCount": 100,
      "likeCount": 10,
      "author": {
        "id": "...",
        "name": "Author Name",
        "image": "https://..."
      },
      "categories": [...],
      "tags": [...]
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 50,
    "totalPages": 5
  }
}

Get Single Post

GET /api/blog/{slug}

Response (200):

{
  "post": {
    "id": 1,
    "title": "My Post",
    "slug": "my-post",
    "content": "...",
    "author": {...},
    "categories": [...],
    "tags": [...]
  }
}

Create Post (Admin)

POST /api/blog

Headers:

Authorization: Required (admin role)
Content-Type: application/json

Body:

{
  "title": "New Post",
  "slug": "new-post",
  "content": "Post content...",
  "excerpt": "Short summary...",
  "featuredImage": "https://...",
  "categoryIds": [1, 2],
  "tagIds": [1, 2, 3],
  "published": false,
  "seoTitle": "SEO Title",
  "seoDescription": "SEO Description"
}

Response (201):

{
  "post": {
    "id": 1,
    "title": "New Post",
    "slug": "new-post",
    ...
  }
}

Update Post (Admin)

PUT /api/blog/{id}

Body: Same as create

Response (200): Updated post

Delete Post (Admin)

DELETE /api/blog/{id}

Response (200):

{
  "success": true,
  "message": "Post deleted"
}

Like Post

POST /api/blog/{id}/like

Response (200):

{
  "liked": true,
  "likeCount": 11
}

Subscription Endpoints

Create Checkout Session

POST /api/subscription/checkout

Body:

{
  "priceId": "price_xxxxx",
  "billingCycle": "monthly"
}

Response (200):

{
  "url": "https://checkout.stripe.com/..."
}

Create Portal Session

POST /api/subscription/portal

Response (200):

{
  "url": "https://billing.stripe.com/..."
}

Get User Subscription

GET /api/subscription

Response (200):

{
  "subscription": {
    "id": "...",
    "status": "active",
    "plan": {
      "name": "Pro",
      "priceMonthly": 1999
    },
    "currentPeriodEnd": "2024-02-01T00:00:00Z"
  }
}

User Endpoints

Get Current User

GET /api/me

Response (200):

{
  "user": {
    "id": "...",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "user",
    "subscription": {...}
  }
}

Update Profile

PUT /api/me

Body:

{
  "name": "New Name",
  "image": "https://..."
}

Response (200):

{
  "user": {
    "id": "...",
    "name": "New Name",
    ...
  }
}

Admin Endpoints

Get All Users (Admin)

GET /api/admin/users

Query Parameters:

  • page, limit, search, role

Response (200):

{
  "users": [...],
  "pagination": {...}
}

Promote User (Admin)

POST /api/admin/users/promote

Body:

{
  "userId": "user_123"
}

Response (200):

{
  "success": true,
  "user": {
    "id": "user_123",
    "role": "admin"
  }
}

Ban User (Admin)

POST /api/admin/users/ban

Body:

{
  "userId": "user_123",
  "reason": "Violation of terms",
  "expires": "2024-12-31T00:00:00Z"
}

Contact Endpoints

Submit Contact Form

POST /api/contact

Body:

{
  "fullName": "John Doe",
  "email": "john@example.com",
  "phone": "+1234567890",
  "company": "Acme Inc",
  "subject": "Inquiry",
  "message": "Hello..."
}

Response (200):

{
  "success": true,
  "message": "Message sent successfully"
}

Get Submissions (Admin)

GET /api/admin/contact-submissions

File Upload Endpoints

Handled by UploadThing. See File Uploads for details.

POST /api/uploadthing

Waitlist Endpoints

Join Waitlist

POST /api/waitlist

Body:

{
  "email": "user@example.com",
  "name": "John Doe"
}

Stripe Webhook

POST /api/stripe/webhook

Headers:

Stripe-Signature: ...

Body: Stripe event payload

Error Codes

CodeMeaning
200Success
201Created
400Bad Request
401Unauthorized
403Forbidden
404Not Found
429Too Many Requests
500Internal Server Error

Example Usage

Fetch Blog Posts

const response = await fetch("/api/blog?page=1&limit=10");
const { posts, pagination } = await response.json();

Create Blog Post (Admin)

const response = await fetch("/api/blog", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "New Post",
    content: "...",
    published: false,
  }),
});

const { post } = await response.json();

Handle Errors

const response = await fetch("/api/blog");

if (!response.ok) {
  const error = await response.json();
  throw new Error(error.error || "Request failed");
}

const data = await response.json();

Rate Limit Headers

Responses include rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1640000000

Next Steps

On this page