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

280 lines
6.8 KiB
Markdown

# 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:**
```typescript
{
fileName: string
fileUrl: string
fileSize: number
mimeType: string
}
```
**Returns:**
```typescript
{ 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:**
```typescript
{
status?: ContractStatus
type?: ContractType
search?: string // searches title, provider, policyNumber, fileName
}
```
**Returns:**
```typescript
{
success: true,
contracts: SerializedContract[]
}
```
**Serialization:** `Decimal``number`, `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:**
```typescript
{ 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:**
```typescript
id: string // contract ID
question: string // user's question
```
**Returns:**
```typescript
{ 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:**
```typescript
{
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:**
```typescript
{
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`:
```typescript
export async function GET() {
return Response.json({ status: "ok" });
}
```