Skip to main content

Overview

The Document API provides endpoints for managing PDF documents, including retrieval, collaboration, vectorization, and metadata updates.

Procedures

getDocData

Retrieves comprehensive data for a document including highlights, collaborators, messages, and user permissions.
docId
string
required
The unique identifier of the document
Returns:
id
string
Document unique identifier
title
string
Document title
url
string
URL to the PDF file
pageCount
number
Total number of pages in the document
lastReadPage
number
Last page the user was reading
note
string | null
User’s notes for the document
isVectorised
boolean
Whether the document has been vectorized for AI chat
highlights
Highlight[]
Array of highlights with position data
owner
User
Document owner information
collaborators
Collaborator[]
Array of collaborators with roles
messages
Message[]
Chat messages about the document
userPermissions
object
User’s permissions for this document
Example:
import { api } from "@/lib/api";

function DocumentViewer({ docId }: { docId: string }) {
  const { data, isLoading } = api.document.getDocData.useQuery({ docId });
  
  if (isLoading) return <div>Loading...</div>;
  
  return (
    <div>
      <h1>{data.title}</h1>
      <p>Pages: {data.pageCount}</p>
      <p>Can edit: {data.userPermissions.canEdit ? "Yes" : "No"}</p>
      {data.highlights.map(h => (
        <div key={h.id}>Highlight on page {h.position.pageNumber}</div>
      ))}
    </div>
  );
}

addCollaborator

Add a collaborator to a document (owner only).
documentId
string
required
The document ID to add a collaborator to
data.email
string
required
Email address of the user to add as collaborator
data.role
CollaboratorRole
required
The role to assign: EDITOR, VIEWER, or OWNER
Example:
const mutation = api.document.addCollaborator.useMutation();

mutation.mutate({
  documentId: "clx123abc",
  data: {
    email: "[email protected]",
    role: "EDITOR"
  }
});

removeCollaboratorById

Remove a collaborator from a document (owner only).
documentId
string
required
The document ID
userId
string
required
The user ID of the collaborator to remove
Example:
const mutation = api.document.removeCollaboratorById.useMutation();

mutation.mutate({
  documentId: "clx123abc",
  userId: "user123"
});

getCollaborators

Get all collaborators for a document (owner only).
documentId
string
required
The document ID
Returns: Array of collaborators including the owner
[]
Collaborator[]
Example:
const { data } = api.document.getCollaborators.useQuery({ 
  documentId: "clx123abc" 
});

// Returns:
// [
//   { id: "user1", email: "[email protected]", role: "OWNER" },
//   { id: "user2", email: "[email protected]", role: "EDITOR" }
// ]

vectorise

Vectorize a document to enable AI chat functionality. This processes the document and creates embeddings for semantic search.
documentId
string
required
The document ID to vectorize
Vectorization is limited by the user’s plan:
  • FREE: Up to a certain number of pages per document
  • FREE_PLUS: More pages allowed
  • PRO: Maximum pages allowed
Example:
const mutation = api.document.vectorise.useMutation({
  onSuccess: () => {
    console.log("Document vectorized successfully");
  },
  onError: (error) => {
    if (error.message.includes("already vectorised")) {
      console.log("Document was already vectorized");
    }
  }
});

mutation.mutate({ documentId: "clx123abc" });

Add a document to the user’s library by providing a PDF URL.
url
string
required
Public URL to the PDF file
title
string
required
Title for the document
Returns: The created document object
This endpoint validates:
  • User has not exceeded their plan’s document limit
  • URL returns a valid PDF file
  • PDF can be loaded successfully
Example:
const mutation = api.document.addDocumentByLink.useMutation();

mutation.mutate({
  url: "https://example.com/paper.pdf",
  title: "Research Paper"
});

updateNotes

Update personal notes for a document (owner only).
documentId
string
required
The document ID
note
string
required
The note content (can be empty string)
Example:
const mutation = api.document.updateNotes.useMutation();

mutation.mutate({
  documentId: "clx123abc",
  note: "Key insights from chapter 3..."
});

updateLastReadPage

Update the last page the user was reading (owner only).
docId
string
required
The document ID
lastReadPage
number
required
The page number (1-indexed)
Example:
const mutation = api.document.updateLastReadPage.useMutation();

// Update reading progress
mutation.mutate({
  docId: "clx123abc",
  lastReadPage: 42
});

updateTitle

Update a document’s title. Available to owners and editors.
docId
string
required
The document ID
title
string
required
New title (1-255 characters)
Example:
const mutation = api.document.updateTitle.useMutation();

mutation.mutate({
  docId: "clx123abc",
  title: "Updated Document Title"
});

Data Models

CollaboratorRole Enum

enum CollaboratorRole {
  EDITOR = "EDITOR",   // Can edit, highlight, and chat
  VIEWER = "VIEWER",   // Can only view
  OWNER = "OWNER"      // Full control (assigned automatically)
}

Document Schema

interface Document {
  id: string;
  url: string;
  title: string;
  ownerId: string;
  note: string | null;
  isVectorised: boolean;
  createdAt: Date;
  updatedAt: Date;
  pageCount: number;
  isUploaded: boolean;
  lastReadPage: number;
  coverImageUrl: string;
  summary: string | null;
}

Error Handling

Common errors:
  • UNAUTHORIZED - User is not authenticated or doesn’t have permission
  • NOT_FOUND - Document or user not found
  • BAD_REQUEST - Invalid input, document limit reached, or already vectorized
  • INTERNAL_SERVER_ERROR - Server error during processing
const mutation = api.document.addCollaborator.useMutation({
  onError: (error) => {
    if (error.data?.code === "UNAUTHORIZED") {
      toast.error("You must be the document owner");
    } else if (error.data?.code === "NOT_FOUND") {
      toast.error("User not found");
    }
  }
});

Build docs developers (and LLMs) love