Files
LexiChain/docs/04-api-reference.md
2026-05-13 21:08:27 +01:00

6.8 KiB

04 — API Reference

This document covers all Next.js route handlers (app/api/) and key server actions (features/*/api/).

Authentication: All protected endpoints require a valid Clerk session. Unauthenticated requests receive a 401 Unauthorized response. Route-level protection is enforced by proxy.ts (Clerk middleware).


Route Handlers (app/api/)

POST /api/uploadthing

File: app/api/uploadthing/route.ts
Purpose: UploadThing file upload endpoint. Handles authenticated file uploads and triggers contract creation.

Constraints:

  • Max file size: 32 MB
  • Accepted types: application/pdf, image/jpeg, image/png, image/webp
  • Authentication: Clerk session required

Flow:

  1. UploadThing middleware validates the session via Clerk
  2. File is stored on UploadThing CDN
  3. On completion, returns { fileUrl, fileName, fileSize, mimeType } to the client

POST /api/webhooks/clerk

File: app/api/webhooks/clerk/route.ts
Purpose: Receives Clerk lifecycle events and syncs user data to PostgreSQL.

Verification: Request signature verified via Svix + CLERK_WEBHOOK_SECRET

Handled Events:

Event Action
user.created Creates a new User record in PostgreSQL
user.updated Updates email, firstName, lastName, imageUrl
user.deleted Deletes User record (cascades to contracts, notifications)

Response: 200 OK on success, 400 Bad Request if signature invalid.


GET /api/contracts/[id]/download

File: app/api/contracts/[id]/download/route.ts
Purpose: Proxies contract file download through the server (adds auth check before serving).

Authentication: Clerk session + ownership validation
Response: File stream with appropriate Content-Type and Content-Disposition headers.


Server Actions (features/contracts/api/contract.action.ts)

All server actions are decorated with "use server" and perform double authentication (Clerk session + DB ownership check).


saveContract(data)

Saves a new contract after UploadThing upload, then automatically triggers AI analysis.

Parameters:

{
  fileName: string
  fileUrl: string
  fileSize: number
  mimeType: string
}

Returns:

{ success: true, contract: Contract } |
{ success: true, contract: Contract, analysisSuccess: false, analysisError: string } |
{ success: false, error: string }

Side effects:

  • Creates Contract record (status: UPLOADED)
  • Creates in-app notification (upload success)
  • Triggers analyzeContractAction() automatically
  • Revalidates /contacts and /dashboard

getContracts(filters?)

Returns all contracts for the authenticated user with optional filtering.

Parameters:

{
  status?: ContractStatus
  type?: ContractType
  search?: string    // searches title, provider, policyNumber, fileName
}

Returns:

{
  success: true,
  contracts: SerializedContract[]
}

Serialization: Decimalnumber, Date → ISO string


getContract(id)

Returns a single contract by ID.

Parameters: id: string (contract ID)

Returns: { success: true, contract: Contract } | { success: false, error: string }


deleteContract(id)

Permanently deletes a contract (ownership validated, cascades to RAG chunks and notifications).

Returns: { success: true } | { success: false, error: string }

Side effects:

  • Deletes file from UploadThing CDN
  • Cascades delete to ContractRagChunk, Notification, BlockchainTransaction
  • Creates in-app notification (delete success)
  • Revalidates /contacts and /dashboard

deleteAllContractsAction()

Deletes all contracts for the authenticated user.

Returns: { success: true, deletedCount: number } | { success: false, error: string }


analyzeContractAction(id)

Triggers the full AI analysis pipeline for a contract.

Parameters: id: string (contract ID)

Returns:

{ success: true, contract: NormalizedAnalysis } |
{
  success: false,
  error: string,
  errorCode: "INVALID_CONTRACT" | "ANALYSIS_ERROR"
}

Pipeline:

  1. Set status → PROCESSING
  2. Run AI extraction (Gemini → Mistral fallback)
  3. Validate AI output
  4. Save extracted fields to DB
  5. Build RAG chunks (embeddings)
  6. Register document hash on blockchain (non-blocking)
  7. Send analysis complete email (non-blocking)
  8. Create in-app notification
  9. Set status → COMPLETED

Error codes:

  • INVALID_CONTRACT — uploaded file is not a recognized contract document
  • ANALYSIS_ERROR — analysis pipeline failed (AI error, parse error, etc.)

askContractQuestionAction(id, question)

Answers a natural-language question about a specific contract using RAG + AI.

Parameters:

id: string        // contract ID
question: string  // user's question

Returns:

{ success: true, answer: string } |
{ success: false, error: string }

Pipeline:

  1. Load contract from DB
  2. RAGService retrieves top-6 most relevant chunks
  3. AIService sends question + contract context + RAG chunks to Gemini
  4. Sanitized answer returned to UI

getContractStats()

Returns analytics data for the dashboard.

Returns:

{
  success: true,
  stats: {
    total: number
    byStatus: Record<ContractStatus, number>
    byType: Record<ContractType, number>
    byMonth: Array<{ month: string, count: number }>
    expiringSoon: number
    averagePremium: number | null
    blockchainCoverage: number  // percentage
  }
}

Notification Server Actions

File: features/notifications/api/ (or lib/services/notification.service.ts)

getNotificationsAction()

Returns all unread (and recent read) notifications for the user.

markNotificationReadAction(id)

Marks a single notification as read.

markAllNotificationsReadAction()

Marks all notifications as read.

deleteNotificationAction(id)

Deletes a single notification.


Blockchain Server Actions

File: features/blockchain/api/

getBlockchainStatsAction()

Returns network stats: total verified docs, block number, network name, connection status.

verifyDocumentAction(documentHash)

Verifies whether a given SHA-256 hash is registered on-chain.

Returns:

{
  exists: boolean
  timestamp: number      // Unix timestamp
  depositor: string      // Ethereum address
  formattedDate: string  // Human-readable date
}

Health Check Endpoint

The Dockerfile HEALTHCHECK calls:

GET /api/health

This route should return 200 OK with { status: "ok" }.
If this route does not exist, create it at app/api/health/route.ts:

export async function GET() {
  return Response.json({ status: "ok" });
}