OCR text & AI summary — API contract (web → backend)
This document describes the HTTP endpoints the RedactStripe web app (apps/web) expects for OCR extracted text and AI document summary. Implement these on your API gateway or service behind VITE_API_URL.
Client: all calls use apiRequest() (apps/web/src/api/client.js):
- Base URL:
import.meta.env.VITE_API_URL(seeresolveApiFetchUrlfor how paths join the base). - Headers:
Content-Type: application/json;Authorization: Bearer <token>when the user has a stored session token. - Successful responses: JSON body; errors: non-2xx with JSON preferably including
errorormessage(surfaced in the UI).
Source files (frontend):
- OCR:
apps/web/src/features/pdf-redaction/api/ocrApi.js, hookhooks/useOcrText.js - AI summary:
apps/web/src/features/pdf-redaction/api/aiSummaryApi.js, hookhooks/useAiSummary.js
AI summary
Used by the AI Summary sidebar: load the latest saved summary when the panel opens; regenerate on button click.
| Method | Path | Description |
|---|---|---|
GET | /ai-summary/latest | Return the latest stored summary for the document. |
POST | /ai-summary/generate | Create or regenerate a summary (sync or async—see notes). |
GET /ai-summary/latest
Query parameters
| Name | Type | Description |
|---|---|---|
doc_id | string | Document identifier (same as navigation/state docId). |
user_id | string | Authenticated user id (numeric or string per your auth model). |
Response (frontend parsing)
The UI reads summary text from either:
response.summary, orresponse.data.summary
Empty or missing summary → sidebar shows “No summary available yet.”
Errors: Any non-2xx sets the sidebar error state from error / message in the JSON body.
POST /ai-summary/generate
JSON body
{
"doc_id": "<document id>",
"user_id": "<user id>"
}
Response
Same as GET: prefer summary or data.summary with the final (or initial) summary text.
Note: The current hook does not poll; it assumes the POST returns when work is done (or returns a stub you extend later). If generation is async, extend the hook or add GET /ai-summary/status and polling in a follow-up.
OCR text
Used by the OCR Text sidebar: fetch stored per-page text; optionally start an OCR job and poll until complete, then fetch text again.
| Method | Path | Description |
|---|---|---|
GET | /ocr/text | Return stored OCR output for the document (typically per-page). |
POST | /ocr/status | Start or trigger OCR processing for the document (may be long-running). |
POST | /ocr/latest-status | Return current job status for polling. |
Optional (not called by the web client today, listed in code comments): GET /ocr/health — health check for the OCR service.
GET /ocr/text
Query parameters
| Name | Type | Description |
|---|---|---|
doc_id | string | Document identifier. |
user_id | string | User identifier. |
Response (frontend parsing)
pages: array of page objects. Each item may include:text— plain text for that pagepage_numberorpage— page index for display headers
The hook merges pages[].text with double newlines for a single text fallback in the UI.
404: Treated as “no OCR stored yet” (empty pages/text, not thrown as a user-facing error).
POST /ocr/status
JSON body
{
"doc_id": "<document id>",
"user_id": "<user id>"
}
Purpose: Kick off OCR. The frontend comment warns that this request may run a long time; consider returning 202 + job_id and short timeouts on the client, or move work async and use status polling only.
POST /ocr/latest-status
JSON body
Same as /ocr/status.
Purpose: Poll while OCR runs. The client calls this every 5 seconds, up to 240 attempts (~20 minutes), until status is terminal.
Status field (flexible)
The hook reads status from the JSON object (or nested data) using the first present field:
status,job_status, orstate(compared case-insensitively)
Completed-like values: completed, complete, success, finished, succeeded, done
Failed-like values: failed, error, cancelled, canceled, failure
On success, the client then calls GET /ocr/text again to load the stored text.
Flow summary
AI summary
- Open sidebar →
GET /ai-summary/latest?doc_id=&user_id= - User clicks Generate →
POST /ai-summary/generatewith body{ doc_id, user_id }
OCR
- Open sidebar (optional load-only) →
GET /ocr/text?doc_id=&user_id= - User runs OCR →
POST /ocr/status→ loopPOST /ocr/latest-statusuntil complete/failed/timeout →GET /ocr/text
Changelog
- Initial contract aligned with
ocrApi.jsandaiSummaryApi.jsin RedactStripe TurboRepo web app.