Suparse

JS / TS SDK & CLI

Ostatnia aktualizacja: 2026-10-15

Suparse JavaScript SDK and CLI

Official JavaScript/TypeScript SDK and CLI 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. Use the SDK in your application or the CLI from your terminal:

  • @suparse/sdk: TypeScript SDK for browser, edge, and Node.js runtimes
  • suparse: command-line interface for processing documents from your terminal

Jump to Quick Start, CLI Usage, SDK Usage, Export Choices, Advanced Recovery, or Reference.

Requirements

  • Node.js 20+
  • Package manager: npm, pnpm, yarn, or bun

Installation

Install the SDK:

npm install @suparse/sdk

Install the CLI globally:

npm install -g @suparse/cli

Or run the CLI without a global install:

npx @suparse/cli process invoice.pdf -o results.json

Authentication

You'll need an API key to use the SDK or CLI. 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:

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

Keep your Suparse API key on your server or edge runtime. Do not put it in browser code, public repositories, or client-side bundles: browser users can inspect JavaScript and network requests.

The browser examples on this page call your own authenticated endpoint, which uses SUPARSE_API_KEY on the server. See the Next.js proxy example for an implementation.

Quick Start

# CLI
suparse process invoice.pdf -o results.json
// 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));
  }
 
  // Individual files can fail even when extract() returns successfully.
  for (const failed of result.failed) {
    console.error(failed.file, failed.error);
  }
} finally {
  await client.close();
}

Browser Quick Start

/api/suparse/extract is a route you must implement in your application; the SDK does not create it. First add the authenticated Next.js proxy, configure its application authentication, and set SUPARSE_API_KEY in the server environment.

Add a file input to your page:

<input id="invoice" type="file" accept="application/pdf,image/*" />

Run this TypeScript in your browser entry point or a client component after the input is mounted. The request uses the signed-in user's same-origin session cookie:

const fileInput = document.querySelector<HTMLInputElement>("#invoice")!;
 
fileInput.addEventListener("change", async () => {
  const file = fileInput.files?.[0];
  if (!file) return;
 
  const formData = new FormData();
  formData.append("file", file);
 
  const response = await fetch("/api/suparse/extract", {
    method: "POST",
    body: formData,
  });
 
  if (!response.ok) {
    console.error(`Extraction request failed: ${response.status}`);
    return;
  }
 
  const result = await response.json();
  for (const item of result.succeeded) {
    console.log(item.documents.map((doc) => doc.extracted_data));
  }
  for (const failed of result.failed) {
    console.error(failed.file, failed.error);
  }
});

CLI Usage

Run suparse --help or suparse <command> --help for full usage information.

Set your API key and process a file directly from the terminal. The CLI will auto-upload, poll, and download the resulting JSON. JSON is the default export format.

Process a Document

export SUPARSE_API_KEY="your_api_key_here"
 
# Auto-detect template
suparse process path/to/invoice.pdf -o results.json
 
# Export as XLSX with the flat layout. The default layout is standard.
suparse process path/to/invoice.pdf --format xlsx --xlsx-layout flat
 
# Export as CSV using each document's original template
suparse process path/to/invoice.pdf --format csv --export-type original
 
# Use a specific template without auto-splitting
suparse process path/to/invoice.pdf --template-id 276a0aa8-84bc-4491-a2e7-1ea13381790c
 
# Auto-split a multi-page PDF containing mixed document types
suparse process path/to/merged.pdf --with-split
 
# Use a specific template with auto-splitting
suparse process path/to/invoice.pdf --template-id 276a0aa8-84bc-4491-a2e7-1ea13381790c --with-split
 
# Process and auto-delete documents from the server after download
suparse process path/to/invoice.pdf --cleanup
 
# Assign uploads to a remote folder
suparse process path/to/invoice.pdf --folder-id <folder-id>
 
# Prompt without echoing for an encrypted PDF password
suparse process path/to/encrypted.pdf --prompt-pdf-password

Export Existing Documents

Export one or more processed documents by ID:

# Export a document to XLSX with the flat layout
suparse export <document-id> --format xlsx --xlsx-layout flat
 
# Export several documents using the default standard XLSX layout
suparse export <document-id-1> <document-id-2> --format xlsx

When -o is omitted, file exports use the filename returned by the API. The --xlsx-layout option accepts standard or flat and defaults to standard.

Process a Folder

Process all supported files (.pdf, .jpg, .jpeg, .png, .heic, .heif) in a folder. Files are uploaded and polled individually. For JSON, each source has its own export request and the results are combined into a single JSON file. CSV and XLSX use an aggregate export request and may be saved as a direct file or ZIP depending on the API response.

# Process all supported files in a folder
suparse process --folder path/to/receipts/
 
# Output to a specific file (default: {folder_name}_results.json)
suparse process --folder path/to/receipts/ -o all_results.json
 
# Export a folder as CSV or XLSX
suparse process --folder path/to/receipts/ --format csv
suparse process --folder path/to/receipts/ --format xlsx --xlsx-layout flat -o ./exports
 
# Export to Google Sheets. This requires a working Google integration.
suparse process --folder path/to/receipts/ --format google_sheets
 
# Process a folder with a specific template
suparse process --folder path/to/receipts/ --template-id 276a0aa8-84bc-4491-a2e7-1ea13381790c
 
# Process a folder with auto-splitting enabled
suparse process --folder path/to/receipts/ --with-split
 
# Process a folder and auto-delete documents from the server after download
suparse process --folder path/to/receipts/ --cleanup
 
# Apply one remote folder and prompted PDF password to every file in the batch
suparse process --folder path/to/receipts/ \
  --folder-id <folder-id> --prompt-pdf-password

--prompt-pdf-password requires an interactive TTY, never echoes the password, and restores terminal state when the prompt exits. There is intentionally no plaintext --pdf-password option. The same password and folder ID are forwarded to every file in a local-folder batch.

Quick schema creation

Start automatic schema creation for one document:

suparse quick-create invoice.pdf
suparse quick-create invoice.pdf --wait --format json
suparse quick-create encrypted.pdf --prompt-pdf-password --folder-id <folder-id>

Inspect one status without polling:

suparse quick-create-status <run-id>
suparse quick-create-status <run-id> --format json

Quick-create also accepts --upload-batch-id and --source-upload-id for advanced replay workflows. Upload-batch creation is outside the endpoint set currently exposed by this SDK, so those IDs must come from another workflow. JSON output includes the full API response, including any error details. Human output includes the run ID, status/stage, path, template IDs, progress counts, and retryability when available.

Multiple-document completions additionally list every saved document with its ordinal, page range, template ID, and template group ID, followed by each failed document's page range, error code, and retryability.

Exit codes

quick-create --wait and quick-create-status use the terminal result to pick the process exit code so scripts can branch without parsing output:

Terminal statusExit code
completed0
completed_with_errors1
failed1

quick-create without --wait exits 0 after the run is accepted.

For interrupted jobs or partial results, see CLI recovery.

Delete Documents

# Delete one or more documents by ID (prompts for confirmation)
suparse delete <document_id>
suparse delete <id1> <id2> <id3>
 
# Skip confirmation prompt
suparse delete <id1> <id2> -y

Deleting a parent document automatically deletes all its child documents server-side.

List Available Templates

Templates define how a document type (invoice, receipt, bank statement, etc.) is parsed. Before processing a document, check which templates are already assigned to your account:

# List templates assigned to your account (table format)
suparse templates
 
# List templates in JSON format
suparse templates --format json
 
# Include all system templates
suparse templates --include-system
 
# Request full template records (summary remains the default)
suparse templates --view full --format json

The recommended way to process documents is with auto-split enabled (--with-split), which handles both single-type and mixed document types automatically:

suparse process path/to/documents.pdf --with-split -o results.json

If you consistently process one document type, look up the template ID and pass it directly:

  1. Run suparse templates to see templates assigned to your account.

  2. Use the matching template ID:

    suparse process invoice.pdf --template-id <id> -o results.json
  3. If no template matches, run suparse templates --include-system to browse all system templates. Assign one to your account via the Suparse UI.

  4. If no system template fits, create a custom template using the template creator in the Suparse UI.

Export Formats

The process command supports these export formats:

FormatOutput behavior
jsonDefault. Writes the task-oriented JSON export to {file_stem}_results.json or {folder_name}_results.json
csvSaves a CSV file or ZIP archive, using the API filename when -o is omitted
xlsxSaves an XLSX file or ZIP archive, using the API filename when -o is omitted
google_sheetsWrites the Google Sheets JSON response, including spreadsheet or folder URLs

--export-type original|unified defaults to unified and affects CSV, XLSX, and Google Sheets exports. See Export Choices for template mapping and XLSX layout examples. JSON remains the default when --format is not provided.

Configuration

The CLI reads settings from global flags, environment variables, and the config file at ~/.config/suparse/config.json.

VariableDefaultDescription
SUPARSE_API_URLhttps://api.suparse.com/api/v1API base URL
SUPARSE_API_KEY-Your API key (required)
SUPARSE_CONFIG_PATH~/.config/suparse/config.jsonOptional config file override

API key priority: --api-key > SUPARSE_API_KEY > the selected config file. The config file should contain an apiKey string field. Set SUPARSE_CONFIG_PATH to select a different file; otherwise ~/.config/suparse/config.json is used. API URL priority: --api-url > SUPARSE_API_URL > default.

Global Options

These options apply to all subcommands.

OptionDescription
--api-urlAPI URL (default: from SUPARSE_API_URL env var)
--api-keyAPI key (default: from env var or config file)
-v, --verboseEnable verbose output

CLI Options

CommandOptionDescription
process--folderProcess all supported files in a folder
process-o, --outputOutput file path, or directory for CSV/XLSX exports
process--formatExport format: json, csv, xlsx, or google_sheets (default: json)
process--export-typeExport mode: original or unified (default: unified)
process--xlsx-layoutXLSX layout: standard or flat (default: standard)
process--template-idTemplate ID to use (default: auto-detect)
process--folder-idAssign uploaded documents to a remote folder
process--prompt-pdf-passwordPrompt securely for an encrypted-PDF password
process--with-splitAuto-split multi-page documents containing mixed document types
process--cleanupDelete documents from server after download
templates--formatOutput format: table or json (default: table)
templates--include-systemInclude system templates
templates--viewTemplate response view: summary or full (default: summary)
quick-create--waitPoll until quick schema creation reaches a terminal result
quick-create--formatOutput format: human or json (default: human)
quick-create--folder-idAssign the source document to a remote folder
quick-create--upload-batch-idUse an existing upload batch ID (batch creation is outside this SDK)
quick-create--source-upload-idUse an existing source upload ID for replay-aware creation
quick-create--prompt-pdf-passwordPrompt securely for an encrypted-PDF password
quick-create-status--formatOutput format: human or json (default: human)
export--formatExport format: json, csv, xlsx, or google_sheets (default: json)
export-o, --outputOutput file path or directory
export--export-typeExport mode: original or unified (default: unified)
export--xlsx-layoutXLSX layout: standard or flat (default: standard)
delete-y, --yesSkip confirmation prompt
process, export, export-job-wait--wait-timeoutExport-job wait deadline in seconds (default: 900); excludes upload/task processing
process, export--idempotency-keyReuse a UUID for an identical export request; rejected for folder JSON processing
task-results--jsonlWrite one document per line instead of one JSON array
task-results--single-pageRetrieve one page instead of traversing all pages
task-results--page-sizeNumber of results requested per page
task-results--cursorResume a page; requires --single-page
task-results, export-job-download-o, --outputOutput file path
task-results, export-job-download--overwriteReplace an existing output file

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 on your server or edge runtime when Node.js file-system APIs are unavailable. Browser applications should follow the Browser Quick Start, sending files to an authenticated route in their own application.

Authenticated Next.js Proxy

For a Next.js application using the App Router, create app/api/suparse/extract/route.ts (or src/app/api/suparse/extract/route.ts if your project uses src/). Set SUPARSE_API_KEY in the server environment, such as .env.local during development. Keep it out of NEXT_PUBLIC_ variables.

This example assumes your application already uses Auth.js and exports its configured auth() helper from @/auth. That helper belongs to your application; the SDK does not provide it. If you use another authentication system, replace the import and session check with your own session verification. Authenticate the caller and check their permission to process documents before reading the upload or calling Suparse.

import { auth } from "@/auth";
import { SuparseClient } from "@suparse/sdk";
 
export const runtime = "nodejs";
 
const client = new SuparseClient({ apiKey: process.env.SUPARSE_API_KEY! });
 
export async function POST(request: Request): Promise<Response> {
  // Application authentication belongs here, before any Suparse work.
  const session = await auth();
  if (!session?.user) {
    return Response.json({ error: "Sign in required" }, { status: 401 });
  }
  // Add your application's document-processing permission check here if needed.
 
  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({
    succeeded: result.succeeded,
    failed: result.failed,
    total: result.total,
  });
}

The route checks the application's session; the Suparse API key authenticates only the server's requests to Suparse. For other server or edge frameworks, use the same sequence in their route handler and read the API key through their server-side environment API.

On your server, 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

Send each selected File to your application's proxy as shown in the Browser Quick Start. Inside the route handler, SuparseClient accepts Blob, File, and URL inputs, including arrays of those types. 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",
  xlsxLayout: "flat",
});
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 });

On a server or edge route without Node.js file-system APIs, use uploadFromSource() instead of uploadFile(). The following code runs inside your authenticated handler, where file is the uploaded File:

import { SuparseClient } from "@suparse/sdk";
 
const client = new SuparseClient({ apiKey: process.env.SUPARSE_API_KEY! });
 
const taskId = await client.uploadFromSource(file, {
  split: true,
  auto_approve: true,
});
const { documentIds } = await client.pollTaskStatus(taskId);
const exportsJson = await client.fetchResults(documentIds);

Encrypted PDFs, folders, and detailed confirmations

Upload options support encrypted PDFs and remote folders across the normal upload-backed workflows. The same pdf_password or folder_id supplied to a multi-file method is applied to every input; call a single-file method when each input needs different values.

import { SuparseNodeClient } from "@suparse/sdk/node";
 
const nodeClient = new SuparseNodeClient();
const taskId = await nodeClient.uploadFile("encrypted-invoice.pdf", {
  pdf_password: "read-from-a-secret-manager",
  folder_id: "remote-folder-id",
});

The compatibility upload methods return a pollable task ID. Advanced batch/replay integrations can inspect the complete confirmation instead:

const confirmation = await nodeClient.uploadFileDetailed("invoice.pdf", {
  upload_batch_id: "existing-batch-id",
  source_upload_id: "existing-source-id",
});

uploadFromSourceDetailed() is available on the browser client, and uploadFileDetailed()/uploadFromSourceDetailed() are available on the Node client. Advanced workflows provide their own upload-batch identifiers.

Quick schema creation

Quick schema creation accepts Blob, File, and URL through @suparse/sdk on your server or edge route, and filesystem paths through @suparse/sdk/node. The result status tells you whether the run completed, failed, or completed with some errors. This example runs on the server, with an uploaded file:

import { getQuickSchemaRunId, SuparseClient } from "@suparse/sdk";
 
const client = new SuparseClient({ apiKey: process.env.SUPARSE_API_KEY! });
const started = await client.startQuickSchemaCreation(file, {
  pdf_password: "optional-secret",
  folder_id: "remote-folder-id",
});
const terminal = await client.waitForQuickSchemaCreation(getQuickSchemaRunId(started));
console.log(terminal.status, terminal.path);

Use pollInterval and maxPollAttempts in waitForQuickSchemaCreation() to override polling defaults for one wait. getQuickSchemaCreation() performs one status request.

Full templates and single-document results

listTemplates() requests the compact summary view by default. Request full records explicitly to receive schema, prompt, validation, creator, and saved document metadata:

const fullTemplates = await client.listTemplates({ view: "full" });
const document = await client.getDocumentResult("document-id");

getDocumentResult() returns a DocumentExtractionResponse for one document. fetchResults() returns TaskExport[] for JSON, file bytes and metadata for CSV/XLSX, or spreadsheet URLs for Google Sheets.

Structured API errors

SuparseAPIError and its status-specific subclasses retain statusCode and responseBody, and also expose optional structured code and meta fields when the API supplies them. Rate-limit errors additionally expose retryAfterSeconds when available.

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:

FormatSDK resultNotes
jsonTaskExport[]Default structured extraction result
csvFileExport with data, filename, contentType, and isZipSaves as CSV or ZIP depending on the API response
xlsxFileExport with data, filename, contentType, and isZipSaves as XLSX or ZIP depending on the API response
google_sheetsGoogleSheetsExportReturns 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.

xlsxLayout accepts "standard" (the default) or "flat" and only affects XLSX exports. See Export Choices for when to use each mode and examples of both layouts.

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,
  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);
}

For interrupted jobs or partial results, see SDK recovery.

Error Handling

SDK-specific errors extend SuparseError. Local file, credential, and runtime failures can also throw standard errors.

extract() can return per-file errors in result.failed even when you pass only one file. Always check that array as well as handling exceptions thrown by the operation.

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");
  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);
  }
} 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;
  }
}

The same result handling applies when you pass multiple files:

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}`);
}

Export Choices

Choose an export format first: JSON for structured data in your application, CSV for tabular imports, XLSX for Excel, or Google Sheets for a connected spreadsheet.

Original or Unified

For CSV, XLSX, and Google Sheets, choose how templates determine the exported fields:

Export typeBehaviorUse it when
originalExports each document using the template version that processed itYou need the fields and structure used for that document, including older template versions
unified (default)Groups documents by template group and maps their data to the latest active template schemaYou want consistent columns across documents processed with different versions of the same template

For example, if you updated an invoice template, original keeps each invoice's processing template, while unified aligns invoices in that template group to the latest active schema. Different template groups can still produce separate export files; unified does not combine unrelated document types into one schema. Multiple generated files are returned as a ZIP.

Set --export-type in the CLI or export_type in SDK export options. JSON returns the same task-oriented structure for either choice. The low-level downloadDocuments() helper defaults to original; the CLI and other SDK export workflows default to unified.

Standard or Flat XLSX

XLSX also lets you choose how document fields and line items are arranged. Set --xlsx-layout in the CLI or xlsxLayout in SDK export options. This setting is independent of the export type and is ignored for other formats.

LayoutData arrangementUse it when
standard (default)Document summary fields and line items appear on separate worksheetsYou want to review document summaries and item details separately
flatA Data worksheet puts summary fields beside each line item, repeating the summary for each itemYou want to filter, pivot, or import a single table

For example, an invoice INV-42 from Acme with two items could appear as follows. These simplified tables illustrate the data arrangement; actual columns follow your template.

With standard and export_type: "unified", the summary worksheet contains one row per document:

InvoiceSupplier
INV-42Acme

With standard and export_type: "original", the summary worksheet instead lists fields as key/value pairs:

FieldValue
InvoiceINV-42
SupplierAcme

In both export types, a separate items worksheet contains the line items:

ItemQuantity
Paper2
Pens5

With flat, the Data worksheet repeats the invoice fields on each item row:

InvoiceSupplierItemQuantity
INV-42AcmePaper2
INV-42AcmePens5

Documents without line items still get one row in the flat layout. A workbook may also include validation worksheets.

# Keep each document's processing template and separate summary/item sheets.
suparse export <document-id> --format xlsx --export-type original --xlsx-layout standard
 
# Align template versions and combine summary fields with each item row.
suparse export <document-id-1> <document-id-2> --format xlsx --export-type unified --xlsx-layout flat

Advanced Recovery

Use these workflows to inspect partial results, resume an export, or recover after a timeout or interruption. For routine extraction, start with CLI Usage or SDK Usage.

CLI: Partial Task Results and Export Recovery

suparse task-results TASK_ID                     # one JSON array, all pages
suparse task-results TASK_ID --jsonl              # one document per line
suparse task-results TASK_ID --single-page --page-size 25 --cursor CURSOR
suparse task-results TASK_ID --jsonl -o results.jsonl
suparse export-job-status JOB_ID                 # full job JSON; no polling
suparse export-job-wait JOB_ID --wait-timeout 900  # seconds, default 900
suparse export-job-download JOB_ID -o result.zip  # no implicit wait or POST
suparse export DOC_ID --wait-timeout 60 --idempotency-key UUID

task-results file output and export-job-download default to no overwrite; add --overwrite explicitly to replace an existing file. Task results do not poll task completion. Null cursor ends snapshot traversal. --cursor requires --single-page; --jsonl and --single-page conflict. JSONL stdout may contain earlier lines after a later-page error; exit is nonzero. If a later page fails, no output file is saved. JSON/JSONL commands reserve stdout for data; recovery identifiers/events/errors go to stderr. Standalone job download prints only the saved path on stdout. Job inspection succeeds even for failed/unavailable states; waiting on those states fails.

Export/process support --wait-timeout (seconds, default 900), while the SDK's request timeout is separate. A folder JSON process submits per-source exports, so --idempotency-key is rejected there. An aggregate CSV/XLSX folder export may use a key. Never reuse a key across different IDs/options. Keys print before submission and accepted job IDs print before waiting. Recover by job ID without resubmission; when no ID was received, retain the key and retry the identical request.

Process failures emit Recovery record: {…} JSON lines on stderr with known task/upload/job IDs, the idempotency key, and exportRequest (exact document IDs and effective export options). Save stderr to retain these records. To replay, use suparse export with the recorded documentIds, --format, --export-type, --xlsx-layout when present, and --idempotency-key. Use these document IDs rather than running process again, which would upload new documents. Each JSON folder source has its own export request and key.

Pressing Ctrl+C stops local requests and waiting, exits with code 130, and does not save a combined result file. Counts of completed files and IDs for recovery are written to stderr. Files already saved remain available. Processing on the server continues. Cleanup is deferred for ambiguous or running work; keep task IDs for later explicit deletion. Unknown upload confirmation retains its upload reference; do not blindly upload again. Uploaded documents are automatically approved by default. SDK callers can set auto_approve: false when human review is required.

export-job-download preserves artifact bytes, verifies server size/SHA-256, and saves the file only after the download passes verification. JSON processing saves parsed TaskExport[] as JSON; use export-job-download for raw ZIP artifacts. Google Sheets exports use immediate responses; background file exports support JSON, CSV, and XLSX.

SDK: Partial Results and Recoverable Exports

// Works through both @suparse/sdk and @suparse/sdk/node.
for await (const document of client.iterTaskResults(taskId, { pageSize: 100 })) {
  console.log(document.id, document.extraction_data, document.page_start);
}
const page = await client.getTaskResults(taskId, { limit: 25, cursor: savedCursor });
// Persist page.next_cursor; null terminates this snapshot, not backend processing.
 
const controller = new AbortController();
const groups = await client.fetchResults(documentIds, {
  format: "json", waitTimeoutMs: 900_000, signal: controller.signal,
  onExportEvent: event => console.error(event),
}); // Same validated TaskExport[] for HTTP 200 or 202.
// controller.abort() stops local requests and waiting, not backend work.

timeoutMs limits individual API requests and artifact transfers in milliseconds. waitTimeoutMs limits export-job waiting (default 900000 ms), including status requests, retries and response reads. Upload, task processing, export submission and artifact transfer are separate phases. pollInterval remains seconds. An interrupted extraction rejects with SuparseAbortError.partialResult; Node processBatch retains its structured partial-result convention. Cancellation does not start remote cleanup.

For a timeout or lost response, retain error.exportJobId, error.taskId, error.uploadReferenceId, error.idempotencyKey, and error.exportRequest (document IDs and effective export options). Resume inspection/waiting with getExportJob / waitForExportJob; download a completed job without starting another export:

const job = await client.waitForExportJob(exportJobId, { waitTimeoutMs: 60_000 });
const raw = await client.fetchExportJobArtifact(job.export_job_id); // exact bytes
// Node only: verify the download and save it without replacing an existing file:
await nodeClient.downloadExportJob(job.export_job_id, "result.zip");
// Pass { overwrite: true } explicitly to replace an existing standalone artifact.

downloadDocuments(ids) requests JSON with export_type: "original" by default and returns the downloaded bytes unchanged, including whitespace or ZIP contents. fetchResults() parses JSON into TaskExport[] and does not unpack ZIP archives. Raw downloads through SuparseClient are held in memory; Node.js background file downloads stream to disk. Background downloads are checked against the server-provided size and SHA-256 checksum before they are returned or saved. Node downloadResults serializes parsed JSON and overwrites existing files; downloadExportJob preserves raw bytes and requires overwrite: true to replace a file. The destination file appears only after writing succeeds, so a failed write does not leave a partially written result there.

A generated UUID is emitted before submission and retained across safe retries. After a lost submission response, retry only with the same key and identical IDs/options. Accepted job recovery never resubmits. Cleanup defers deletion when submission/job status is uncertain or may still run. A local verified artifact write failure alone does not mean backend work remains active.

Replay-safe upload confirmation and quick-create retries require both upload_batch_id and source_upload_id. Legacy ambiguous confirmation throws SuparseUploadConfirmationUnknownError: retain its uploadReferenceId instead of blindly uploading again. Approval defaults to true. SDK callers can set auto_approve: false for workflows that require human review.

Google Sheets exports use immediate responses. Background file exports support JSON, CSV, and XLSX. Parsed JSON returns TaskExport[]; use raw/job downloads for ZIP artifacts or other JSON shapes. For browser applications, download background artifacts through a Node.js server endpoint when the browser cannot read signed storage redirects.

Reference

Constructor Parameters

SuparseClient requires apiKey directly. Keep the key on your server or edge runtime and have browser applications call your authenticated proxy. SuparseNodeClient can read apiKey and baseUrl from environment variables.

ParameterTypeDefaultDescription
apiKeystringSUPARSE_API_KEY in SuparseNodeClient onlyYour API key
baseUrlstringSUPARSE_API_URL env var or https://api.suparse.com/api/v1API base URL
timeoutMsnumber60000API request/artifact transfer timeout in milliseconds
maxRetriesnumber3Max retry attempts for requests eligible under the retry policy below
pollIntervalnumber5Initial seconds between polling attempts
maxPollAttemptsnumber300Max 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.

Transient GET, DELETE, and presigned upload PUT failures can be retried up to maxRetries. POST retries depend on the endpoint and its replay safeguards:

  • File export submissions retain the same idempotency key and identical document IDs/options across safe retries.
  • Upload confirmation and quick-schema creation require both upload_batch_id and source_upload_id for replay-safe retries.
  • Upload URL creation and POST requests without the required replay safeguards are not automatically retried.

After a lost export submission response, retain the idempotency key and retry only the identical request. Once an export job ID is known, inspect or wait for that job instead of submitting another export. If upload confirmation is ambiguous, retain the upload reference for recovery instead of uploading again.

Result Objects

ObjectPropertiesDescription
TaskExporttask_id, original_file, total_documents_extracted, documentsSuccessfully extracted file
DocumentExportdocument_id, file_name, page_start, page_end, template_id, credits_used, extracted_dataExtracted document and parsed fields
ExtractionTemplateSummaryid, name, description, template_language, template_group_id, parent_template_id, version, team_id, is_active, is_system_template, created_atTemplate summary returned by listTemplates
FileExportformat, contentType, filename, isZip, dataIn-memory CSV/XLSX export bytes
GoogleSheetsExportmessage, spreadsheet_id, spreadsheet_url, folder_url, spreadsheetsGoogle Sheets export response
FailedResultfile, error, optional cancelled, task/upload/job IDs, idempotencyKey, exportRequest, operationMayBeRunningFailed input with recovery context
BatchResultsucceeded, failed, totalContainer for batch results
TaskResultDocumentid, file_name, extraction_data, page_start, page_end, page_count, template_idPartial task document
TaskResultPagedocuments, next_cursorOne page; null cursor ends traversal
ExportJobReadexport_job_id, status, requested/effective formats, counts, timestamps, artifact, errorExport job status and metadata
ExportJobArtifactfilename, content_type, size_bytes, checksum_sha256Artifact integrity metadata
RawFileExportdata, format, contentType, filename, isZip, optional job/key/artifact metadataExact in-memory response or artifact bytes

Partial Result and Export Job Methods

MethodOptionsReturns
getTaskResults(taskId, options)limit (1–100, default 100), cursor, signalTaskResultPage
iterTaskResults(taskId, options)pageSize (1–100, default 100), cursor, signalAsync iterator of TaskResultDocument
getExportJob(jobId, options)signalExportJobRead
waitForExportJob(jobId, options)waitTimeoutMs, signalCompleted ExportJobRead
downloadDocuments(documentIds, options)Export options below; export_type defaults to originalRawFileExport
fetchExportJobArtifact(jobId, options)signalRawFileExport
downloadExportJob(jobId, outputPath?, options)Node only: signal, overwrite (default false)Saved file path

Methods return promises except the async iterator. Job artifact downloads require a completed job; use waitForExportJob to wait first.

Export Options

OptionValuesDefaultDescription
formatjson, csv, xlsx, google_sheetsjsonExport format for fetchResults, downloadResults, and processDocument
export_typeoriginal, unifiedunifiedExport mode for CSV, XLSX, and Google Sheets exports
xlsxLayoutstandard, flatstandardXLSX worksheet layout; ignored for other export formats
signalAbortSignal—Cancel local requests and waiting
waitTimeoutMsPositive number900000Export-job wait deadline in milliseconds
idempotencyKeyUUID stringGenerated per submissionReplay an identical export request
onExportEvent(event: ExportEvent) => void—Receive submission and accepted events with key/job context

Exceptions

The SDK-specific exceptions below inherit from SuparseError.

ExceptionRaised When
SuparseErrorBase exception for all SDK errors
SuparseNetworkErrorNetwork connection fails or times out
SuparsePollingTimeoutErrorTask polling limit or export-job wait deadline is reached
SuparseProcessingErrorDocument fails to process on the server
SuparseAPIErrorBase for HTTP error responses; has statusCode and responseBody
SuparseAuthError401/403 authentication or authorization error
SuparseNotFoundError404 resource not found
SuparseRateLimitError429 too many requests
SuparseServerError5xx server error
SuparseSDKErrorSDK fails to parse or handle the expected API response
SuparseAbortErrorA local operation is cancelled; extraction errors retain partialResult
SuparseUploadConfirmationUnknownErrorUpload confirmation is ambiguous; retains uploadReferenceId for recovery
SuparseExportErrorExport job, protocol, storage, or integrity failure; exposes reason and recovery context

Errors can include task/upload/job IDs, idempotencyKey, exportRequest, lastStatus, and operationMayBeRunning for recovery.

extract() Parameters

ParameterTypeDefaultDescription
filesNode: string, Blob, File, URL, or array; browser/edge: Blob, File, URL, or arrayrequiredOne or more files to process
template_idstringundefinedTemplate ID (auto-detect if omitted)
splitbooleanfalseAuto-split multi-page documents
auto_approvebooleantrueAutomatically approve documents; set to false to require human review
pdf_passwordstring | nullundefinedPassword for encrypted PDFs; the same value is used for every input
folder_idstring | nullundefinedRemote folder ID for uploaded documents; the same value is used for every input
cleanupbooleanfalseDelete documents from server after extraction
onProgress(result) => voidundefinedCalled with each TaskExport or FailedResult as it completes
signalAbortSignalundefinedCancel the local extraction workflow
exportOptionsExtractExportOptionsundefinedPer-source waitTimeoutMs and onExportEvent; keys are generated per source

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

onProgress is a best-effort synchronous observer for extract() and extractFolder(). If the callback throws, extraction continues: other files are still processed, results are still returned, and the configured cleanup still runs. Callbacks are not awaited; handle asynchronous errors inside the callback.

extractFolder() Parameters

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

ParameterTypeDefaultDescription
folderstringrequiredDirectory to scan
template_idstringundefinedTemplate ID (auto-detect if omitted)
splitbooleanfalseAuto-split multi-page documents
auto_approvebooleantrueAutomatically approve documents; set to false to require human review
pdf_passwordstring | nullundefinedPassword for encrypted PDFs; the same value is used for every input
folder_idstring | nullundefinedRemote folder ID for uploaded documents; the same value is used for every input
cleanupbooleanfalseDelete documents from server after extraction
onProgress(result) => voidundefinedCalled with each result as it completes
signalAbortSignalundefinedCancel the local folder workflow
exportOptionsExtractExportOptionsundefinedPer-source waitTimeoutMs and onExportEvent

Supported Files

ExtensionMIME Type
.pdfapplication/pdf
.jpg, .jpegimage/jpeg
.pngimage/png
.heicimage/heic
.heifimage/heif