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 runtimessuparse: 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/sdkInstall the CLI globally:
npm install -g @suparse/cliOr run the CLI without a global install:
npx @suparse/cli process invoice.pdf -o results.jsonAuthentication
You'll need an API key to use the SDK or CLI. To obtain one:
- Sign in at suparse.com
- Go to the API Keys tab
- Enter a key name and click Generate New Key
- 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-passwordExport 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 xlsxWhen -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 jsonQuick-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 status | Exit code |
|---|---|
completed | 0 |
completed_with_errors | 1 |
failed | 1 |
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> -yDeleting 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 jsonThe 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.jsonIf you consistently process one document type, look up the template ID and pass it directly:
-
Run
suparse templatesto see templates assigned to your account. -
Use the matching template ID:
suparse process invoice.pdf --template-id <id> -o results.json -
If no template matches, run
suparse templates --include-systemto browse all system templates. Assign one to your account via the Suparse UI. -
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:
| Format | Output behavior |
|---|---|
json | Default. Writes the task-oriented JSON export to {file_stem}_results.json or {folder_name}_results.json |
csv | Saves a CSV file or ZIP archive, using the API filename when -o is omitted |
xlsx | Saves an XLSX file or ZIP archive, using the API filename when -o is omitted |
google_sheets | Writes 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.
| Variable | Default | Description |
|---|---|---|
SUPARSE_API_URL | https://api.suparse.com/api/v1 | API base URL |
SUPARSE_API_KEY | - | Your API key (required) |
SUPARSE_CONFIG_PATH | ~/.config/suparse/config.json | Optional 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.
| Option | Description |
|---|---|
--api-url | API URL (default: from SUPARSE_API_URL env var) |
--api-key | API key (default: from env var or config file) |
-v, --verbose | Enable verbose output |
CLI Options
| Command | Option | Description |
|---|---|---|
process | --folder | Process all supported files in a folder |
process | -o, --output | Output file path, or directory for CSV/XLSX exports |
process | --format | Export format: json, csv, xlsx, or google_sheets (default: json) |
process | --export-type | Export mode: original or unified (default: unified) |
process | --xlsx-layout | XLSX layout: standard or flat (default: standard) |
process | --template-id | Template ID to use (default: auto-detect) |
process | --folder-id | Assign uploaded documents to a remote folder |
process | --prompt-pdf-password | Prompt securely for an encrypted-PDF password |
process | --with-split | Auto-split multi-page documents containing mixed document types |
process | --cleanup | Delete documents from server after download |
templates | --format | Output format: table or json (default: table) |
templates | --include-system | Include system templates |
templates | --view | Template response view: summary or full (default: summary) |
quick-create | --wait | Poll until quick schema creation reaches a terminal result |
quick-create | --format | Output format: human or json (default: human) |
quick-create | --folder-id | Assign the source document to a remote folder |
quick-create | --upload-batch-id | Use an existing upload batch ID (batch creation is outside this SDK) |
quick-create | --source-upload-id | Use an existing source upload ID for replay-aware creation |
quick-create | --prompt-pdf-password | Prompt securely for an encrypted-PDF password |
quick-create-status | --format | Output format: human or json (default: human) |
export | --format | Export format: json, csv, xlsx, or google_sheets (default: json) |
export | -o, --output | Output file path or directory |
export | --export-type | Export mode: original or unified (default: unified) |
export | --xlsx-layout | XLSX layout: standard or flat (default: standard) |
delete | -y, --yes | Skip confirmation prompt |
process, export, export-job-wait | --wait-timeout | Export-job wait deadline in seconds (default: 900); excludes upload/task processing |
process, export | --idempotency-key | Reuse a UUID for an identical export request; rejected for folder JSON processing |
task-results | --jsonl | Write one document per line instead of one JSON array |
task-results | --single-page | Retrieve one page instead of traversing all pages |
task-results | --page-size | Number of results requested per page |
task-results | --cursor | Resume a page; requires --single-page |
task-results, export-job-download | -o, --output | Output file path |
task-results, export-job-download | --overwrite | Replace an existing output file |
SDK Usage
The SDK exports two clients:
SuparseClientfrom@suparse/sdk: browser/edge-compatible client forBlob,File, andURLinputsSuparseNodeClientfrom@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:
| 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.
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 type | Behavior | Use it when |
|---|---|---|
original | Exports each document using the template version that processed it | You 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 schema | You 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.
| Layout | Data arrangement | Use it when |
|---|---|---|
standard (default) | Document summary fields and line items appear on separate worksheets | You want to review document summaries and item details separately |
flat | A Data worksheet puts summary fields beside each line item, repeating the summary for each item | You 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:
| Invoice | Supplier |
|---|---|
| INV-42 | Acme |
With standard and export_type: "original", the summary worksheet instead lists fields as key/value pairs:
| Field | Value |
|---|---|
| Invoice | INV-42 |
| Supplier | Acme |
In both export types, a separate items worksheet contains the line items:
| Item | Quantity |
|---|---|
| Paper | 2 |
| Pens | 5 |
With flat, the Data worksheet repeats the invoice fields on each item row:
| Invoice | Supplier | Item | Quantity |
|---|---|---|---|
| INV-42 | Acme | Paper | 2 |
| INV-42 | Acme | Pens | 5 |
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 flatAdvanced 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 UUIDtask-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.
| Parameter | Type | Default | Description |
|---|---|---|---|
apiKey | string | SUPARSE_API_KEY in SuparseNodeClient only | Your API key |
baseUrl | string | SUPARSE_API_URL env var or https://api.suparse.com/api/v1 | API base URL |
timeoutMs | number | 60000 | API request/artifact transfer timeout in milliseconds |
maxRetries | number | 3 | Max retry attempts for requests eligible under the retry policy below |
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.
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_idandsource_upload_idfor 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
| 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, optional cancelled, task/upload/job IDs, idempotencyKey, exportRequest, operationMayBeRunning | Failed input with recovery context |
BatchResult | succeeded, failed, total | Container for batch results |
TaskResultDocument | id, file_name, extraction_data, page_start, page_end, page_count, template_id | Partial task document |
TaskResultPage | documents, next_cursor | One page; null cursor ends traversal |
ExportJobRead | export_job_id, status, requested/effective formats, counts, timestamps, artifact, error | Export job status and metadata |
ExportJobArtifact | filename, content_type, size_bytes, checksum_sha256 | Artifact integrity metadata |
RawFileExport | data, format, contentType, filename, isZip, optional job/key/artifact metadata | Exact in-memory response or artifact bytes |
Partial Result and Export Job Methods
| Method | Options | Returns |
|---|---|---|
getTaskResults(taskId, options) | limit (1–100, default 100), cursor, signal | TaskResultPage |
iterTaskResults(taskId, options) | pageSize (1–100, default 100), cursor, signal | Async iterator of TaskResultDocument |
getExportJob(jobId, options) | signal | ExportJobRead |
waitForExportJob(jobId, options) | waitTimeoutMs, signal | Completed ExportJobRead |
downloadDocuments(documentIds, options) | Export options below; export_type defaults to original | RawFileExport |
fetchExportJobArtifact(jobId, options) | signal | RawFileExport |
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
| 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 |
xlsxLayout | standard, flat | standard | XLSX worksheet layout; ignored for other export formats |
signal | AbortSignal | — | Cancel local requests and waiting |
waitTimeoutMs | Positive number | 900000 | Export-job wait deadline in milliseconds |
idempotencyKey | UUID string | Generated per submission | Replay 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.
| Exception | Raised When |
|---|---|
SuparseError | Base exception for all SDK errors |
SuparseNetworkError | Network connection fails or times out |
SuparsePollingTimeoutError | Task polling limit or export-job wait deadline is reached |
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 |
SuparseAbortError | A local operation is cancelled; extraction errors retain partialResult |
SuparseUploadConfirmationUnknownError | Upload confirmation is ambiguous; retains uploadReferenceId for recovery |
SuparseExportError | Export 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
| 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 | Automatically approve documents; set to false to require human review |
pdf_password | string | null | undefined | Password for encrypted PDFs; the same value is used for every input |
folder_id | string | null | undefined | Remote folder ID for uploaded documents; the same value is used for every input |
cleanup | boolean | false | Delete documents from server after extraction |
onProgress | (result) => void | undefined | Called with each TaskExport or FailedResult as it completes |
signal | AbortSignal | undefined | Cancel the local extraction workflow |
exportOptions | ExtractExportOptions | undefined | Per-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.
| 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 | Automatically approve documents; set to false to require human review |
pdf_password | string | null | undefined | Password for encrypted PDFs; the same value is used for every input |
folder_id | string | null | undefined | Remote folder ID for uploaded documents; the same value is used for every input |
cleanup | boolean | false | Delete documents from server after extraction |
onProgress | (result) => void | undefined | Called with each result as it completes |
signal | AbortSignal | undefined | Cancel the local folder workflow |
exportOptions | ExtractExportOptions | undefined | Per-source waitTimeoutMs and onExportEvent |
Supported Files
| Extension | MIME Type |
|---|---|
.pdf | application/pdf |
.jpg, .jpeg | image/jpeg |
.png | image/png |
.heic | image/heic |
.heif | image/heif |