Application Flows
A complete walkthrough of the three ways to use the Pdffillr SDK - Chat, Upload Document, and URL Upload. Each flow follows the same foundation, then diverges into a short sequence of SDK calls. Read through once, then copy the snippet that matches your use case.
1. The Three Flows
The SDK exposes three distinct patterns for working with a document. All three start identically - authenticate, upload, create a session, attach the document. After that, you choose the path that fits what you need to do.
Ask questions, extract data, and receive AI-generated answers against the content of your attached document. Replies stream in real time over WebSocket.
client.sdk.chat.send()Submit a map of field names to values and the SDK fills the PDF for you. The completed document is delivered as a download URL via a WebSocket event.
client.docs.uploadFilledInfo()Instead of uploading a local file, import a document directly from Google Drive or Dropbox. The SDK handles the OAuth-authenticated fetch for you.
client.docs.importFromGoogleDrive()Foundation
Every flow begins with these six steps. They are identical regardless of which path you take afterwards. Get these right once and the rest is straightforward.
new Pdffillr({ apiKey })Create one client instance at application startup and reuse it everywhere. The SDK reads your API secret from the environment and attaches it to every request automatically.
client.auth.login({ email, password })Exchange your credentials for a session token and hand it back to the client with client.setToken(). Every call after this point is automatically authorised.
client.docs.upload(filePath)Send the PDF you want to work with. The SDK returns a document ID that you carry through the rest of the flow to reference this specific file.
client.sdk.chat.sessions.create()Open a fresh, isolated session context. The session is the unit of work that groups your document, your messages, and the AI's responses into a single, coherent interaction.
client.docs.getPreviewUrl(docId)Resolve a short-lived signed URL for the uploaded document. Use this to render a live preview in your UI or to confirm the upload was received correctly before proceeding.
client.sdk.chat.sessions.attachDocument(sessionId, docId)Bind the document to the active session. After this call the AI model has full document context - your chosen flow can now begin.
import 'dotenv/config';
import Pdffillr from '@pdffillr/sdk';
// 1. Initialise the client once at application startup.
const client = new Pdffillr({
apiKey: process.env['PDFFILLR_API_KEY'],
});
// 2. Authenticate - exchange your credentials for a session token.
const { token } = await client.auth.login({
email: process.env['USER_EMAIL'],
password: process.env['USER_PASSWORD'],
});
client.setToken(token);
// 3. Upload the PDF you want to work with.
const { id: docId } = await client.docs.upload('./contract.pdf');
// 4. Create a new chat session.
// This is the unit of work that drives the entire interaction.
const session = await client.sdk.chat.sessions.create();
// 5. Get a preview URL for the uploaded document (optional).
const { url: previewUrl } = await client.docs.getPreviewUrl(docId);
// 6. Attach the document to the session.
// From this point the AI has full context of the document.
await client.sdk.chat.sessions.attachDocument(session.id, docId);
// ✅ Foundation complete - your session is ready.setupSession() helper and call it at the top of each flow. It keeps your flow-specific code focused on only the steps that differ.Chat flow
Once the session is set up, you can start sending messages. The AI reads your question in the context of the attached document and responds. You can send as many messages as you like in a single session, and retrieve the full history at any point.
client.sdk.chat.send(sessionId, { message })Pass a natural-language prompt and the session ID. The SDK routes the question to the AI model with your document as context and resolves with the AI's reply. Straightforward and fully typed.
client.sdk.chat.getMessages(userId)Fetch every message exchanged in the session, both user messages and AI replies, in chronological order. Useful for rendering a conversation thread or auditing what was asked.
client.realtime.connect()Open a WebSocket connection to receive streaming AI responses and session state changes as they happen, without polling. The SDK manages the connection and reconnection logic for you.
// (foundation already complete - client, session, and docId are available)
// 7. Send a natural-language question about the document.
const reply = await client.sdk.chat.send(session.id, {
message: 'What is the payment due date in this contract?',
});
console.log('AI reply:', reply.content);
// 8. Retrieve the full conversation history at any time.
const { messages } = await client.sdk.chat.getMessages(session.userId);
messages.forEach((m) => console.log(`[${m.role}] ${m.content}`));
// 9. Subscribe to real-time session events over WebSocket.
// Streaming replies and state changes arrive here without polling.
const ws = client.realtime.connect();
ws.on('message', (event) => {
console.log('Real-time event:', event);
});Upload document flow
When you already know the values you want to write into a form, skip the conversation and go straight to filling. Send a field map and the SDK queues the job. When the fill is complete, a WebSocket event delivers the download URL of the finished PDF.
client.docs.uploadFilledInfo(docId, { fields })Pass the document ID and a map of field names to their values. The SDK sends this to the fill engine, which processes the job asynchronously and returns a jobId. Field names must match the internal names of your PDF's AcroForm fields exactly.
ws.on('fill_complete', handler)Listen on the WebSocket for the fill_complete event. The payload includes a downloadUrl pointing to the fully filled PDF. Close the connection once you have received it.
// (foundation already complete - client, session, and docId are available)
// 7. Submit the field values you want written into the PDF.
// Field names must match the internal names of your PDF form fields.
const { jobId } = await client.docs.uploadFilledInfo(docId, {
fields: {
full_name: 'Jane Doe',
policy_no: 'POL-2024-98765',
start_date: '2024-01-01',
signature: 'Jane Doe',
},
});
console.log('Fill job queued:', jobId);
// 8. Listen for the fill_complete event - the SDK delivers the
// download URL for the finished PDF over WebSocket.
const ws = client.realtime.connect();
ws.on('fill_complete', ({ downloadUrl }) => {
console.log('Filled PDF ready:', downloadUrl);
ws.close();
});client.docs.getFields(docId) to get a list of every fillable field name in the document before you submit.URL upload flow
If your document already lives in Google Drive or Dropbox, you do not need to download and re-upload it. Pass the file reference directly to the SDK and it imports the document using your configured OAuth credentials. After that, the workflow continues exactly like any other flow.
client.docs.importFromGoogleDrive({ sessionId, fileId })Provide the session ID and the Drive file ID from the document URL. The SDK fetches the file with your OAuth token and registers it as a managed document.
// (foundation already complete - client and session are available)
// 7a. Import a document directly from Google Drive.
// The SDK fetches the file using your configured OAuth token.
const { docId } = await client.docs.importFromGoogleDrive({
sessionId: session.id,
fileId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OHB',
});
// 8. Listen for the import_complete event to get the registered document details.
const ws = client.realtime.connect();
ws.on('import_complete', ({ docId: importedDocId }) => {
console.log(`Successfully imported Google Drive document: ${importedDocId}`);
});client.docs.importFromDropbox({ sessionId, sharedLink })Provide the session ID and the Dropbox shared link. Append ?dl=0 to the URL to force a raw download stream. The SDK fetches the file and registers it as a managed document.
// (foundation already complete - client and session are available)
// 7b. Import a document directly from Dropbox using a shared link.
// Append ?dl=0 to the share URL to force a raw download stream.
const { docId } = await client.docs.importFromDropbox({
sessionId: session.id,
sharedLink: 'https://www.dropbox.com/s/abc123/contract.pdf?dl=0',
});
// 8. Listen for the import_complete event to get the registered document details.
const ws = client.realtime.connect();
ws.on('import_complete', ({ docId: importedDocId }) => {
console.log(`Successfully imported Dropbox document: ${importedDocId}`);
});What to read next
PDFFILLR.AI
The intelligent layer for modern fund
administration. Automating high-stakes
documentation with precision and speed.