TypeScript SDK

Fundamentals

The core building blocks of every Pdffillr SDK integration - making your first API call, understanding the client namespace, getting the most out of TypeScript types, and writing error handling that holds up in production.

Chat sessionsTyped responsesasync / awaittry / catchESM + CommonJS
What this page covers
Writing and running your first SDK request end-to-end
Wrapping async calls correctly in ESM modules and scripts
The client.sdk.chat.sessions namespace hierarchy explained
How each property chain maps to a REST API path segment
TypeScript type inference and what your editor shows you
Using the SDK in plain JavaScript without any type setup
Handling errors with try / catch in a way that is production-safe
A retry pattern with exponential back-off for transient failures

1. Your First Request

Every interaction with the Pdffillr API starts with creating a chat session. A session is the unit of work that drives one complete, AI-guided form-filling interaction - from first question to filled PDF. The call is a single awaited method on the client with no required arguments. Here is the complete, minimal program to do it.

first-request.ts
import 'dotenv/config';
import Pdffillr from '@pdffillr/sdk';

// 1. Initialise the client once at application startup.
//    The SDK reads your API key from the environment automatically.
const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'],
});

// 2. Create a new chat session.
//    This sends POST /v1/sdk/chat/sessions and resolves with the session object.
const session = await client.sdk.chat.sessions.create();

// 3. Inspect the result.
console.log(session);

What each line does

01
Load environment variablesimport 'dotenv/config' reads your .env file and populates process.env before any other module runs. This must be the very first import so PDFFILLR_API_KEY is available when the client is constructed.
02
Import the SDKPdffillr is the default export - no named destructuring needed. The import brings in the client class and all its bundled TypeScript types.
03
Instantiate the clientCreate one client instance and reuse it across your application. The constructor reads your API key and stores it for every subsequent request. Instantiating the client is cheap and synchronous.
04
Call sessions.create() and await the resultThis sends a POST /v1/sdk/chat/sessions request over HTTPS. The SDK attaches your API key, waits for the response, deserialises the JSON body, and resolves the Promise with a typed session object.

Using await outside a top-level ES module

Top-level await works only in ES modules ("type": "module" in package.json, or .mts / .mjs files). In CommonJS files or older TypeScript setups, wrap your calls in an async function and call it immediately.

main.ts (CommonJS / no top-level await)
import 'dotenv/config';
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'],
});

// Wrap in an async function if you are not at the top level of an ES module.
async function main() {
  const session = await client.sdk.chat.sessions.create();
  console.log('Session created:', session);
}

main().catch(console.error);
Instantiate the client once - reuse everywhere
The SDK client is stateless with respect to individual requests. Create one instance at application startup - in a module, a dependency-injection container, or a global singleton - and import it wherever you need to make API calls. Creating a new instance per request is wasteful and unnecessary.

2. API Namespace

The SDK organises every API resource into a nested property hierarchy that mirrors the Pdffillr REST API's URL structure. You navigate to a resource by chaining property accesses on the client object, then call the method that represents the HTTP verb. This design means the SDK is self-documenting - the method name tells you the operation and your editor's autocomplete shows you every option without leaving your IDE.

Namespace tree
namespace
client
└── sdk                              // All SDK-level resources
    └── chat                         // Conversational form-filling
        └── sessions
            └── .create()            // POST /v1/sdk/chat/sessions
REST mapping reference
Property chainHTTP methodPath
client.sdk-/v1/sdk
client.sdk.chat-/v1/sdk/chat
client.sdk.chat.sessions-/v1/sdk/chat/sessions
client.sdk.chat.sessions.create()POST/v1/sdk/chat/sessions
client.sdk
Root SDK namespace

The top-level namespace for every Pdffillr API resource. All features and endpoints are nested under this property. Think of it as the root of the resource tree - everything you can do with the API starts here.

TIPType "client.sdk." in your editor to see all available sub-namespaces via autocomplete.
client.sdk.chat
Chat resource group

Groups all resources related to AI-driven, conversational form-filling. The chat layer is responsible for the back-and-forth interaction between the end user and the Pdffillr AI engine - guiding a user through a form field by field, validating responses in real time.

TIPMore resources will be added under client.sdk.chat as the API grows.
client.sdk.chat.sessions
Sessions resource

The sessions resource manages the full lifecycle of a chat session - from creation through to the final filled PDF and JSON output. Each call to sessions.create() opens a fresh, isolated session context on Pdffillr. Sessions are the primary unit of work in the platform.

TIPEach session is independent. You can have multiple sessions running concurrently.
The namespace hierarchy grows with the API
As new Pdffillr endpoints are released, they will appear as additional methods or sub-namespaces within the existing hierarchy. Upgrading the SDK package automatically makes new resources available through the same chaining pattern - no structural changes to your code are needed.

3. TypeScript Support

The SDK is written in TypeScript and ships its compiled JavaScript output alongside bundled .d.ts declaration files. This means you get complete, accurate type information in any editor that supports the TypeScript Language Server - including VS Code, WebStorm, and Neovim with LSP - without installing any additional package or changing your tsconfig.json.

What your editor shows you

Method autocompleteType "client.sdk." and your editor lists every available namespace and method with inline documentation. No need to consult external docs for method names.
Response shape inferenceThe return type of every method is inferred from the SDK's built-in types. Hover over the resolved value to see the full object shape without leaving your editor.
Compile-time errorsPassing the wrong type to a method - a number where a string is expected, or a missing required option - is caught at compile time, not at runtime in production.
Type inference in practice - no annotation needed
typed-usage.ts
import 'dotenv/config';
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'],
});

// TypeScript infers the return type automatically.
// Hover over 'session' in your editor to see the full type.
const session = await client.sdk.chat.sessions.create();

// No manual type annotation needed - your editor already knows
// the shape of every property on the response object.

Module system compatibility

Module systemImport syntaxWhen to use
ESM (recommended)import Pdffillr from …TypeScript projects, or package.json "type": "module"
CommonJSrequire('@pdffillr/sdk')Legacy Node.js projects without ESM configured
TypeScript is entirely optional
The SDK works in plain JavaScript with zero changes. You lose compile-time type checking but retain full runtime behaviour. If you later migrate to TypeScript, the types are already bundled in the package - no reinstall or reconfiguration needed.

4. Error Handling

Every SDK method that makes a network call returns a Promise. When something goes wrong - an invalid API key, a rate-limit breach, a malformed request, or a transient server fault - the Promise rejects with aPdffillr.APIError subclass. Robust error handling is not optional in production: unhandled rejections crash Node.js processes, and silently swallowed errors hide outages from your monitoring stack.

Basic pattern - catch, log, re-throw
error-basic.ts
import 'dotenv/config';
import Pdffillr from '@pdffillr/sdk';

const client = new Pdffillr({
  apiKey: process.env['PDFFILLR_API_KEY'],
});

try {
  const session = await client.sdk.chat.sessions.create();
  console.log('Session ready:', session);
} catch (err) {
  // Log the failure - never swallow errors silently.
  console.error('SDK request failed:', err);

  // Re-throw so the caller or process handler can decide
  // whether to retry, alert, or gracefully shut down.
  throw err;
}

Common failure scenarios

401 Unauthorized
Cause

The API key is missing, malformed, expired, or revoked.

Fix

Verify PDFFILLR_API_KEY is set correctly and that the key is active in the dashboard.

429 Too Many Requests
Cause

Your application is sending more requests than the rate limit allows.

Fix

Implement exponential back-off before retrying. Do not retry immediately - that makes the problem worse.

Network error / ECONNREFUSED
Cause

The Node.js process cannot reach the Pdffillr API - firewall, DNS, or VPN issue.

Fix

Confirm that outbound HTTPS is permitted from your server. Check DNS resolution for the API hostname.

5xx Server Error
Cause

A transient fault on Pdffillr - the platform is degraded or deploying.

Fix

Retry with exponential back-off. Check the Pdffillr status page. 5xx errors are usually short-lived.

Production pattern - retry with exponential back-off

For transient server errors (5xx) and rate-limit responses (429), retrying with increasing delays is the correct production pattern. Client errors (4xx) must not be retried - they will not self-resolve.

retry-pattern.ts
import Pdffillr from '@pdffillr/sdk';

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

const session = await client.sdk.chat.sessions
  .create({ title: 'My session' })
  .catch(async (err) => {
    if (err instanceof Pdffillr.APIError) {
      console.log(err.status); // 400
      console.log(err.name); // BadRequestError
      console.log(err.headers); // {server: 'nginx', ...}
    } else {
      throw err;
    }
  });
Three rules for production error handling
1.Always log before re-throwing. A log entry is how you know an error happened. Re-throwing ensures the failure propagates to your top-level handler rather than being silently swallowed.2.Never retry 4xx errors. A 401, 403, or 422 indicates a problem with your request - retrying immediately will just produce the same error and consume rate-limit quota.3.Use back-off for 429 and 5xx. Exponential back-off with jitter is the industry-standard pattern. Retrying immediately under rate-limit or server stress makes both problems worse.

Next steps

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