All API routes are located in /app/api/ and follow RESTful conventions.
Most endpoints require authentication via NextAuth session.
// Headers required
{
"Cookie": "next-auth.session-token=..."
}- Development:
http://localhost:3000/api - Production:
https://your-domain.com/api
NextAuth.js authentication endpoint
Auth Required: No
Handles:
POST /api/auth/signin- Sign inPOST /api/auth/signout- Sign outPOST /api/auth/callback/*- OAuth callbacksGET /api/auth/session- Get sessionGET /api/auth/csrf- Get CSRF token
Provider Callbacks:
/api/auth/callback/google- Google OAuth/api/auth/callback/github- GitHub OAuth/api/auth/callback/credentials- Email/Password
Handle Stripe webhook events
Auth Required: No (Stripe signature verification)
Events Handled:
checkout.session.completed- Payment completedpayment_intent.succeeded- Payment successfulpayment_intent.failed- Payment failed
Request Headers:
stripe-signature: <signature>
Webhook Flow:
- Verify Stripe signature
- Parse event
- Handle event type
- Update database (add credits, create purchase record)
- Send confirmation email
- Return 200 OK
Example Event (checkout.session.completed):
{
"id": "evt_xxx",
"type": "checkout.session.completed",
"data": {
"object": {
"id": "cs_xxx",
"customer": "cus_xxx",
"amount_total": 1400,
"metadata": {
"userId": "user_xxx",
"credits": "75"
}
}
}
}Response:
{
"received": true
}Send email (internal use)
Auth Required: Yes (Admin only)
Request Body:
{
"to": "user@example.com",
"subject": "Email Subject",
"template": "verification",
"data": {
"name": "John",
"link": "https://..."
}
}Response:
{
"success": true,
"messageId": "msg_xxx"
}List all users (Admin only)
Auth Required: Yes (Admin)
Query Parameters:
page(number, optional): Page number (default: 1)limit(number, optional): Items per page (default: 20)search(string, optional): Search by name/email
Response:
{
"data": [
{
"id": "user_id",
"name": "John Doe",
"email": "john@example.com",
"role": "USER",
"createdAt": "2024-01-01T00:00:00.000Z"
}
],
"pagination": {
"total": 100,
"page": 1,
"pages": 5
}
}Get platform statistics (Admin only)
Auth Required: Yes (Admin)
Response:
{
"data": {
"totalUsers": 1000,
"activeUsers": 750,
"totalRevenue": 50000,
"totalCreditsIssued": 100000
}
}All errors follow this structure:
{
"error": "Error message",
"code": "ERROR_CODE",
"details": { /* optional */ }
}Status Codes:
200- Success201- Created400- Bad Request401- Unauthorized403- Forbidden404- Not Found500- Server Error
- Standard: 100 requests per 15 minutes per IP
- Authentication: 5 failed attempts per 15 minutes
- Webhooks: No limit (but signature verified)
Template for new API routes:
// /app/api/new-endpoint/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
export async function GET(req: NextRequest) {
const session = await auth()
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Implementation
return NextResponse.json({ data })
}Add documentation here after creating new endpoints.
SaaSPilot primarily uses Server Actions instead of API routes for most operations. Server Actions are located in /actions/.
Register a new user
import { register } from '@/actions/register'
const result = await register({
name: "John Doe",
email: "john@example.com",
password: "password123"
})Login user
import { login } from '@/actions/login'
const result = await login({
email: "john@example.com",
password: "password123"
})Create Stripe checkout session
import { createStripeSession } from '@/actions/createStripeSession'
const result = await createStripeSession({
priceId: "price_xxx",
credits: 75
})
// Returns: { url: "https://checkout.stripe.com/..." }Update user settings
import { updateSettings } from '@/actions/settings'
const result = await updateSettings({
name: "New Name",
email: "newemail@example.com"
})# Get session
curl http://localhost:3000/api/auth/session \
-H "Cookie: next-auth.session-token=xxx"
# Test webhook (with signature)
curl -X POST http://localhost:3000/api/webhooks/stripe \
-H "stripe-signature: xxx" \
-H "Content-Type: application/json" \
-d '{"type":"checkout.session.completed",...}'# Forward webhooks to local server
stripe listen --forward-to localhost:3000/api/webhooks/stripe
# Trigger test events
stripe trigger checkout.session.completed- Always validate authentication
- Use Zod for input validation
- Sanitize user inputs
- Rate limit sensitive endpoints
- Use HTTPS in production
- Verify signatures
- Use idempotency keys
- Handle duplicate events
- Log all webhook events
- Always check authentication
- Validate all inputs
- Use transactions for multi-step operations
- Return user-friendly error messages