Skip to main content
The published client is ndi-sdk on npm. It covers the same /v1 surface as this site. The Python package is separate (pip install ndi-sdk). Requires Node 20+ (or any runtime with native fetch, FormData, and Blob: browsers, Deno, Bun, edge). Zero runtime dependencies. Dual ESM + CommonJS.
Mint a key on the API keys page in the NDI console, then:
new NdiClient() reads $NDI_API_KEY and $NDI_BASE_URL. You can also pass { api_key, base_url }. There is one async client — fetch is async-only. close() is a no-op for the default fetch. If you pass your own fetch, you own its lifetime.

What you can do

One-shot calls on client.documents do not write to a workspace. Uploads for those calls are single-use: the bytes are dropped when the job that reads them finishes.

Parse a local file

wait_seconds holds the HTTP response open when the work finishes quickly. For everything else, poll:

Extract structured JSON

Pass a JSON Schema. Extract from an upload, or from a prior parse with { type: "parse_result", job_id } so the parse is not paid for twice. not_found on a field is an answer about the document, not an error.

Split and classify

split cuts a scanned packet into logical documents. classify labels one document against classes you define. Classify reads the original file, so it rejects a parse-result source.

Ground quoted text

Ground pins a quote back to a location in the source.

Search a workspace

A workspace is a durable corpus: upload files, ingest them once, then search and ask questions repeatedly. Uploading does not make a file searchable — ingestion does.
For a single file, client.uploadAndIngest(...) collapses the upload and ingest calls. Across several spreadsheets, client.tools.queryTables(...) answers one question over the set.

Next steps