280 lines
6.8 KiB
Markdown
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" });
|
|
}
|
|
```
|