DeepCitation + Express.js

Add citation verification to any Express.js API. Three endpoints: upload, chat (proxy your LLM), and verify.

CSS not needed. Express APIs return JSON — the React components (CitationComponent) are only used if you have a separate frontend consuming these endpoints.


Install

npm install deepcitation express multer @types/multer

File Structure

src/
├── server.ts          ← Express app with three routes
├── upload.ts          ← prepareAttachments()
├── chat.ts            ← wrapCitationPrompt() + your LLM call
└── verify.ts          ← getAllCitationsFromLlmOutput() + verifyAttachment()

Setup

// server.ts
import express from "express";
import multer from "multer";
import { DeepCitation } from "deepcitation";

const app = express();
const upload = multer({ storage: multer.memoryStorage() });

const dc = new DeepCitation({ apiKey: process.env.DEEPCITATION_API_KEY! });

app.use(express.json());

Route 1: Upload Document

// POST /api/upload
app.post("/api/upload", upload.single("file"), async (req, res) => {
  const file = req.file;
  if (!file) return res.status(400).json({ error: "No file provided" });

  const { fileDataParts, deepTextPages } = await dc.prepareAttachments([
    { file: file.buffer, filename: file.originalname },
  ]);

  res.json({
    fileDataPart: fileDataParts[0],
    deepTextPages,
  });
});

Route 2: Chat (Proxy Your LLM)

import { wrapCitationPrompt } from "deepcitation";

// POST /api/chat
app.post("/api/chat", async (req, res) => {
  const { userMessage, deepTextPages } = req.body;

  const { enhancedSystemPrompt, enhancedUserPrompt } = wrapCitationPrompt({
    systemPrompt: "You are a helpful assistant that provides cited responses.",
    userPrompt: userMessage,
    deepTextPages,
  });

  // Replace with your LLM provider (e.g. gpt-5-mini, gemini-2.0-flash-lite)
  const llmOutput = await callYourLLM(enhancedSystemPrompt, enhancedUserPrompt);

  res.json({ llmOutput });
});

Route 3: Verify Citations

import { getAllCitationsFromLlmOutput } from "deepcitation";

// POST /api/verify
app.post("/api/verify", async (req, res) => {
  const { llmOutput, attachmentId } = req.body;

  // Golden rule: CitationRecord is Record<string, Citation>, NOT an array
  const citations = getAllCitationsFromLlmOutput(llmOutput);
  const { verifications } = await dc.verifyAttachment(attachmentId, citations);

  res.json({ verifications });
});

Golden Rules

  1. CitationRecord is an object, not an array — Record<string, Citation>. Use Object.keys(citations).length, not .length.
  2. Always call parseCitationResponse() before displaying LLM output to users — .visibleText strips <<<CITATION_DATA>>> markers.
  3. Never fabricate citation URLs — only use URLs returned by the verification API.
  4. Keep your API key server-side — never send it to the browser.
import { parseCitationResponse } from "deepcitation";

// Before displaying to users:
const result = parseCitationResponse(llmOutput);
const cleanText = result.visibleText; // <<<CITATION_DATA>>> markers stripped

Error Handling

DeepCitation errors extend DeepCitationError with isRetryable and docUrl:

import { DeepCitationError } from "deepcitation";

app.post("/api/verify", async (req, res) => {
  try {
    const citations = getAllCitationsFromLlmOutput(req.body.llmOutput);
    const result = await dc.verifyAttachment(req.body.attachmentId, citations);
    res.json(result);
  } catch (err) {
    if (err instanceof DeepCitationError) {
      res.status(err.statusCode ?? 500).json({
        error: err.message,
        retryable: err.isRetryable,
        docs: err.docUrl,
      });
    } else {
      res.status(500).json({ error: "Internal server error" });
    }
  }
});

Start the Server

const PORT = process.env.PORT ?? 3001;
app.listen(PORT, () => console.log(`DC API running on port ${PORT}`));

Next Steps

  • API Reference — full endpoint documentation
  • Error Handling — all error codes and fix steps
  • Styling — if you’re building a React frontend to consume these endpoints

Back to top

© 2026 DeepCitation — a product of FileLasso, Inc.