TypeScript SDK ยท client.sdk.feedback

Feedback

The feedback namespace is how you close the loop between your users and the AI fill pipeline. Record where each filled PDF is stored, retrieve version history, let users report errors directly from your interface, and pull those reports for review - all in one place.

client.sdk.feedbackfilledPdf.recordSaveEventfilledPdf.getVersionHistoryuser.submituser.list
What this page covers
How the AI feedback loop works end-to-end
Recording a filled PDF save event after fill completes
Retrieving the version history of a filled PDF
Submitting user-reported errors from your UI
Listing and filtering all feedback for your account
The standard error_type categories and when to use each

How feedback works

The fill pipeline is AI-driven, which means it is not perfect. The feedback system exists so your users can report mistakes, and the AI can learn from them over time. There are two distinct steps you integrate into your application.

Step 1 - Your serverAfter fill completes

Once the AI fill pipeline finishes and you have stored the filled PDF, call filledPdf.recordSaveEvent(). This registers the output location so the platform knows which file belongs to which session - a required step for any feedback submitted in Step 2 to be correctly attributed.

Step 2 - Your UIWhen a user reports an error

Surface a "Report an issue" or "This is wrong" action in your interface. When a user submits a report, call user.submit() with details about which field was wrong and why. The report appears in your admin dashboard and feeds directly into AI model improvement.

End-to-end integration example
feedback-integration.ts
import Pdffillr from '@pdffillr/sdk';
import fs from 'fs';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'], // This is the default and can be omitted
});

// Step 1 - Upload the blank PDF template.
const doc = await client.sdk.docs.upload({
  file: fs.createReadStream('form.pdf'),
});

// Step 2 - Create a session and run the AI fill pipeline.
const session = await client.sdk.chat.sessions.create({ title: 'KYC Form' });
// ...fill pipeline runs asynchronously...

// Step 3 - Once the filled PDF is stored, record the save event.
//    This tells the feedback loop exactly where the filled output lives.
await client.sdk.feedback.filledPdf.recordSaveEvent({
  filled_pdf_location: `filled-pdfs/${session.session_id}/output.pdf`,
  pdf_id: String(doc.doc_id),
  session_id: session.session_id,
});

// Step 4 - If the user reports an error via your UI, submit feedback.
await client.sdk.feedback.user.submit({
  session_id: session.session_id,
  pdf_id: String(doc.doc_id),
  field_name: 'Tax ID',
  field_type: 'text',
  page_number: 1,
  error_type: 'wrong_field',
  feedback: 'Value placed in Tax ID field but should have gone into the EIN field.',
});

console.log('Feedback loop complete - this session is now tracked for AI improvement.');
recordSaveEvent is required for accurate feedback
Without a recorded save event, the platform cannot link a user report back to the correct fill output. Always call filledPdf.recordSaveEvent() before exposing the filled PDF to your users.

1. Record a Save Event

Call this method on your server immediately after the AI fill pipeline completes and you have stored the filled PDF. It logs the storage location of the output and ties it to the originating session and PDF template - this is what makes the version history and feedback attribution work correctly.

client.sdk.feedback.filledPdf.recordSaveEvent(body, options?)POST
Endpoint//v1/sdk/feedback/filled-pdfReturns/void
Required parameters - body
ParameterTypeDescription
filled_pdf_locationstringThe S3 key, file path, or URL where the filled PDF has been stored.
pdf_idstringThe ID of the blank PDF template that was used for this fill job.
session_idstringThe ID of the session that produced this filled output.
Example
record-save-event.ts
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'], // This is the default and can be omitted
});

// Call this on your server once the fill pipeline has completed
// and the filled PDF has been stored.
await client.sdk.feedback.filledPdf.recordSaveEvent({
  // Where the filled PDF is stored - S3 key, file path, or URL.
  filled_pdf_location: 'filled-pdfs/dev-123/session-abc/v1.pdf',

  // The ID of the blank PDF template used for this fill job.
  pdf_id: '42',

  // The session that produced this filled output.
  session_id: 'clx9f2k3n0000abc123xyz',
});

console.log('Save event recorded. The AI feedback loop can now track this output.');
When to call this
Call recordSaveEvent() from your backend - not the browser. It should run in the same flow where you move the filled PDF to its final storage location (S3 bucket, database, CDN, etc.).

2. Get Version History

Retrieves all recorded versions for a given session and PDF, ordered by date descending. Every time you call recordSaveEvent for the same session and document, a new version is added to the history logs.

client.sdk.feedback.filledPdf.getVersionHistory(query, options?)GET
Endpoint//v1/sdk/feedback/filled-pdfReturns/Array of version objects
Required parameters - query
ParameterTypeDescription
pdf_idstringThe ID of the PDF template.
session_idstringThe ID of the session.
Example
get-version-history.ts
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'], // This is the default and can be omitted
});

// Fetch all recorded versions for a specific document in a session.
const history = await client.sdk.feedback.filledPdf.getVersionHistory({
  pdf_id: '42',
  session_id: 'clx9f2k3n0000abc123xyz',
});

console.log('Version history retrieved successfully.');

3. Submit User Feedback

Records a user's report about an incorrectly filled field. This is intended to be called from your application whenever a user flags a problem - for example, by clicking a "Report an issue" button next to a filled field. Reports are visible in the admin analytics dashboard and feed directly into AI model improvement.

client.sdk.feedback.user.submit(body, options?)POST
Endpoint//v1/sdk/feedback/userReturns/void
Parameters - body
ParameterTypeDescription
session_idstringThe session where the incorrectly filled PDF was produced.
pdf_idstringThe ID of the PDF template involved in this report.
field_namestringThe name or label of the form field being reported.
field_typestringThe type of the field: text, checkbox, radio, date, signature, or dropdown.
page_numbernumberThe page number (1-based) where the field appears.
error_typestringThe category of error. See the error_type table below.
feedbackstringA plain-English description of what went wrong.
cornersunknown(Optional) Bounding box { x1, y1, x2, y2 } of the field on the page.
error_type values
Wrong Valuewrong_value

The field was filled but with the wrong value or inaccurate data.

Wrong Fieldwrong_field

The value was placed in the incorrect form field.

Missing Fieldmissing_field

The required information was provided but the field was left empty.

Extra Fieldextra_field

The AI filled a field that should have been left blank or untouched.

Formattingformatting

The data is correct but the format is wrong (e.g., incorrect date format).

Otherother

Any other feedback or issue that does not fit into the standard categories.

Example
submit-feedback.ts
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'], // This is the default and can be omitted
});

// Triggered when a user clicks "Report an issue" or "This is wrong" in your UI.
await client.sdk.feedback.user.submit({
  // Which session and PDF this report is about.
  session_id: 'clx9f2k3n0000abc123xyz',
  pdf_id: '42',

  // The specific field the user is reporting a problem with.
  field_name: 'Date of Birth',
  field_type: 'date',
  page_number: 2,

  // Optional: Provide bounding box coordinates of the field
  corners: { x1: 100, y1: 200, x2: 250, y2: 220 },

  // What kind of error occurred (see error_type values below).
  error_type: 'formatting',

  // A plain-English description of what went wrong.
  feedback: 'Date was filled as MM/DD/YYYY but form requires DD/MM/YYYY.',
});

console.log('Feedback submitted. This will appear in your admin analytics dashboard.');
Where to call this in your app
Wire this to any "Report an issue" action in your UI - for example, a button rendered next to each filled field in a review step. Pass the session_id and pdf_id from the fill result you already have in state; collect field_name, error_type, and feedback from a small form the user submits.

4. List Feedback

Retrieves all feedback submitted under your developer account. Results are paginated and ordered by submission date, newest first. You can filter by a specific PDF or session to narrow down reports for a particular fill job. Use this to build an admin view of reported issues or to export feedback data for review.

client.sdk.feedback.user.list(query?, options?)GET
Endpoint//v1/sdk/feedback/userReturns/Paginated feedback list
Query parameters (all optional)
ParameterTypeDefaultDescription
pagenumber1Page number to retrieve. 1-indexed.
limitnumber20Number of items per page.
pdf_idstring-Filter to feedback for a specific PDF template.
session_idstring-Filter to feedback for a specific session.
Example
list-feedback.ts
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'], // This is the default and can be omitted
});

// Fetch all feedback across your account.
const result = await client.sdk.feedback.user.list();

result.data?.forEach((item) => {
  console.log(`[${item.error_type}] "${item.field_name}" - ${item.feedback}`);
});

// Filter down to a specific PDF or session.
const forPdf     = await client.sdk.feedback.user.list({ pdf_id: '42' });
const forSession = await client.sdk.feedback.user.list({
  session_id: 'clx9f2k3n0000abc123xyz',
});

// Paginate through a large set of reports.
const page2 = await client.sdk.feedback.user.list({ page: 2, limit: 20 });
console.log(`Page 2 has ${page2.data?.length || 0} feedback items.`);
Admin use case
user.list() is designed for your backend admin views - not for end-users. Use the session_id or pdf_id filters to scope the results to a specific job when building a per-document feedback review panel.

What to read next

Was this page helpful?
PDFFILLR.AI logo

PDFFILLR.AI

The intelligent layer for modern fund
administration. Automating high-stakes
documentation with precision and speed.

Powered byEngineersMind