Install from npm. You need Node 22 or newer, npm, version 0.18.19 or newer of the SDK, and a Transform API key.Run this command from your project directory:
Set UNSTRUCTURED_API_KEY to your API key and save your input as document.pdf. Use Node 22 or newer.To try the example without your own file, download the ACME Corp Annual Report sample PDF and save it as document.pdf in your project directory.Save this example as parse.mjs. These examples use JavaScript syntax with the TypeScript SDK, so Node can run them directly.
import { readFile } from "node:fs/promises";import { TransformClient } from "unstructured-transform-client";const client = new TransformClient({ timeoutMs: 60_000 });const file = new File([await readFile("document.pdf")], "document.pdf");const outcome = await client.parse.run({ input: file, waitSeconds: 30 });console.log(outcome.body);
Run node parse.mjs from the project directory in the shell where you exported your key.The call waits up to 30 seconds and prints the completed result or pending job handle. Follow request progress for a pending job. A completed Parse contains Markdown by default; no output options are required.If you omit apiKey, the TypeScript SDK reads UNSTRUCTURED_API_KEY from the environment.The client defaults to https://transform.unstructured.io. Pass serverUrl only when you target a different deployment.
If you omit waitSeconds, the server waits up to 15 minutes by default, then returns a result or pending job handle. On Node, set waitSeconds as described below. Use zero to return a pending job immediately. See wait behavior and request progress.
With the default timeoutMs of 60,000, set waitSeconds to 30 or less. To wait longer, raise timeoutMs above the wait. On Node, keep waitSeconds at 240 or less because built-in fetch stops waiting for headers after 300 seconds.
Set waitSeconds: 0 on client.parse.run to receive a pending job handle. Server-side asynchronous processing is separate from JavaScript promises: await waits for that response, not for the document to finish processing.Save this complete example as parse-async.mjs and run node parse-async.mjs with your API key set and document.pdf in the project directory:
import { readFile } from "node:fs/promises";import { TransformClient, isAccepted } from "unstructured-transform-client";const client = new TransformClient();const file = new File([await readFile("document.pdf")], "document.pdf");// Submit once and retain the job ID for retrieval.const submitted = await client.parse.run({ input: file, waitSeconds: 0 });if (isAccepted(submitted)) { console.log("Parse job ID:", submitted.body.id); let job = await client.jobs.get(submitted.body.id); // Poll the same job until processing reaches a final status. while (job.status === "queued" || job.status === "processing") { await new Promise((resolve) => setTimeout(resolve, 2000)); job = await client.jobs.get(submitted.body.id); } // Retrieval wraps the parsed document under result. if (job.status === "completed" || job.status === "completed_with_warnings") { console.log(job.result); } else if (job.status === "failed") { throw new Error(JSON.stringify(job.error)); } else { console.log("Parse stopped:", job.status); }} else { console.log(submitted.body);}
The two-second delay is an example polling interval, not a server requirement. Stop the script to stop polling; this does not cancel the server job. Keep the job ID to resume retrieval. If you request output: "elements", pass it to jobs.get too and read job.result.elements after success.
Use the current Transform SDK release. Replace your-completed-parse-id with a completed Parse ID. The example schema requests an invoice number; adapt it using the schema guide.
import { TransformClient, isAccepted } from "unstructured-transform-client";const client = new TransformClient();const parseId = "your-completed-parse-id";const schema = {"type": "object", "properties": {"invoice_number": {"type": "string"}}};const extraction = await client.extract.run({ parseId, schema, waitSeconds: 0,});if (isAccepted(extraction)) { const deadline = Date.now() + 300_000; let job = await client.jobs.get(extraction.body.id); while (job.status === "queued" || job.status === "processing") { if (Date.now() >= deadline) { throw new Error(`extraction ${extraction.body.id} is still ${job.status}`); } await new Promise((resolve) => setTimeout(resolve, 2000)); job = await client.jobs.get(extraction.body.id); } console.log(job.status, job.result?.extractedData);} else if (extraction.body.status === "completed" || extraction.body.status === "completed_with_warnings") { console.log(extraction.body.extractedData);} else { console.log(`Extraction stopped: ${extraction.body.status}`);}
The two-second delay is an example polling interval, not a server requirement. Keep the job ID to resume retrieval. Check the final status before using job.result.extractedData.
import { TransformClient } from "unstructured-transform-client";const client = new TransformClient();for await (const job of client.jobs.iterate({ status: "completed" })) { console.log(job.id, job.status);}
iterate follows cursors and yields individual jobs. Use jobs.list() when you need one page at a time.Filter by operation, read the count across all matching pages, and iterate over every matching job:
import { TransformClient } from "unstructured-transform-client";const client = new TransformClient({ retries: { maxAttempts: 5, maxElapsedMs: 20_000 },});
Pass retries: false to disable retries. The client uses backoff for eligible transient failures. A submission that might already have created a job is not retried after a read timeout or server response, to avoid duplicate jobs.See Chain Parse and Extract for a complete sequence that passes the Parse ID into Extract.