Skip to main content

API Authentication Enforcement

Every API endpoint follows a strict authentication and authorization pattern.

Auth Matrix

EndpointAuth LevelToken CostNotes
GET /api/track-pixelNoneNonePublic tracking pixel
GET /api/blog-ogNoneNonePublic OG image
POST /api/generateUserai_generationMain RAG pipeline
POST /api/generate-emailUserai_generationSimple generation
POST /api/send-emailUseremail_sendResend delivery
POST /api/send-email-sesUseremail_sendSES delivery
POST /api/validate-ampUserNoneAMP validation
GET /api/resend-statusUserNoneDelivery status
POST /api/admin/*AdminNoneRAG management
GET /api/admin/*AdminNoneAdmin data

Enforcement Pattern

Every protected endpoint follows this pattern at the top of the handler:

export default async function handler(req, res) {
// 1. Method check
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}

// 2. Auth verification
const user = await verifyUser(req, res);
if (!user) return; // 401 already sent

// 3. Token spending (if applicable)
const tokenResult = await spendTokensServer(req, res, 'ai_generation');
if (!tokenResult) return; // 402 already sent

// 4. Input validation
const { prompt } = req.body;
if (!prompt) {
return res.status(400).json({ error: 'Prompt is required' });
}

// 5. Business logic...
}

Auth Modules

Two auth modules exist for historical reasons (TypeScript vs JavaScript routes):

ModuleLanguageFunctions
api/_auth.tsTypeScriptverifyUser, verifyAdmin, spendTokensServer, setCorsHeaders
api/admin/_auth.jsJavaScriptSame functions (JS implementation)

Both implement identical logic. The JS version is used by generate.js and all api/admin/*.js routes.

Token Spending Security

Token deduction is server-side only. The flow:

  1. Frontend calls checkCanAfford() — read-only, no deduction
  2. Frontend executes the API call if affordable
  3. Server calls spendTokensServer() — atomic deduction via spend_tokens RPC
  4. Frontend calls refreshBalance() to sync UI

This ensures users cannot bypass token costs by calling APIs directly (e.g., via curl).