Skip to main content

API Routes

Overview

API Routes (app/api/**/route.ts) are used for:

  1. External service integration (Directus, Redis)
  2. Proxy endpoints (keeping credentials server-side)
  3. Special operations (invitations, webhooks)

Implementation Pattern

// app/api/essearch/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createDirectus, rest, authentication } from "@directus/sdk";

export async function POST(req: NextRequest) {
try {
const body = await req.json();
const { firstName, lastName, ... } = body.params;

// Authenticate with Directus
const client = createDirectus(directusUrl)
.with(authentication("json"))
.with(rest());

await client.login(email, password);
const token = await client.getToken();

// Call external service
const response = await fetch(`${directusUrl}/essearch/validation`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ firstName, lastName, ... }),
});

const data = await response.json();
return NextResponse.json({
persons: data.hits || [],
totalHits: data.total?.value,
});
} catch (error) {
return NextResponse.json(
{ error: error.message },
{ status: 500 }
);
}
}

API Route Categories

1. Voter Search APIs

/api/essearch - Dynamic credentials

  • Accepts credentials in request body
  • Uses environment variables based on emailKey, passwordKey, endpointKey
  • Token caching in HTTP-only cookies

/api/essearch-common - Fixed credentials

  • Uses DIRECTUS_API_EMAIL_SEARCH, DIRECTUS_API_PASSWORD_SEARCH, DIRECTUS_URL_SEARCH
  • Simpler for common search operations

2. Duplicate Detection API

/api/duplicate

// app/api/duplicate/route.ts
export async function POST(req: NextRequest) {
const { campaignId, voterId } = await req.json();

const client = await getRedisConnection();
const exists = await client.sIsMember(
`campaign:${campaignId}:signers`,
voterId
);

return NextResponse.json({ exists: Boolean(exists) });
}

Features:

  • Redis set membership check
  • Fast duplicate detection
  • Connection pooling and error handling

3. Team Invitation API

/api/invite-team-member

  • Uses Supabase service role key
  • Creates user invitation
  • Invokes Supabase Edge Function for email

API Route vs Server Action

FeatureAPI RouteServer Action
URL/api/endpointNo URL (direct function call)
Use CaseExternal services, webhooksForm mutations, CRUD
Callingfetch('/api/endpoint')Direct function import
Type SafetyManual typingFull TypeScript support
Form IntegrationRequires form handlingDirect form action