Final Push
This commit is contained in:
279
docs/04-api-reference.md
Normal file
279
docs/04-api-reference.md
Normal file
@@ -0,0 +1,279 @@
|
||||
# 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" });
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user