npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@suparse/sdk

v1.3.1

Published

Official TypeScript SDK for the Suparse Document Processing API

Readme

@suparse/sdk

npm version

Official JavaScript and TypeScript SDK for the Suparse Document Processing API.

Suparse is an AI-powered document processing API for extracting structured data from any document type, including invoices, receipts, bank statements, purchase orders and many more.

Requirements

  • Node.js 20+
  • Browser, edge, or Node.js runtime with fetch, Blob, and FormData

Installation

npm install @suparse/sdk

Authentication

You'll need an API key to use the SDK. To obtain one:

  1. Sign in at suparse.com
  2. Go to the API Keys tab
  3. Enter a key name and click Generate New Key
  4. Copy the key value. It will be shown only once.

Set it as an environment variable when using the Node client:

export SUPARSE_API_KEY="your_api_key_here"

Or pass it directly to the SDK constructor:

import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient({ apiKey: "your_api_key_here" });

Browser Key Safety

Do not put an unrestricted Suparse API key in browser code, public repositories, or client-side bundles. Browser users can inspect bundled JavaScript and network requests.

Use SuparseClient directly in the browser only with a key that Suparse explicitly marks as safe for public browser use, with origin, permission, and quota limits that match your application. Otherwise, keep SUPARSE_API_KEY on your server or edge runtime and have the browser call your own authenticated endpoint.

Quick Start

// Node.js SDK, with SUPARSE_API_KEY set
import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient();

try {
  const result = await client.extract("invoice.pdf");

  for (const item of result.succeeded) {
    console.log(item.original_file);
    console.log(item.documents.map((doc) => doc.extracted_data));
  }
} finally {
  await client.close();
}
// Browser runtime calling your server or edge proxy
const file = new File([fileBytes], "invoice.pdf", { type: "application/pdf" });
const formData = new FormData();
formData.append("file", file);

const response = await fetch("/api/suparse/extract", {
  method: "POST",
  body: formData,
});

const result = await response.json();
console.log(result.succeeded);

SDK Usage

The SDK exports two clients:

  • SuparseClient from @suparse/sdk: browser/edge-compatible client for Blob, File, and URL inputs
  • SuparseNodeClient from @suparse/sdk/node: Node.js client with file paths, folder processing, and disk output helpers

Both clients handle uploads, polling, exports, retries, rate limits, and parallel batch processing. Batch extraction runs up to 10 files concurrently.

Node.js

Use @suparse/sdk/node for local files and server-side applications.

import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient();

try {
  const result = await client.extract(["invoice1.pdf", "invoice2.pdf"]);

  for (const item of result.succeeded) {
    console.log(item.original_file);
    console.log(item.documents.map((doc) => doc.extracted_data));
  }

  for (const failed of result.failed) {
    console.error(failed.file, failed.error);
  }
} finally {
  await client.close();
}

The Node client reads SUPARSE_API_KEY and SUPARSE_API_URL from environment variables by default, so you can use new SuparseNodeClient() if those are set. Pass apiKey and baseUrl directly when you do not want to use environment variables.

Browser and Edge

Use @suparse/sdk for runtimes without Node.js file-system APIs.

In browser applications, call your server or edge proxy by default so the Suparse API key stays outside the client bundle:

const formData = new FormData();
formData.append("file", fileInput.files![0]);

const response = await fetch("/api/suparse/extract", {
  method: "POST",
  body: formData,
});

const result = await response.json();

for (const item of result.succeeded) {
  console.log(item.documents.map((doc) => doc.extracted_data));
}

On a server or edge route, keep the API key in the runtime environment and call Suparse from there:

import { SuparseClient } from "@suparse/sdk";

const client = new SuparseClient({ apiKey: process.env.SUPARSE_API_KEY! });

export async function POST(request: Request): Promise<Response> {
  const formData = await request.formData();
  const file = formData.get("file");

  if (!(file instanceof File)) {
    return Response.json({ error: "file is required" }, { status: 400 });
  }

  const result = await client.extract(file, { split: true });
  return Response.json(result);
}

Only skip the proxy when the key is explicitly browser-restricted by Suparse for public use.

You can also pass a URL; the SDK fetches it and uploads the response body:

const result = await client.extract(new URL("https://example.com/invoice.pdf"));

Extract One or More Documents

extract() is the primary SDK API.

Node.js File Paths

import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient();

const result = await client.extract("invoice.pdf", {
  template_id: "276a0aa8-84bc-4491-a2e7-1ea13381790c",
  split: true,
  cleanup: true,
  onProgress: (item) => {
    if ("file" in item) {
      console.error(`Failed: ${item.file} - ${item.error}`);
    } else {
      console.log(`Done: ${item.original_file}`);
    }
  },
});

SuparseNodeClient accepts a single file path, an array of file paths, Blob/File objects, URL objects, or an array mixing those input types.

Batch Processing

const result = await client.extract(["receipts/jan.pdf", "receipts/feb.pdf"]);

for (const item of result.succeeded) {
  console.log(item.original_file, item.documents);
}

for (const failed of result.failed) {
  console.error(failed.file, failed.error);
}

console.log(`Total: ${result.total}`);

Browser Files

The same key-safety rule applies here: use this direct browser pattern only with a browser-restricted public key. Use a server or edge proxy for unrestricted API keys.

import { SuparseClient } from "@suparse/sdk";

const client = new SuparseClient({ apiKey: "browser_restricted_public_key" });
const files = Array.from(fileInput.files ?? []);

const result = await client.extract(files, {
  split: false,
  auto_approve: true,
});

SuparseClient accepts Blob, File, and URL inputs. Use SuparseNodeClient when you need local file paths or disk output helpers.

Extract a Folder

extractFolder() is available from SuparseNodeClient. It scans a directory for supported files and delegates to extract().

import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient();

const result = await client.extractFolder("./receipts/", {
  template_id: "276a0aa8-84bc-4491-a2e7-1ea13381790c",
  split: true,
  cleanup: true,
});

for (const item of result.succeeded) {
  console.log(item.original_file, item.documents);
}

extractFolder() scans the immediate directory only, filters to supported extensions, sorts the files by name, and returns an empty BatchResult when no supported files are found.

Result Data

Each successful item is a TaskExport. Its documents array contains the extracted document records and parsed fields:

for (const item of result.succeeded) {
  console.log(item.task_id);
  console.log(item.original_file);

  for (const document of item.documents) {
    console.log(document.document_id);
    console.log(document.template_id);
    console.log(document.page_start, document.page_end);
    console.log(document.credits_used);
    console.log(document.extracted_data);
  }
}

For single-page documents, documents usually has one entry. When split is enabled, a single uploaded PDF can produce multiple document entries with their own page ranges and template IDs.

Low-Level API

Use the low-level methods when you need direct control over upload, polling, export, and deletion.

import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient();

// Upload a file and get back a task ID
const taskId = await client.uploadFile("invoice.pdf", {
  template_id: "276a0aa8-84bc-4491-a2e7-1ea13381790c",
  split: false,
  auto_approve: true,
});

// Poll until processing completes
const { status, documentIds } = await client.pollTaskStatus(taskId);

// Fetch JSON results in memory
const exportsJson = await client.fetchResults(documentIds);

// Fetch a CSV/XLSX export in memory. The API may return a ZIP when
// multiple files are generated.
const xlsxExport = await client.fetchResults(documentIds, {
  format: "xlsx",
  export_type: "unified",
});
console.log(xlsxExport.filename, xlsxExport.contentType, xlsxExport.isZip);

// Export to Google Sheets. This requires a working Google integration.
const sheetsExport = await client.fetchResults(documentIds, {
  format: "google_sheets",
});
console.log(sheetsExport.spreadsheet_url ?? sheetsExport.folder_url);

// Or write results to disk. JSON remains the default format.
await client.downloadResults(documentIds, "output.json");

// For file formats, omit the output path to use the API filename,
// or pass a directory/file path explicitly.
await client.downloadResults(documentIds, "./exports", {
  format: "csv",
  export_type: "original",
});

// Delete documents by ID
await client.deleteDocuments(["550e8400-e29b-41d4-a716-446655440000"]);

// List available templates
const templates = await client.listTemplates();
for (const template of templates) {
  console.log(`${template.name} (${template.template_language})`);
}

// Include system templates too
const allTemplates = await client.listTemplates({ includeSystem: true });

Browser and edge runtimes can use uploadFromSource() instead of uploadFile(). In browser code, only pass a browser-restricted public key directly; otherwise call uploadFromSource() from your server or edge proxy.

import { SuparseClient } from "@suparse/sdk";

const client = new SuparseClient({ apiKey: "browser_restricted_public_key" });

const taskId = await client.uploadFromSource(fileInput.files![0], {
  split: true,
  auto_approve: true,
});
const { documentIds } = await client.pollTaskStatus(taskId);
const exportsJson = await client.fetchResults(documentIds);

Export Formats

JSON is the default export format for extract(), fetchResults(), downloadResults(), and processDocument() workflows. The low-level export helpers also support the formats exposed by the Suparse API:

| Format | SDK result | Notes | | --------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------- | | json | TaskExport[] | Default structured extraction result | | csv | FileExport with data, filename, contentType, and isZip | Saves as CSV or ZIP depending on the API response | | xlsx | FileExport with data, filename, contentType, and isZip | Saves as XLSX or ZIP depending on the API response | | google_sheets | GoogleSheetsExport | Returns spreadsheet or folder URLs; requires Google integration |

export_type can be "unified" or "original" and defaults to "unified". It affects csv, xlsx, and google_sheets exports. JSON currently returns the same task-oriented shape for either export type.

Node Convenience Methods

SuparseNodeClient also exposes convenience methods for file-based workflows:

import { SuparseNodeClient } from "@suparse/sdk/node";

const client = new SuparseNodeClient();

// Process one document and write the JSON export to disk.
await client.processDocument("invoice.pdf", "results.json", {
  template_id: "276a0aa8-84bc-4491-a2e7-1ea13381790c",
  split: false,
  auto_approve: true,
  cleanup: true,
});

// Process one document and write an XLSX export to disk.
await client.processDocument("invoice.pdf", "./exports", {
  format: "xlsx",
  export_type: "unified",
});

// Process multiple files and receive raw task/document IDs.
const { succeeded, failed } = await client.processBatch(["a.pdf", "b.pdf"], {
  template_id: "276a0aa8-84bc-4491-a2e7-1ea13381790c",
  split: true,
});

for (const item of succeeded) {
  console.log(item.filePath, item.taskId, item.documentIds);
}

for (const item of failed) {
  console.error(item.filePath, item.taskId, item.error);
}

Error Handling

All SDK exceptions inherit from SuparseError.

import {
  SuparseNodeClient,
  SuparseError,
  SuparseAuthError,
  SuparseNetworkError,
  SuparsePollingTimeoutError,
} from "@suparse/sdk/node";

const client = new SuparseNodeClient({ apiKey: "your_api_key_here" });

try {
  const result = await client.extract("invoice.pdf");
  console.log(result.succeeded);
} catch (error) {
  if (error instanceof SuparseAuthError) {
    console.error("Invalid API key");
  } else if (error instanceof SuparseNetworkError) {
    console.error("Connection failed");
  } else if (error instanceof SuparsePollingTimeoutError) {
    console.error("Processing timed out");
  } else if (error instanceof SuparseError) {
    console.error(`Unexpected Suparse error: ${error.message}`);
  } else {
    throw error;
  }
}

For batch operations, check result.failed to handle per-file errors without catching exceptions:

const result = await client.extract(["a.pdf", "b.pdf", "c.pdf"]);

for (const item of result.succeeded) {
  console.log(`OK: ${item.original_file} -> ${item.documents.map((doc) => doc.document_id)}`);
}

for (const failed of result.failed) {
  console.error(`FAIL: ${failed.file} -> ${failed.error}`);
}

Reference

Constructor Parameters

SuparseClient requires apiKey directly. In browser code, that must be a browser-restricted public key; keep unrestricted keys on a server or edge runtime. SuparseNodeClient can read apiKey and baseUrl from environment variables.

| Parameter | Type | Default | Description | | ----------------- | -------- | ------------------------------------------------------------- | --------------------------------------------------- | | apiKey | string | SUPARSE_API_KEY in SuparseNodeClient only | Your API key. Use only browser-restricted public keys in browser code | | baseUrl | string | SUPARSE_API_URL env var or https://api.suparse.com/api/v1 | API base URL | | timeoutMs | number | 60000 | Request timeout in milliseconds | | maxRetries | number | 3 | Max retry attempts for retryable network/API errors | | pollInterval | number | 5 | Initial seconds between polling attempts | | maxPollAttempts | number | 300 | Max polling attempts before timeout |

Polling uses exponential backoff starting from pollInterval seconds and caps the delay at 15 seconds. maxPollAttempts limits the total number of poll attempts before SuparsePollingTimeoutError is thrown.

Result Objects

| Object | Properties | Description | | ---------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------ | | TaskExport | task_id, original_file, total_documents_extracted, documents | Successfully extracted file | | DocumentExport | document_id, file_name, page_start, page_end, template_id, credits_used, extracted_data | Extracted document and parsed fields | | ExtractionTemplateSummary | id, name, description, template_language, template_group_id, parent_template_id, version, team_id, is_active, is_system_template, created_at | Template summary returned by listTemplates | | FileExport | format, contentType, filename, isZip, data | In-memory CSV/XLSX export bytes | | GoogleSheetsExport | message, spreadsheet_id, spreadsheet_url, folder_url, spreadsheets | Google Sheets export response | | FailedResult | file, error | File that failed during extraction | | BatchResult | succeeded, failed, total | Container for batch results |

Export Options

| Option | Values | Default | Description | | ------------- | --------------------------------------- | ----------- | --------------------------------------------------------------- | | format | json, csv, xlsx, google_sheets | json | Export format for fetchResults, downloadResults, and processDocument | | export_type | original, unified | unified | Export mode for CSV, XLSX, and Google Sheets exports |

Exceptions

All exceptions inherit from SuparseError.

| Exception | Raised When | | ---------------------------- | ------------------------------------------------------------------ | | SuparseError | Base exception for all SDK errors | | SuparseNetworkError | Network connection fails or times out | | SuparsePollingTimeoutError | Polling exceeds maxPollAttempts | | SuparseProcessingError | Document fails to process on the server | | SuparseAPIError | Base for HTTP error responses; has statusCode and responseBody | | SuparseAuthError | 401/403 authentication or authorization error | | SuparseNotFoundError | 404 resource not found | | SuparseRateLimitError | 429 too many requests | | SuparseServerError | 5xx server error | | SuparseSDKError | SDK fails to parse or handle the expected API response |

extract() Parameters

| Parameter | Type | Default | Description | | -------------- | ---------------------------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------- | | files | Node: string, Blob, File, URL, or array; browser/edge: Blob, File, URL, or array | required | One or more files to process | | template_id | string | undefined | Template ID (auto-detect if omitted) | | split | boolean | false | Auto-split multi-page documents | | auto_approve | boolean | true | Set to false to require human review in the Suparse UI | | cleanup | boolean | false | Delete documents from server after extraction | | onProgress | (result) => void | undefined | Called with each TaskExport or FailedResult as it completes |

cleanup deletes the uploaded parent task documents after results have been fetched. Deleting a parent document also deletes its child documents server-side.

extractFolder() Parameters

extractFolder() is available only in @suparse/sdk/node.

| Parameter | Type | Default | Description | | -------------- | ------------------ | ------------------ | ------------------------------------------------------------------------------------------ | | folder | string | required | Directory to scan | | template_id | string | undefined | Template ID (auto-detect if omitted) | | split | boolean | false | Auto-split multi-page documents | | auto_approve | boolean | true | Set to false to require human review in the Suparse UI | | cleanup | boolean | false | Delete documents from server after extraction | | onProgress | (result) => void | undefined | Called with each result as it completes |

Supported Files

| Extension | MIME Type | | --------------- | ----------------- | | .pdf | application/pdf | | .jpg, .jpeg | image/jpeg | | .png | image/png | | .heic | image/heic | | .heif | image/heif |

CLI

The companion CLI is published as @suparse/cli:

npm install -g @suparse/cli
suparse process invoice.pdf -o results.json

Documentation

Full API documentation is available at suparse.com/docs.

License

MIT