Installation
Requirements: Node.js 18+ or compatible runtime (Bun, Deno). TypeScript 4.7+ recommended.
The SDK is published with both CommonJS and ES Modules (ESM) support.
Client Setup
import { Factify } from "@factify/sdk";
const factify = new Factify({
bearerAuth: process.env.FACTIFY_KEY,
});
Configuration Options
| Option | Type | Default | Description |
|---|
bearerAuth | string | — | API key (required). Format: ffy_... |
serverURL | string | https://api.factify.com | API base URL |
timeoutMs | number | undefined | Request timeout in milliseconds |
retryConfig | RetryConfig | SDK default | Retry strategy configuration |
debugLogger | Logger | undefined | Enable debug logging |
const factify = new Factify({
bearerAuth: process.env.FACTIFY_KEY,
serverURL: "https://api.factify.com",
timeoutMs: 30000,
retryConfig: {
strategy: "backoff",
backoff: {
initialInterval: 1,
maxInterval: 50,
exponent: 1.1,
maxElapsedTime: 100,
},
},
});
Debug logging reveals secrets like API tokens. Only use during local development.
Available Resources
Documents
factify.documents.list({ pageSize, query, createdById, accessLevel, processingStatus, sort, ownership, trashState })
factify.documents.create({ title, payload: { fileName, content } })
factify.documents.get({ documentId })
factify.documents.update({ documentId, title, description })
factify.documents.export({ documentId })
factify.documents.process({ documentId })
factify.documents.trash({ documentId })
factify.documents.untrash({ documentId })
factify.documents.transferOwnership({ documentId, newOwnerUserId })
factify.documents.listDuplicates({ documentId })
factify.documents.getQuota()
Versions
factify.versions.list({ documentId })
factify.versions.create({ documentId, payload: { fileName, content } })
factify.versions.get({ versionId })
factify.versions.update({ versionId, description })
Organizations
factify.organizations.list()
factify.organizations.get({ organizationId })
factify.organizations.update({ organizationId, name })
factify.organizations.getPublicProfile({ organizationId })
Members
factify.organizations.members.list({ organizationId })
factify.organizations.members.add({ organizationId, userId, role })
factify.organizations.members.update({ organizationId, userId, role })
factify.organizations.members.remove({ organizationId, userId })
Invites
factify.organizations.invites.list({ organizationId })
factify.organizations.invites.create({ organizationId, email, role })
factify.organizations.invites.accept({ organizationId })
factify.organizations.invites.resend({ organizationId, inviteId })
factify.organizations.invites.revoke({ organizationId, inviteId })
API Keys
factify.apiKeys.list({ organizationId })
factify.apiKeys.create({ organizationId, name })
factify.apiKeys.revoke({ apiKeyId })
Sharing
factify.sharing.list({ documentId })
factify.sharing.grant({ documentId, recipientId, role })
factify.sharing.update({ documentId, recipientId, role })
factify.sharing.revoke({ documentId, recipientId })
factify.sharing.getGeneralAccess({ documentId })
factify.sharing.setGeneralAccess({ documentId, accessLevel })
factify.sharing.createShareLink({ documentId })
Policies
factify.policies.list({ documentId })
factify.policies.attach({ documentId, kind })
factify.policies.detach({ documentId, policyId })
Access Requests
factify.accessRequests.list({ documentId })
factify.accessRequests.create({ documentId })
factify.accessRequests.checkStatus({ documentId })
factify.accessRequests.approve({ documentId, accessRequestId })
factify.accessRequests.deny({ documentId, accessRequestId })
factify.accessRequests.inspect({ documentId })
Usage & Quotas
factify.usage.get()
factify.usage.getHistory()
factify.usage.listKeyQuotas()
factify.usage.setKeyQuota({ apiKeyId, monthlyLimit })
factify.usage.deleteKeyQuota({ apiKeyId })
Timelines
factify.timelines.get({ documentId })
Users
factify.users.getMe()
factify.users.preferences.get()
List endpoints return async iterables. Use for await...of to auto-paginate:
const result = await factify.documents.list({ pageSize: 10 });
for await (const page of result) {
// Each page contains an array of documents
console.log(page.documents);
}
Or handle pages manually:
const result = await factify.documents.list({ pageSize: 10 });
// First page
const firstPage = await result.next();
console.log(firstPage.value.documents);
// Check if more pages exist
if (!firstPage.done) {
const secondPage = await result.next();
}
File Uploads
Pass a file stream or Blob as the content field:
import { openAsBlob } from "node:fs";
const result = await factify.documents.create({
title: "Q4 Financial Report",
payload: {
fileName: "report.pdf",
content: await openAsBlob("./report.pdf"),
},
});
Error Handling
import { Factify } from "@factify/sdk";
import * as errors from "@factify/sdk/models/errors";
try {
const doc = await factify.documents.get({ documentId: "doc_abc123" });
} catch (error) {
if (error instanceof errors.FactifyError) {
console.log(error.message);
console.log(error.httpMeta.response.status);
if (error instanceof errors.ErrorT) {
console.log(error.data$.error);
}
}
}
| Error Class | When |
|---|
FactifyError | Base class for all HTTP errors |
ErrorT | Structured API error (4xx/5xx with body) |
ConnectionError | Unable to reach server |
RequestTimeoutError | Request timed out |
RequestAbortedError | Request was cancelled |
ResponseValidationError | Response doesn’t match expected schema |
Retries
Override retry behavior per-call:
import { Factify } from "@factify/sdk";
const result = await factify.documents.list(
{ pageSize: 10 },
{
retries: {
strategy: "backoff",
backoff: {
initialInterval: 1,
maxInterval: 50,
exponent: 1.1,
maxElapsedTime: 100,
},
},
}
);
Standalone Functions
All methods are also available as standalone functions for tree-shaking in browser and serverless environments:
import { FactifyCore } from "@factify/sdk/core.js";
import { documentsList } from "@factify/sdk/funcs/documentsList.js";
const client = new FactifyCore({
bearerAuth: process.env.FACTIFY_KEY,
});
const result = await documentsList(client, { pageSize: 10 });
Source & Issues