Skip to main content

JavaScript / Node.js Examples

Complete examples for integrating DocBit AI into your JavaScript application.

Installation

npm install axios

Basic Setup

const axios = require('axios');

const DocBit AIClient = axios.create({
  baseURL: 'https://api.docbit.ai',
  headers: {
    'Authorization': `ApiKey ${process.env.DOCBIT_API_KEY}`,
    'Content-Type': 'application/json'
  }
});

// Helper to add required headers
function withContext(orgId, userId, roles) {
  return {
    headers: {
      'X-External-Org-Id': orgId,
      'X-External-User-Id': userId,
      'X-External-Roles': JSON.stringify(roles)
    }
  };
}

Chat Request

async function askQuestion(orgId, userId, roles, question, conversationId = null) {
  const response = await DocBit AIClient.post(
    '/api/ai/chat',
    {
      message: question,
      conversationId
    },
    withContext(orgId, userId, roles)
  );
  
  return response.data;
}

// Usage
const answer = await askQuestion(
  'acme',
  'user-456',
  ['hr', 'all-staff'],
  'What is our vacation policy?'
);

console.log(answer.content);
console.log('Citations:', answer.citations);

Streaming Chat

const EventSource = require('eventsource');

function streamChat(orgId, userId, roles, question, onToken, onDone) {
  return new Promise((resolve, reject) => {
    const body = JSON.stringify({ message: question });
    
    // Note: EventSource doesn't support POST, use fetch with ReadableStream
    fetch('https://api.docbit.ai/api/ai/chat/stream', {
      method: 'POST',
      headers: {
        'Authorization': `ApiKey ${process.env.DOCBIT_API_KEY}`,
        'Content-Type': 'application/json',
        'X-External-Org-Id': orgId,
        'X-External-User-Id': userId,
        'X-External-Roles': JSON.stringify(roles)
      },
      body
    }).then(async response => {
      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        const chunk = decoder.decode(value);
        const lines = chunk.split('\n');
        
        for (const line of lines) {
          if (line.startsWith('data: ')) {
            const data = JSON.parse(line.slice(6));
            
            if (data.token) {
              onToken(data.token);
            } else if (data.citations) {
              onDone(data);
              resolve(data);
            }
          }
        }
      }
    }).catch(reject);
  });
}

// Usage
let fullResponse = '';

await streamChat(
  'acme',
  'user-456',
  ['employee'],
  'Summarize the benefits package',
  (token) => {
    fullResponse += token;
    process.stdout.write(token);
  },
  (done) => {
    console.log('\n\nCitations:', done.citations);
  }
);

Upload Document

const FormData = require('form-data');
const fs = require('fs');

async function uploadDocument(orgId, userId, roles, filePath, aclRoles = []) {
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  
  if (aclRoles.length > 0) {
    aclRoles.forEach(role => form.append('aclRoles', role));
  }
  
  const response = await DocBit AIClient.post(
    '/api/documents/upload',
    form,
    {
      ...withContext(orgId, userId, roles),
      headers: {
        ...withContext(orgId, userId, roles).headers,
        ...form.getHeaders()
      }
    }
  );
  
  return response.data;
}

// Usage - upload HR document visible only to HR team
await uploadDocument(
  'acme',
  'admin-1',
  ['admin'],
  './hr-policy.pdf',
  ['hr']
);

// Upload company-wide document
await uploadDocument(
  'acme',
  'admin-1',
  ['admin'],
  './employee-handbook.pdf',
  ['all-staff']
);

Express Middleware

const express = require('express');
const app = express();

// Middleware to add DocBit AI headers from your session
function DocBit AIContext(req, res, next) {
  // Get user from your auth system
  const user = req.session.user;
  
  req.DocBit AIHeaders = {
    'X-External-Org-Id': user.organizationId,
    'X-External-User-Id': user.id,
    'X-External-Roles': JSON.stringify(user.roles)
  };
  
  next();
}

app.use(DocBit AIContext);

app.post('/api/ask', async (req, res) => {
  try {
    const response = await DocBit AIClient.post(
      '/api/ai/chat',
      { message: req.body.question },
      { headers: req.DocBit AIHeaders }
    );
    res.json(response.data);
  } catch (error) {
    res.status(error.response?.status || 500).json({
      error: error.response?.data?.error || 'Internal error'
    });
  }
});

Error Handling

async function safeAsk(orgId, userId, roles, question) {
  try {
    return await askQuestion(orgId, userId, roles, question);
  } catch (error) {
    if (error.response) {
      switch (error.response.status) {
        case 400:
          throw new Error(`Bad request: ${error.response.data.error}`);
        case 401:
          throw new Error('Authentication failed. Check API key.');
        case 429:
          // Rate limited - implement retry with backoff
          await sleep(1000);
          return safeAsk(orgId, userId, roles, question);
        default:
          throw new Error(`API error: ${error.response.status}`);
      }
    }
    throw error;
  }
}

TypeScript Types

interface ChatRequest {
  message: string;
  conversationId?: string;
  documentIds?: string[];
  folderIds?: string[];
}

interface Citation {
  documentId: string;
  documentTitle: string;
  page?: number;
  section?: string;
  excerpt: string;
}

interface ChatResponse {
  conversationId: string;
  content: string;
  citations: Citation[];
  confidence: 'High' | 'Medium' | 'Low';
}

async function askQuestion(
  orgId: string,
  userId: string,
  roles: string[],
  question: string
): Promise<ChatResponse> {
  // ... implementation
}