Skip to content

Ragextract for developers

Everything the application does, it does over this API: put documents into a workspace, ask a question per column, run it, and read back answers with the page each one was read from.

Two ways in

Both reach the same 53 endpoints. What differs is who writes the client.

What you can build

The API is the product without the grid on top. A client can ingest documents, define and run a table of questions over them, correct an answer, and read the citation behind every cell. That is enough to put extraction inside a pipeline that already exists — a deal tracker, an intake queue, a nightly job over a supplier folder — rather than asking anyone to open a second tool.

  • Ingest. Upload a document, or hand over a URL to fetch. PDF, Office formats and images; over 100 MB goes in parts.
  • Ask. A column is a prompt with one of eight output types, so what comes back is a date, a number, a category or a picture — not a paragraph you then have to parse.
  • Check. Every answer carries the file, the page, the quote and a box on that page, plus a confidence score. Corrections are kept beside the extraction rather than replacing it.
  • Retrieve. Semantic search across a workspace's pages, by text or by image.

What it is not: there is no endpoint for sharing a workspace, inviting someone, buying credits or changing a plan. Those are account acts and they stay in the app.

From nothing to a cited answer

The whole path, in one paste. Every call below has a page in the reference with its parameters and its failure modes.

Request
export KEY="psk_live_…"
export API="https://api.ragextract.com/v2"

# 0 — what does this key reach?
curl $API/verify -H "x-api-key: $KEY"

# 1 — a workspace to work in
curl -X POST $API/workspaces -H "x-api-key: $KEY" \
  -H "content-type: application/json" \
  -d '{"name": "Vendor contracts"}'
#  → data.id = wks_7Kq2mB4nR8vXpL3d

# 2 — put a document in it. This returns a JOB, not a finished file,
#     and it is what spends credits: one per page.
curl -X POST $API/workspaces/wks_7Kq…/files -H "x-api-key: $KEY" \
  -F "file=@acme-msa-2024.pdf"
#  → data.id = dsj_L8vB2mQ6xR3kW9pZ

# 3 — poll until status is SUCCESS
curl $API/workspaces/wks_7Kq…/jobs/dsj_L8v… -H "x-api-key: $KEY"

# 4 — a table is a question per column and a document per row.
#     All three of these are free; nothing is computed yet.
curl -X POST $API/workspaces/wks_7Kq…/tables -H "x-api-key: $KEY" \
  -H "content-type: application/json" \
  -d '{"name": "Vendor contracts"}'
#  → data.id = rev_Qm5xC9bV3nK7sAeR

curl -X POST $API/workspaces/wks_7Kq…/tables/rev_Qm5…/columns \
  -H "x-api-key: $KEY" -H "content-type: application/json" \
  -d '{"name": "Governing law",
       "prompt": "Which law governs this agreement?",
       "outputType": "text_quote"}'

curl -X POST $API/workspaces/wks_7Kq…/tables/rev_Qm5…/rows \
  -H "x-api-key: $KEY" -H "content-type: application/json" \
  -d '{"subjectType": "file", "subjectId": "ds_M3xJ8pQ1vK5nB7wT"}'

# 5 — what would running it cost? Free to ask.
curl "$API/workspaces/wks_7Kq…/tables/rev_Qm5…/runs/preview" \
  -H "x-api-key: $KEY"
#  → { "cost": 4, "cells": 1, "skippedRowIds": [] }

# 6 — run it. THIS is the charged call.
curl -X POST $API/workspaces/wks_7Kq…/tables/rev_Qm5…/runs \
  -H "x-api-key: $KEY" -H "content-type: application/json" -d '{}'

# 7 — read the answers, each with the page it came from
curl $API/workspaces/wks_7Kq…/tables/rev_Qm5…/cells -H "x-api-key: $KEY"
#  → value, citations[{ fileId, page, quote, box }], confidence

Three things spend credits

Everything else — listing, reading, creating a table, adding columns and rows, pricing a run — is free. Credits are prepaid and there is no subscription.

  • Ingest — 1 credit per page, once per document. Adding a column to a year-old table costs no more than adding it on day one, because the reading is already paid for.
  • Extraction — the column's own rate per cell, from 4 credits, plus a surcharge on bundled rows. Charged per cell as each one succeeds, so a failed cell is not billed.
  • Search — 40 credits per block of 100 searches. The one people do not expect, because a search feels like a read.

Run preview prices a run before you start it, using the same arithmetic the charge uses. Pricing has the rates in money.

Getting a key

Requests authenticate with a personal API key (psk_…) in the x-api-key header. Keys are created under Integrations → API keys in the Ragextract app’s settings, shown once, and stored hashed. A key never reaches more than the person who created it can, and scopes only ever narrow it further — Authentication has the model.

What is here

If you are writing JavaScript

There is an SDK, and for a JS or TypeScript caller it is the better door. @subworkflow/ragextract routes on your key’s prefix — a psk_ key reaches /v2 — so it is one import and a key:

Request
npm i @subworkflow/ragextract   # 0.2.0 or later

import { Ragextract } from '@subworkflow/ragextract';

const ragextract = new Ragextract({ apiKey: process.env.RAGEXTRACT_API_KEY });
const ws = ragextract.workspace('wks_7Kq2mB4nR8vXpL3d');

const file  = await ws.files.upload(new URL('https://example.com/acme-msa-2024.pdf'));
const table = await ws.tables.create({ name: 'Vendor contracts' });

await ws.tables.addColumn(table.id, {
  name: 'Governing law',
  prompt: 'Which law governs this agreement?',
  outputType: 'text_quote',
});
await ws.tables.addRow(table.id, { type: 'file', id: file.id });

const { cost } = await ws.tables.previewRun(table.id);   // free to ask
const cells = await ws.tables.runAndWait(table.id);      // this is the charged call

It wraps the two parts of this API that are genuinely awkward by hand: an upload switches to a multipart session above 100 MB without you choosing, and runAndWait() polls a run to completion, which every caller was otherwise writing for themselves. The workspace handle is there because every /v2 route nests under a workspace, and the alternative is a workspace id as the first argument of every call.

Pin ^0.2.0. 0.1.1 and earlier reach /v1 only — and could not be imported from Node at all, for want of a main field.

The reference below still describes the wire format rather than the SDK, deliberately: it is what a client in any language has to match, and it is where the parameters and failure modes live.

If you are using n8n

There is an official community node, n8n-nodes-ragextract, and from 0.2.0 it calls /v2 with the same personal key — tables, runs, bundles and search included. The n8n node covers installing it, the credential and what each operation does. 0.1.x reaches /v1 only, so an existing workflow needs the upgrade before anything on these pages works through it.

What is not here

  • There is no Python client. Every sample carries a language switcher, but curl is the only tab on an endpoint page today. Everything here is reachable over plain HTTP from any language, which is what the reference documents.
  • There are no webhooks. Ingest and extraction are asynchronous and you poll them — the job for a document, the run for a table. Both carry enough state for a progress bar.
  • Reading your data from an LLM client is a different door. If the goal is to let Claude or an agent read workspaces, tables and answers, that is the MCP server — read-only, connected by signing in rather than by a key you hold, and gated per organisation. It adds no capability this API does not have; it removes the need to write a client.

Where else to look

The product documentation explains what these nouns mean — what a bundle is for, what makes an answer stale, how a correction is audited — screen by screen. A client is easier to write once those are settled, and this reference does not repeat them.