Skip to main content

Install

npm install @okrapdf/sdk
import { createOkra, OkraClient } from '@okrapdf/sdk';
import { doc } from '@okrapdf/sdk/doc';
createOkra(...) returns an OkraClient. Use it when you want workflow defaults or middleware-style options. Use new OkraClient(...) when you want the direct class.

Upload and ask

import { createOkra } from '@okrapdf/sdk';

const okra = createOkra({ apiKey: process.env.OKRA_API_KEY });

const session = await okra.sessions.create('./report.pdf', {
  wait: true,
  model: 'anthropic/claude-haiku-4.5',
});

const { answer, sources } = await session.prompt('What is total revenue?');

console.log(answer);
console.log(sources);
sessions.create(...) accepts local file paths in Node, URLs, Blob, ArrayBuffer, or Uint8Array. Use sessions.from(documentId) to attach to an existing document.

Read pages and entities

const status = await session.status();
const pages = await session.pages({ range: '1-3' });
const tables = await session.entities({ type: 'table' });

console.log(status.phase, pages.length, tables.nodes.length);

Structured output

import { z } from 'zod';

const Invoice = z.object({
  vendor: z.string(),
  total: z.number(),
  currency: z.string().optional(),
});

const result = await session.prompt('Extract invoice fields', {
  schema: Invoice,
});

console.log(result.data);

Streaming

for await (const event of session.stream('Summarize in 3 bullets')) {
  if (event.type === 'text_delta') process.stdout.write(event.text);
  if (event.type === 'done') console.log('\nfinal:', event.answer);
}

Passive file assets

Use files.upload(...) when you want to store a PDF first and decide later whether to parse, host, or run a workflow.
const file = await okra.files.upload('./invoice.pdf');

console.log(file.id);
console.log(file.urls.bytes);

Host and URL building

The SDK exports a deterministic URL builder for document-derived assets:
const d = doc(session.id, { fileName: 'report.pdf' });

console.log(d.pg[1].png());
console.log(d.pg[1].md());
console.log(d.full.md());
For clean hosted PDF deployments, call the REST Host API or upload through files.upload(...) and publish with /v1/host.

Invoice extraction workflow

const file = await okra.files.upload('./invoice.pdf');

const run = await okra.runInvoiceExtraction({
  inputs: [file.id],
  quality: 'standard',
});

console.log(run.runId, run.exports.csvUrl, run.exports.jsonUrl);

Dynamic agent workflows

The stable SDK surface currently exposes built-in workflows such as invoice extraction. Custom JavaScript workflow authoring lives in the MCP and REST workflow surfaces:
  • Use Dynamic Agent Workflows for the agent() / parallel() / pipeline() scripting grammar.
  • Use MCP when an agent should draft, run, and inspect a workflow.
  • Use POST /v1/workflows and POST /v1/runs when your app wants to create and run a workflow directly.

Collections

const stream = okra.collections.query(
  'col-abc123',
  'Extract revenue, net income, and EPS.',
);

for await (const event of stream) {
  console.log(event);
}

API surface

createOkra({ apiKey, baseUrl?, sharedSecret?, fetch?, workflow? }) => OkraClient

okra.sessions.create(sourceOrDocId, { wait?, model?, upload?, waitOptions? }) => session
okra.sessions.from(documentId, { model? }) => session

okra.files.upload(input, options?)
okra.files.get(fileId)
okra.files.list(options?)
okra.files.delete(fileId)

session.status()
session.wait()
session.pages({ range? })
session.page(pageNumber)
session.entities({ type?, limit?, offset? })
session.prompt(query, { schema?, model? })
session.stream(query, options?)
session.publish()
session.shareLink({ role, expiresInMs, maxViews, label })