Copy the entire prompt block and paste it into your AI assistant. Replace placeholder values like
YOUR_API_KEY with your actual credentials.Setup & Configuration
Initialize the Client
- JavaScript/TypeScript
- Python
- C#
Copy
Create a DocBit AI API client class in TypeScript for my Node.js project.
API Configuration:
- Base URL: https://api.docbit.ai
- Authentication: X-Api-Key header with API key from DOCBIT_API_KEY env variable
Required Headers (must be sent with every request):
- X-Api-Key: The API key for authentication
- X-External-Org-Id: String identifier for the organization/tenant (e.g., "org_abc123")
- X-External-User-Id: String identifier for the end user (e.g., "user_xyz789")
- X-External-Roles: Comma-separated list of roles for access control (e.g., "engineering,admin")
Client Class Requirements:
1. Constructor accepts: apiKey, defaultOrgId, defaultUserId, defaultRoles
2. Method: chat(message: string, options?: { conversationId?: string, orgId?: string, userId?: string, roles?: string[] })
- POST to /api/ai/chat
- Body: { message, conversationId }
- Returns: { response: string, conversationId: string, sources: Array<{ documentId: string, snippet: string }> }
3. Method: chatStream(message: string, options?: { conversationId?: string, orgId?: string, userId?: string, roles?: string[] })
- POST to /api/ai/chat/stream
- Returns an async generator that yields string chunks
4. Method: uploadDocument(file: Buffer | ReadStream, filename: string, options?: { roles?: string[], folder?: string })
- POST to /api/documents/upload as multipart/form-data
- Form fields: file, roles (comma-separated), folder (optional)
- Returns: { documentId: string, status: string }
Use axios or fetch. Include TypeScript interfaces for all request/response types.
Copy
Create a DocBit AI API client class in Python for my project.
API Configuration:
- Base URL: https://api.docbit.ai
- Authentication: X-Api-Key header with API key from DOCBIT_API_KEY env variable
Required Headers (must be sent with every request):
- X-Api-Key: The API key for authentication
- X-External-Org-Id: String identifier for the organization/tenant (e.g., "org_abc123")
- X-External-User-Id: String identifier for the end user (e.g., "user_xyz789")
- X-External-Roles: Comma-separated list of roles for access control (e.g., "engineering,admin")
Client Class Requirements:
1. __init__ accepts: api_key, default_org_id, default_user_id, default_roles (list)
2. Method: chat(message: str, conversation_id: str = None, org_id: str = None, user_id: str = None, roles: list = None) -> dict
- POST to /api/ai/chat
- Body: { "message": message, "conversationId": conversation_id }
- Returns dict with: response (str), conversationId (str), sources (list of dicts with documentId, snippet)
3. Method: chat_stream(message: str, conversation_id: str = None, ...) -> Generator[str, None, None]
- POST to /api/ai/chat/stream
- Yields string chunks as they arrive via SSE
4. Method: upload_document(file_path: str, roles: list = None, folder: str = None) -> dict
- POST to /api/documents/upload as multipart/form-data
- Returns dict with: documentId (str), status (str)
Use the requests library. Include type hints. Handle SSE parsing for streaming.
Copy
Create a DocBit AI API client class in C# for my .NET 8 project.
API Configuration:
- Base URL: https://api.docbit.ai
- Authentication: X-Api-Key header with API key from configuration
Required Headers (must be sent with every request):
- X-Api-Key: The API key for authentication
- X-External-Org-Id: String identifier for the organization/tenant (e.g., "org_abc123")
- X-External-User-Id: String identifier for the end user (e.g., "user_xyz789")
- X-External-Roles: Comma-separated list of roles for access control (e.g., "engineering,admin")
Client Class Requirements:
1. Constructor injection: IHttpClientFactory, IConfiguration
2. Method: Task<ChatResponse> ChatAsync(string message, ChatOptions? options = null)
- POST to /api/ai/chat
- Body: { "message": message, "conversationId": options?.ConversationId }
- ChatResponse: Response (string), ConversationId (string), Sources (List<Source>)
3. Method: IAsyncEnumerable<string> ChatStreamAsync(string message, ChatOptions? options = null)
- POST to /api/ai/chat/stream
- Yields string chunks from SSE stream
4. Method: Task<UploadResponse> UploadDocumentAsync(Stream file, string filename, UploadOptions? options = null)
- POST to /api/documents/upload as MultipartFormDataContent
- UploadResponse: DocumentId (string), Status (string)
Create record types for ChatOptions (ConversationId, OrgId, UserId, Roles), UploadOptions (Roles, Folder), ChatResponse, UploadResponse, Source.
Register with DI using AddHttpClient<DocBitClient>().
Chat Integration
Basic Chat Request
Copy
Implement a function to send a chat message to the DocBit AI RAG API and display the response with source citations.
API Endpoint: POST https://api.docbit.ai/api/ai/chat
Content-Type: application/json
Required Headers:
- X-Api-Key: "your-api-key" (authentication)
- X-External-Org-Id: "org_abc123" (tenant isolation - all queries scoped to this org's documents)
- X-External-User-Id: "user_xyz789" (tracks conversation history per user)
- X-External-Roles: "engineering,team-alpha" (only documents tagged with these roles are searched)
Request Body:
{
"message": "What is our refund policy?",
"conversationId": "550e8400-e29b-41d4-a716-446655440000" // Optional: omit for new conversation
}
Success Response (200):
{
"response": "According to our policy, customers can request a refund within 30 days...",
"conversationId": "550e8400-e29b-41d4-a716-446655440000",
"sources": [
{
"documentId": "doc_abc123",
"documentName": "Refund Policy 2024.pdf",
"snippet": "...refund requests must be submitted within 30 calendar days...",
"relevanceScore": 0.94
}
]
}
Error Handling:
- 400: Invalid request body - check message is not empty
- 401: Invalid or missing API key
- 429: Rate limited - read Retry-After header, wait, then retry
- 500: Server error - retry with exponential backoff (1s, 2s, 4s)
Display the response text to the user. If sources array is not empty, show citations with document names and snippets.
Streaming Chat
Copy
Implement streaming chat with DocBit AI using Server-Sent Events (SSE) for real-time response display.
API Endpoint: POST https://api.docbit.ai/api/ai/chat/stream
Content-Type: application/json
Accept: text/event-stream
Required Headers:
- X-Api-Key: "your-api-key"
- X-External-Org-Id: "org_abc123"
- X-External-User-Id: "user_xyz789"
- X-External-Roles: "engineering,team-alpha"
Request Body:
{
"message": "Explain our deployment process",
"conversationId": "550e8400-e29b-41d4-a716-446655440000" // Optional
}
SSE Response Format:
The response is a stream of server-sent events. Each event contains a chunk of the response:
data: {"chunk": "Based on ", "conversationId": "550e8400-..."}
data: {"chunk": "your documentation, ", "conversationId": "550e8400-..."}
data: {"chunk": "the deployment process involves...", "conversationId": "550e8400-..."}
data: {"sources": [{"documentId": "doc_123", "documentName": "Deploy Guide.md", "snippet": "..."}]}
data: [DONE]
Implementation Requirements:
1. Make POST request with request body (not GET like typical SSE)
2. Read response as a stream, not waiting for full response
3. Parse each line starting with "data: " - the rest is JSON (except "[DONE]")
4. Append each chunk.chunk to the displayed text immediately
5. When you receive the sources event, store/display the citations
6. When you receive [DONE], the stream is complete
7. Save the conversationId from any chunk for follow-up messages
8. Handle connection errors - show error message, allow retry
9. Implement a 60-second timeout for the stream connection
Document Upload
Upload with Access Control
Copy
Implement document upload to DocBit AI with role-based access control and progress tracking.
API Endpoint: POST https://api.docbit.ai/api/documents/upload
Content-Type: multipart/form-data
Required Headers:
- X-Api-Key: "your-api-key" (authentication)
- X-External-Org-Id: "org_abc123" (document stored under this organization)
Form Fields:
- file: (required) The document file
- Supported types: .pdf, .docx, .doc, .txt, .md, .html
- Max size: 50MB
- Content-Disposition: form-data; name="file"; filename="Policy Document.pdf"
- roles: (required) Comma-separated roles that can access this document
- Example: "hr,managers,all-staff"
- Users must have at least one matching role to query this document
- Use "public" or similar for org-wide access (your choice of naming)
- folder: (optional) Logical folder path for organization
- Example: "policies/hr/2024"
- Used for organizing documents, not access control
Example Request (curl):
curl -X POST https://api.docbit.ai/api/documents/upload \
-H "X-Api-Key: your-api-key" \
-H "X-External-Org-Id: org_abc123" \
-F "file=@/path/to/document.pdf" \
-F "roles=hr,managers" \
-F "folder=policies/hr"
Success Response (202 Accepted):
{
"documentId": "doc_7f3b2a1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"filename": "Policy Document.pdf",
"status": "processing",
"message": "Document uploaded successfully. Processing will complete in 1-5 minutes."
}
Error Responses:
- 400: Missing required field (file or roles) or invalid file type
{ "error": "Invalid file type. Supported: pdf, docx, doc, txt, md, html" }
- 401: Invalid or missing API key
- 413: File too large
{ "error": "File size exceeds 50MB limit" }
- 429: Rate limited - check Retry-After header
Implementation Requirements:
1. Validate file extension before upload (pdf, docx, doc, txt, md, html)
2. Check file size is under 50MB before uploading
3. Show upload progress percentage using XMLHttpRequest or fetch with progress
4. Display "Processing..." status after upload completes
5. Store the documentId for status tracking if needed
6. Handle each error case with appropriate user message
Role-Based Access Control
Dynamic Role Assignment
Copy
Create middleware/interceptor that automatically sets DocBit AI headers based on the authenticated user.
Context: DocBit AI uses three headers for access control:
- X-External-Org-Id: Isolates data by organization (tenant)
- X-External-User-Id: Tracks per-user conversation history
- X-External-Roles: Filters documents (user only sees docs with matching roles)
My Authentication System: [FILL IN YOUR AUTH DETAILS]
- Auth provider: [e.g., "Auth0", "Firebase Auth", "Custom JWT", "ASP.NET Identity"]
- Where org/tenant ID is stored: [e.g., "JWT claim 'tenant_id'", "user.organization_id in DB", "subdomain"]
- Where user ID is stored: [e.g., "JWT 'sub' claim", "session.userId", "user.id"]
- Where roles/permissions are stored: [e.g., "JWT 'roles' array", "user_roles DB table", "AD groups"]
Role Mapping Logic:
My app has these permission levels: [e.g., "admin, manager, employee, contractor"]
Map them to DocBit AI roles like this:
- admin → "admin,all-documents,confidential,internal,public"
- manager → "management,internal,public,team-{teamId}"
- employee → "internal,public,team-{teamId}"
- contractor → "public,project-{projectId}"
Middleware Requirements:
1. Run on every request to my DocBit AI proxy endpoint
2. Extract user identity from [your auth mechanism]
3. Look up or compute the user's DocBit AI roles
4. Create headers object:
{
"X-Api-Key": process.env.DOCBIT_API_KEY,
"X-External-Org-Id": extractedOrgId,
"X-External-User-Id": extractedUserId,
"X-External-Roles": computedRoles.join(",")
}
5. Forward request to DocBit AI with these headers
6. Never expose the API key to the client - this runs server-side only
Multi-Tenant Setup
Copy
Implement a multi-tenant DocBit AI integration where each customer organization has isolated data.
Multi-Tenancy Model:
- Each tenant in my app = one X-External-Org-Id in DocBit AI
- Tenants cannot see each other's documents (enforced by DocBit AI)
- Users within a tenant have different access levels (controlled by roles)
My Application Structure:
- Database: [e.g., "PostgreSQL with tenant_id column on all tables" / "separate DB per tenant"]
- User model: [e.g., "users table with tenant_id, role columns"]
- Auth: [e.g., "JWT with claims: sub, tenant_id, roles[]"]
Tenant Identification Method: [CHOOSE ONE]
- Subdomain: acme.myapp.com → tenant_id = "acme"
- Path: myapp.com/org/acme → tenant_id = "acme"
- JWT claim: token.tenant_id → tenant_id
- Header: X-Tenant-ID header → tenant_id
Implementation Requirements:
1. Create a service/module that extracts tenant context from request
2. Validate user belongs to the claimed tenant (prevent tenant spoofing)
3. Map my internal tenant ID to X-External-Org-Id (can be same value or mapped)
4. Map my internal user ID to X-External-User-Id
5. Compute X-External-Roles from user's permissions within that tenant
6. Create a proxy endpoint: POST /api/chat that:
- Authenticates the user
- Extracts tenant context
- Builds DocBit headers
- Forwards to https://api.docbit.ai/api/ai/chat
- Returns response to client
7. Never send X-Api-Key to client - keep it server-side only
8. Log tenant_id and user_id with each request for audit trail
Error Handling & Reliability
Retry with Backoff
Copy
Implement a robust HTTP client wrapper for DocBit AI with automatic retry and exponential backoff.
Retry Strategy:
- Max retries: 3
- Backoff schedule: 1s → 2s → 4s (double each time)
- Jitter: Add random 0-500ms to prevent thundering herd
Retryable Errors (DO retry):
- 429 Too Many Requests: Rate limited
- Check Retry-After header first (value in seconds)
- If header exists: wait that many seconds
- If no header: use exponential backoff
- 500 Internal Server Error: Temporary server issue
- 502 Bad Gateway: Upstream issue
- 503 Service Unavailable: Server overloaded
- 504 Gateway Timeout: Request took too long
- Network errors: ECONNRESET, ETIMEDOUT, ECONNREFUSED
Non-Retryable Errors (do NOT retry):
- 400 Bad Request: Fix the request body
- 401 Unauthorized: Fix API key or headers
- 403 Forbidden: Check permissions
- 404 Not Found: Resource doesn't exist
- 413 Payload Too Large: File exceeds 50MB
Implementation:
async function docbitRequest(method, path, body, headers, attempt = 1) {
try {
const response = await fetch(url, { method, body, headers });
if (response.ok) return response;
if (isRetryable(response.status) && attempt <= 3) {
const waitTime = getWaitTime(response, attempt);
console.log(`Attempt ${attempt} failed with ${response.status}, retrying in ${waitTime}ms`);
await sleep(waitTime);
return docbitRequest(method, path, body, headers, attempt + 1);
}
throw new DocBitError(response.status, await response.json());
} catch (networkError) {
if (isNetworkError(networkError) && attempt <= 3) {
const waitTime = Math.pow(2, attempt) * 1000 + Math.random() * 500;
await sleep(waitTime);
return docbitRequest(method, path, body, headers, attempt + 1);
}
throw networkError;
}
}
function getWaitTime(response, attempt) {
const retryAfter = response.headers.get('Retry-After');
if (retryAfter) return parseInt(retryAfter) * 1000;
return Math.pow(2, attempt) * 1000 + Math.random() * 500; // 1s, 2s, 4s + jitter
}
Error Handler
Copy
Create a comprehensive error handler for DocBit AI API responses with user-friendly messages.
Error Response Format from API:
{
"error": "Description of what went wrong",
"code": "ERROR_CODE", // Optional
"details": { ... } // Optional additional context
}
Error Mapping:
| Status | Cause | User Message | Developer Action |
|--------|-------|--------------|------------------|
| 400 | Invalid request body | "Your message couldn't be processed. Please try again." | Log request body, check JSON format, validate message is non-empty |
| 401 | Bad/missing API key | "Authentication failed. Please contact support." | Check DOCBIT_API_KEY env var, verify key is valid in dashboard |
| 403 | Forbidden | "You don't have access to this resource." | Check org ID matches, verify API key permissions |
| 404 | Not found | "The conversation was not found. Starting a new one." | Clear conversationId and retry, resource was deleted |
| 413 | File too large | "File is too large. Maximum size is 50MB." | Check file size before upload, compress if possible |
| 429 | Rate limited | "Too many requests. Please wait a moment." | Implement backoff, check Retry-After header, consider queuing |
| 500 | Server error | "Something went wrong. Retrying..." | Retry with backoff, if persists contact support |
| 502/503/504 | Infrastructure | "Service temporarily unavailable. Retrying..." | Retry with backoff, usually resolves quickly |
Implementation:
class DocBitError extends Error {
constructor(status, body) {
const { userMessage, shouldRetry } = mapError(status, body);
super(userMessage);
this.status = status;
this.shouldRetry = shouldRetry;
this.originalError = body;
}
}
function mapError(status, body) {
const messages = {
400: { userMessage: "Your message couldn't be processed. Please try again.", shouldRetry: false },
401: { userMessage: "Authentication failed. Please contact support.", shouldRetry: false },
404: { userMessage: "Conversation not found. Starting fresh.", shouldRetry: false },
413: { userMessage: `File too large. Maximum size is 50MB.`, shouldRetry: false },
429: { userMessage: "Too many requests. Please wait a moment.", shouldRetry: true },
500: { userMessage: "Something went wrong. Please try again.", shouldRetry: true },
};
return messages[status] || { userMessage: "An unexpected error occurred.", shouldRetry: false };
}
Always log the full error (status, body, request details) server-side for debugging.
Never expose internal error details to end users.
Framework Integration
Express.js Middleware
Copy
Create Express.js middleware and routes for DocBit AI integration with my existing auth.
My Current Setup:
- Express.js 4.x with TypeScript
- Authentication: [e.g., "Passport.js with JWT strategy" / "express-session" / "Auth0 middleware"]
- User object location: [e.g., "req.user after auth middleware" / "req.session.user"]
- User object structure: { id: string, tenantId: string, roles: string[], email: string }
Middleware Requirements:
1. Create middleware: attachDocBitContext(req, res, next)
- Must run AFTER authentication middleware
- Extract from req.user:
- tenantId → X-External-Org-Id
- id → X-External-User-Id
- roles array → X-External-Roles (join with comma)
- Attach to req: req.docbitHeaders = { ... }
- If user not authenticated, return 401
2. Create proxy routes that use this middleware:
POST /api/ai/chat
- Validate request body has 'message' (string, non-empty)
- Forward to https://api.docbit.ai/api/ai/chat with docbitHeaders
- Return response JSON to client
POST /api/ai/chat/stream
- Forward to https://api.docbit.ai/api/ai/chat/stream
- Pipe the SSE response back to client (res.setHeader('Content-Type', 'text/event-stream'))
POST /api/documents/upload
- Accept multipart form (use multer middleware)
- Validate file type and size (max 50MB)
- Forward to https://api.docbit.ai/api/documents/upload
- Return response JSON to client
3. Error handling middleware for DocBit errors
4. Never expose DOCBIT_API_KEY to client - only use server-side
Example route structure:
router.use(authMiddleware);
router.use(attachDocBitContext);
router.post('/chat', chatHandler);
router.post('/chat/stream', streamHandler);
router.post('/documents/upload', multer().single('file'), uploadHandler);
FastAPI Dependency
Copy
Create FastAPI dependencies and routes for DocBit AI integration with my existing auth.
My Current Setup:
- FastAPI with Python 3.11+
- Authentication: [e.g., "JWT via python-jose" / "FastAPI-Users" / "custom OAuth2"]
- Current user dependency: [e.g., "get_current_user(token: str = Depends(oauth2_scheme))"]
- User model: User(id: str, tenant_id: str, roles: List[str], email: str)
Dependency Requirements:
1. Create dependency: get_docbit_headers(current_user: User = Depends(get_current_user)) -> dict
Returns: {
"X-Api-Key": settings.DOCBIT_API_KEY,
"X-External-Org-Id": current_user.tenant_id,
"X-External-User-Id": current_user.id,
"X-External-Roles": ",".join(current_user.roles)
}
2. Create async HTTP client dependency using httpx.AsyncClient
3. Create routes:
@router.post("/ai/chat")
async def chat(
body: ChatRequest, # message: str, conversationId: Optional[str]
headers: dict = Depends(get_docbit_headers),
client: httpx.AsyncClient = Depends(get_http_client)
) -> ChatResponse:
response = await client.post(
"https://api.docbit.ai/api/ai/chat",
json=body.dict(exclude_none=True),
headers=headers
)
response.raise_for_status()
return ChatResponse(**response.json())
@router.post("/ai/chat/stream")
async def chat_stream(...) -> StreamingResponse:
# Return SSE stream using StreamingResponse
@router.post("/documents/upload")
async def upload_document(
file: UploadFile,
roles: str = Form(...),
folder: Optional[str] = Form(None),
headers: dict = Depends(get_docbit_headers)
) -> UploadResponse:
# Validate file, forward as multipart
4. Create Pydantic models: ChatRequest, ChatResponse, UploadResponse
5. Add error handlers for httpx.HTTPStatusError
6. Use python-dotenv for DOCBIT_API_KEY
ASP.NET Core Service
Copy
Create ASP.NET Core services and controllers for DocBit AI integration with my existing auth.
My Current Setup:
- ASP.NET Core 8 Web API
- Authentication: [e.g., "JWT Bearer with Microsoft.Identity" / "ASP.NET Core Identity" / "Auth0"]
- User claims available via HttpContext.User (ClaimsPrincipal)
- Relevant claims: [e.g., "sub for user ID, tenant_id for org, role for roles"]
Service Requirements:
1. Create IDocBitService interface and implementation:
public interface IDocBitService
{
Task<ChatResponse> ChatAsync(string message, string? conversationId, CancellationToken ct = default);
IAsyncEnumerable<string> ChatStreamAsync(string message, string? conversationId, CancellationToken ct = default);
Task<UploadResponse> UploadDocumentAsync(IFormFile file, string roles, string? folder, CancellationToken ct = default);
}
public class DocBitService : IDocBitService
{
private readonly HttpClient _httpClient;
private readonly IHttpContextAccessor _httpContextAccessor;
// Inject IHttpClientFactory (named client "DocBit"), IHttpContextAccessor
// Get user claims: _httpContextAccessor.HttpContext?.User
// Extract: sub claim → X-External-User-Id
// tenant_id claim → X-External-Org-Id
// role claims → X-External-Roles (join with comma)
}
2. Register in Program.cs:
builder.Services.AddHttpContextAccessor();
builder.Services.AddHttpClient("DocBit", client => {
client.BaseAddress = new Uri("https://api.docbit.ai");
client.DefaultRequestHeaders.Add("X-Api-Key", builder.Configuration["DocBit:ApiKey"]);
});
builder.Services.AddScoped<IDocBitService, DocBitService>();
3. Create controller:
[ApiController]
[Route("api/ai")]
[Authorize] // Requires authentication
public class AiController : ControllerBase
{
[HttpPost("chat")]
public async Task<ActionResult<ChatResponse>> Chat([FromBody] ChatRequest request)
[HttpPost("chat/stream")]
public async Task StreamChat([FromBody] ChatRequest request)
// Return with Content-Type: text/event-stream
[HttpPost("documents/upload")]
public async Task<ActionResult<UploadResponse>> Upload(IFormFile file, [FromForm] string roles, [FromForm] string? folder)
}
4. Create DTOs: ChatRequest, ChatResponse, UploadResponse with [Required] attributes
5. Add appsettings.json section: "DocBit": { "ApiKey": "..." }
6. Never log or expose the API key
Full Implementation
Complete Chat UI
Copy
Build a complete chat interface component that integrates with DocBit AI via my backend proxy.
My Frontend Stack: [e.g., "React 18 with TypeScript" / "Vue 3" / "Next.js 14" / "Svelte"]
My Backend Proxy Endpoint: [e.g., "/api/ai/chat/stream" - already handles auth headers]
UI Requirements:
1. Chat container with scrollable message history
2. Message bubbles: user messages on right (blue), AI responses on left (gray)
3. Text input at bottom with send button (also submit on Enter)
4. "New conversation" button to clear history and start fresh
Streaming Display:
1. When user sends message:
- Add user message bubble immediately
- Add empty AI message bubble with typing indicator
- POST to /api/ai/chat/stream with { message, conversationId }
2. As SSE chunks arrive:
- Parse "data: {json}" lines
- Append chunk.chunk text to the AI message bubble
- Scroll to bottom automatically
3. When sources event arrives:
- Store sources array
- Display expandable "Sources" section below AI message
4. When [DONE] arrives:
- Remove typing indicator
- Save conversationId for next message
- Re-enable input
Source Citations Display:
- Collapsible section: "View 3 sources"
- Each source shows: document name, relevant snippet (truncated to ~100 chars)
- Optional: link to view full document if you have a document viewer
State Management:
- messages: Array<{ role: 'user' | 'assistant', content: string, sources?: Source[] }>
- conversationId: string | null
- isLoading: boolean
- error: string | null
Error Handling:
- Show error toast/banner if request fails
- Keep user's message in input if sending failed
- "Retry" button for failed messages
Accessibility:
- Aria-live region for new messages
- Focus management: return focus to input after sending
- Keyboard navigation support
Document Management
Copy
Build a document upload interface for DocBit AI with drag-and-drop and role assignment.
My Frontend Stack: [e.g., "React 18 with TypeScript" / "Vue 3" / "Next.js 14"]
My Backend Proxy Endpoint: [e.g., "POST /api/documents/upload" - already handles auth]
Upload Interface Requirements:
1. Drag-and-drop zone (large dashed border area)
- Text: "Drag files here or click to browse"
- Visual feedback on drag over (highlight border)
- Also supports click to open file picker
2. File validation before upload:
- Allowed types: .pdf, .docx, .doc, .txt, .md, .html
- Max size: 50MB per file
- Show error for invalid files immediately
3. For each file, show upload form:
- File name and size
- Roles input: [CHOOSE ONE]
- Multi-select dropdown with predefined roles from my system
- OR free-text comma-separated input
- This is REQUIRED - don't allow upload without roles
- Folder input (optional): text input or folder tree picker
- "Upload" and "Cancel" buttons
4. Upload progress:
- Progress bar showing percentage (use XMLHttpRequest for progress)
- File size uploaded / total size
- Cancel button during upload
5. Upload states for each file:
- pending: waiting to upload
- uploading: in progress with percentage
- processing: upload complete, DocBit is processing (show spinner)
- complete: ready for queries (show green checkmark)
- error: failed (show error message and retry button)
6. Batch upload support:
- Allow selecting multiple files
- Upload sequentially or show queue
- Summary: "3 of 5 files uploaded"
API Integration:
POST /api/documents/upload
Content-Type: multipart/form-data
Body: FormData with file, roles, folder
Response: { documentId, filename, status: "processing" }
Implementation Notes:
- Use FormData API for multipart upload
- XMLHttpRequest (not fetch) for upload progress events
- Store uploaded documentIds if you want to show status later
- Consider chunked upload for very large files (optional)