Live App →

API Reference

Complete endpoint documentation for all Sentinel services. All API calls route through the Studio Backend (BFF) at studio-backend-dev.centricitywealth.tech. The frontend never calls downstream microservices directly.


Response Envelope

All V1 endpoints return a standard ResponseEnvelope<T>:

{
  "success": true,
  "message": "Operation completed",
  "error": null,
  "result": { /* T  the actual payload */ }
}

The api-client.ts layer automatically unwraps this envelope so callers receive T directly. V2 pipeline progress is the exception – it returns raw JSON without an envelope.

graph LR
    Raw["API Response<br/>{success, result: T}"]:::primary --> Client["api-client.ts<br/>Unwraps envelope"]:::secondary
    Client --> Caller["Caller gets T<br/>directly"]:::success
    V2["V2 Progress<br/>Raw JSON"]:::neutral --> Smart["Smart detection<br/>Pass through as-is"]:::warning
    Smart --> Caller

    classDef primary fill:#dbeafe,stroke:#3b82f6,color:#1e293b
    classDef secondary fill:#e0e7ff,stroke:#6366f1,color:#1e293b
    classDef success fill:#d1fae5,stroke:#10b981,color:#1e293b
    classDef warning fill:#fef3c7,stroke:#f59e0b,color:#1e293b
    classDef danger fill:#fee2e2,stroke:#ef4444,color:#1e293b
    classDef neutral fill:#f1f5f9,stroke:#64748b,color:#1e293b
    classDef highlight fill:#fae8ff,stroke:#a855f7,color:#1e293b
    classDef dark fill:#1e293b,stroke:#334155,color:#f8fafc

Request Lifecycle

Every API call flows through a consistent chain: React Query hook, API module, gateway layer, and the shared api-client.ts. The following diagram traces a complete request from the page component down to the Studio BFF and back.

sequenceDiagram
    participant Page as Page Component
    participant Hook as React Query Hook
    participant API as API Module
    participant GW as Gateway
    participant Client as api-client.ts
    participant BFF as Studio BFF

    Page->>Hook: useQuery / useMutation
    Hook->>API: nexus.getDocuments()
    API->>GW: nexusRequest('/documents/')
    GW->>Client: request('/nexus/documents/')
    Client->>Client: Build URL + Add Bearer
    Client->>BFF: GET /api/v1/nexus/documents/
    BFF-->>Client: ResponseEnvelope
    Client-->>Client: Unwrap .result
    Client-->>GW: T
    GW-->>API: T
    API-->>Hook: T
    Hook-->>Page: { data: T }

Auth (Server Actions)

Authentication is handled server-side via Next.js Server Actions. Tokens are stored in encrypted HttpOnly cookies and are never exposed to the browser.

Method Endpoint Description
POST /api/v1/auth/login Login with email and password
POST /api/v1/auth/register Create a new account
POST /api/v1/auth/refresh Refresh the access token
POST /api/v1/auth/logout Logout and clear the session

POST /api/v1/auth/login

Request:

{
  "email": "user@example.com",
  "password": "your-password"
}

Response:

{
  "success": true,
  "message": "Login successful",
  "result": {
    "access_token": "eyJhbG...",
    "refresh_token": "eyJhbG...",
    "user": {
      "id": "uuid",
      "email": "user@example.com",
      "full_name": "John Doe",
      "role": "user"
    }
  }
}

POST /api/v1/auth/register

Request:

{
  "email": "user@example.com",
  "password": "secure-password",
  "full_name": "John Doe"
}

POST /api/v1/auth/refresh

Headers:

Authorization: Bearer <refresh_token>

Response: Returns a new access_token and refresh_token pair.


Dashboard

Aggregated platform metrics and activity feed for the authenticated user.

Method Endpoint Description
GET /api/v1/dashboard?period=all_time Aggregated platform metrics
GET /api/v1/dashboard/activity?page=1&limit=20 Activity feed with pagination

GET /api/v1/dashboard?period=all_time

Returns high-level stats: documents processed, extraction count, success rate, AI conversation count, and token usage.

Query Parameters:

  • period — One of all_time, 7d, 30d, 90d

Response (unwrapped):

{
  "documents_processed": 142,
  "extractions": 138,
  "success_rate": 97.2,
  "conversations": 56,
  "token_usage": {
    "total_tokens": 1250000,
    "total_cost_inr": 4200.50
  }
}

GET /api/v1/dashboard/activity?page=1&limit=20

Returns a paginated list of recent activity events (uploads, extractions, chats).


Nexus (V1)

Document intelligence endpoints for upload, extraction, export, and metadata.

Method Endpoint Description
GET /api/v1/documents/me?limit=50&skip=0 List authenticated user’s documents with pagination
GET /api/v1/nexus/documents/{doc_id}/extraction Get extraction data for a document
POST /api/v1/nexus/upload/ Upload a document (multipart/form-data)
GET /api/v1/nexus/doc-fetch/{job_id}?type=ORIGINAL Fetch the original uploaded PDF
GET /api/v1/nexus/export/{job_id}/fields Get export field definitions
GET /api/v1/nexus/token-usage/{doc_id} Token usage breakdown by stage
GET /api/v1/nexus/stats Platform-wide stats (admin-only)

GET /api/v1/documents/me?limit=50&skip=0

Returns only the authenticated user’s documents. Replaced the previous admin-scoped /nexus/documents/ endpoint as of v6.2.

Query Parameters:

  • limit — Number of documents to return (default: 50)
  • skip — Offset for pagination (default: 0)

Response (unwrapped):

[
  {
    "doc_id": "uuid",
    "job_id": "uuid",
    "file_name": "CAS_Statement_Jan2026.pdf",
    "status": "completed",
    "classification": "CAS",
    "confidence_score": 95.4,
    "created_at": "2026-02-18T10:30:00Z",
    "updated_at": "2026-02-18T10:35:00Z"
  }
]

GET /api/v1/nexus/documents/{doc_id}/extraction

Returns the full extraction result including securities holdings, asset allocation, and account metadata.

Response (unwrapped):

{
  "doc_id": "uuid",
  "entities": [
    {
      "entity_name": "John Doe",
      "pan": "ABCDE1234F",
      "holdings": [
        {
          "scheme_name": "HDFC Top 100 Fund",
          "isin": "INF179K01AB3",
          "units": 150.25,
          "nav": 845.32,
          "market_value": 127007.34,
          "asset_class": "Equity"
        }
      ],
      "asset_allocation": {
        "equity": 65.2,
        "debt": 25.8,
        "hybrid": 9.0
      }
    }
  ]
}

POST /api/v1/nexus/upload/

Upload a financial document for processing.

Request: multipart/form-data

  • file — The PDF file to upload

Response (unwrapped):

{
  "job_id": "uuid",
  "doc_id": "uuid",
  "status": "uploaded",
  "password_required": false,
  "password_hint": null
}

GET /api/v1/nexus/doc-fetch/{job_id}?type=ORIGINAL

Fetches the original uploaded PDF binary. Returns the file as application/pdf.

Query Parameters:

  • typeORIGINAL for the uploaded PDF, LAYOUT for layout analysis images

GET /api/v1/nexus/export/{job_id}/fields

Returns available export field definitions for a processed document.

Query Parameters (optional):

  • export_typeholdings or underlying

GET /api/v1/nexus/token-usage/{doc_id}

Returns per-stage token usage with cost breakdown.

Response (unwrapped):

{
  "doc_id": "uuid",
  "stages": [
    {
      "stage_name": "classification",
      "model": "gpt-4o",
      "input_tokens": 1200,
      "output_tokens": 450,
      "cost_inr": 12.50
    }
  ],
  "total_tokens": 45000,
  "total_cost_inr": 185.00
}

GET /api/v1/nexus/stats

Access: Admin-only. Returns platform-wide statistics across all users.


Nexus (V2 Pipeline)

Version 2 endpoints for the document processing pipeline. V2 introduces process_id-based tracking alongside job_id.

Method Endpoint Description
POST /api/v2/nexus/pipeline/process Start the document processing pipeline
GET /api/v2/nexus/status/process/{process_id}/progress Poll pipeline progress

POST /api/v2/nexus/pipeline/process

Initiates the 10-stage AI extraction pipeline for an uploaded document.

Request:

{
  "job_id": "uuid"
}

Response (unwrapped):

{
  "process_id": "uuid",
  "job_id": "uuid",
  "status": "processing"
}

Note: The process_id is stored in the frontend’s nexus-store.processIdMap and used for all subsequent progress polling.

GET /api/v2/nexus/status/process/{process_id}/progress

Polls the current progress of a running pipeline.

Important: This endpoint returns raw JSON without a ResponseEnvelope. The api-client.ts smart detection passes it through as-is.

Response (raw, no envelope):

{
  "process_id": "uuid",
  "status": "processing",
  "progress_pct": 60,
  "current_stage": "extraction",
  "stages_completed": 6,
  "total_stages": 10,
  "stages": [
    {
      "name": "classification",
      "status": "completed",
      "duration_ms": 2300
    },
    {
      "name": "extraction",
      "status": "in_progress",
      "duration_ms": null
    }
  ]
}

Pipeline Stages (in order):

# Stage Description
1 Upload File received and validated
2 Classification Document type identification
3 Parsing Text extraction from PDF
4 Structuring Content structure analysis
5 Extraction Securities and holdings extraction
6 Validation Data integrity checks
7 Enrichment Market data enrichment
8 Calculation Portfolio calculations
9 Summary AI-generated document summary
10 Completion Final output assembly

Polling Flow

After the frontend starts a V2 pipeline, it polls the progress endpoint every 2 seconds until progress_pct reaches 100. The progress endpoint returns raw JSON (no ResponseEnvelope), which api-client.ts detects and passes through as-is.

sequenceDiagram
    participant FE as Frontend
    participant BFF as Studio BFF
    participant Nexus as Nexus Backend

    FE->>BFF: POST /v2/pipeline/process
    BFF->>Nexus: Start pipeline
    Nexus-->>BFF: { process_id, job_id }
    BFF-->>FE: { process_id, job_id }

    loop Every 2 seconds
        FE->>BFF: GET /v2/status/process/{id}/progress
        BFF->>Nexus: Check progress
        Nexus-->>BFF: { progress_pct, stages_completed }
        BFF-->>FE: Raw JSON (no envelope)
    end

    Note over FE: progress_pct reaches 100
    FE->>BFF: GET /v1/nexus/documents/{id}/extraction
    BFF-->>FE: Extraction data

Zen

Financial AI chat endpoints. Zen uses a synchronous (non-streaming) request/response model. Messages are sent as FormData, not JSON.

Method Endpoint Description
POST /api/v1/zen/chat/ Create a new chat session (returns bare UUID)
POST /api/v1/zen/chat/invoke Send a message (FormData, synchronous)
GET /api/v1/zen/chat/sessions/summary List all sessions with summaries
GET /api/v1/zen/chat/session/{session_id} Get a session with its full message history
PUT /api/v1/zen/chat/session/{session_id} Rename a session
DELETE /api/v1/zen/chat/session/{session_id} Delete a session
POST /api/v1/zen/uploads/ Upload a file for RAG-powered chat
GET /api/v1/zen/chat/{session_id}/documents/{doc_id}/status Poll Nexus processing status for a document in a session

POST /api/v1/zen/chat/

Creates a new chat session.

Response: Returns a bare UUID string (not wrapped in an object).

"a1b2c3d4-e5f6-7890-abcd-ef1234567890"

POST /api/v1/zen/chat/invoke

Sends a message and receives the AI response synchronously.

Request: multipart/form-data

Field Type Required Description
session_id string Yes UUID of the chat session
query string Yes The user’s message text
skip_guardrail string No "true" or "false" (default: "false")
web_search string No "true" or "false" — enable real-time web search
agent_id string No MongoDB ObjectId of a specific agent to invoke

Response (unwrapped):

{
  "status": "success",
  "message_id": "uuid-of-user-message",
  "response_message_id": "uuid-of-ai-response",
  "response": "Based on current data, the top performing large-cap mutual funds are...",
  "meta": {
    "web_search": "True",
    "agents_invoked": [
      {
        "agent_id": "6989c8987e0f5c816015fd18",
        "agent_name": "Market Research"
      }
    ]
  },
  "guardrail": null,
  "error": null
}

Key detail: AI messages must be keyed by response_message_id, not message_id. The message_id field refers to the user’s message. The meta.web_search field is a string ("True"/"False"), not a boolean.

GET /api/v1/zen/chat/sessions/summary

Returns all chat sessions for the authenticated user, ordered by most recent.

Response (unwrapped):

[
  {
    "session_id": "uuid",
    "title": "Portfolio Analysis Discussion",
    "created_at": "2026-02-18T14:20:00Z",
    "updated_at": "2026-02-18T15:45:00Z",
    "message_count": 12
  }
]

GET /api/v1/zen/chat/session/{session_id}

Returns a single session with its complete message history.

PUT /api/v1/zen/chat/session/{session_id}

Request:

{
  "title": "New Session Title"
}

DELETE /api/v1/zen/chat/session/{session_id}

Permanently deletes a chat session and all its messages.

POST /api/v1/zen/uploads/

Uploads a file for RAG-powered document Q&A within a chat session.

Request: multipart/form-data

Field Type Required Description
file File Yes The document to upload (PDF)
session_id string Yes UUID of the chat session

Response (unwrapped):

{
  "document_ids": ["uuid"],
  "file_name": "quarterly_report.pdf",
  "status": "processed"
}

GET /api/v1/zen/chat/{session_id}/documents/{doc_id}/status

Polls the processing status of a document attached to a chat session. Used by the NexusProcessingIndicator component to show live Nexus pipeline progress within the chat UI. Called with suppressAuthEvent: true so 401 responses from background polling do not trigger the global session-expired modal.

Response (unwrapped):

{
  "doc_id": "uuid",
  "status": "nexus_processing",
  "filename": "CAS_Jan2026.pdf",
  "source": "nexus",
  "chunks_indexed": 0,
  "nexus_progress": {
    "current_stage": "entity_detect",
    "stages_completed": 4,
    "total_stages": 10,
    "status": "processing",
    "progress_pct": 40
  },
  "error_message": null
}

Status values:

Status Meaning
processing Document being ingested for RAG
nexus_processing Document running through the Nexus 10-stage pipeline
completed Fully indexed and ready for queries
failed Pipeline or ingestion error

Health Checks

Method Endpoint Description
GET /api/v1/health/ Studio Backend health
GET /api/v1/discovery/services/nexus/health Nexus service health via discovery

Authentication

All endpoints (except auth and health) require a Bearer token in the Authorization header:

Authorization: Bearer <access_token>

The frontend reads the access token from the in-memory Zustand auth store. The token is never persisted to localStorage – only the user profile is persisted. Token refresh is handled automatically via encrypted HttpOnly cookies on the server side.


Error Handling

Failed requests return the standard envelope with success: false:

{
  "success": false,
  "message": "Document not found",
  "error": {
    "code": "NOT_FOUND",
    "details": "No document with ID abc-123"
  },
  "result": null
}

Common HTTP status codes:

Status Meaning
200 Success
400 Bad request (validation error)
401 Unauthorized (token expired or missing)
403 Forbidden (insufficient permissions)
404 Resource not found
413 Payload too large (file upload)
500 Internal server error

BFF Routing Summary

All 32 Nexus routes are explicitly defined in the Studio Backend middleware. Zen routes use a wildcard proxy pattern. The frontend’s gateway layers (nexus-gateway.ts, zen-gateway.ts) prepend the service prefix (/nexus, /zen) to all paths before the api-client.ts constructs the final URL as {baseUrl}/api/{version}/{path}.

Gateway Prefix Routing
Nexus /nexus 32 explicit middleware routes
Zen /zen Wildcard proxy

URL Construction: api-client.ts defaults to V1. Use apiVersion: 'v2' to override for pipeline endpoints.


Last Updated: March 3, 2026