# PdfParse > PdfParse turns PDFs and scanned documents into structured data using OCR and AI. Define extraction fields, review results, and export JSON, CSV, or SQLite. Use PdfParse for invoices, receipts, bank statements, purchase orders, and custom document extraction. Document workflows include email ingestion, routing rules, splitting, human review, and querying saved rows. The REST API is https://api.pdfparse.net/v1 and uses project-scoped API keys. The remote MCP server is https://mcp.pdfparse.net/mcp and uses OAuth. Browser WebMCP tools are a separate integration: they provide public documentation, sample-data queries, and workflow navigation within the current page. Processing your own documents requires the normal account, permissions, and any applicable usage allowance. Public SQL demo results are sample data. Use the pricing page for current plans and limits. Use the endpoint reference and OpenAPI contract for request and response details. Product documentation and policies take precedence over examples. --- ## Product and use cases - [Product](https://pdfparse.net/): Overview of document extraction and workflows. - [Pricing](https://pdfparse.net/pricing): Current plans, allowances, and billing information. - [PDF to JSON](https://pdfparse.net/pdf-to-json): Extract fields and nested records as JSON. - [PDF to CSV](https://pdfparse.net/pdf-to-csv): Extract PDF tables for spreadsheets. - [PDF to SQLite](https://pdfparse.net/pdf-to-sqlite): Extract relational data and try the public SQL demo. - [Invoice parser](https://pdfparse.net/invoice-parser): Extract invoice fields and line items. - [Bank statement parser](https://pdfparse.net/bank-statement-parser): Extract transactions from statements. - [Receipt parser](https://pdfparse.net/receipt-parser): Extract receipt data. - [Purchase order parser](https://pdfparse.net/purchase-order-parser): Extract purchase order fields. - [Email PDF parser](https://pdfparse.net/email-pdf-parser): Ingest PDF attachments through email workflows. - [Document routing](https://pdfparse.net/document-routing): Route documents to extraction tables. --- ## Reference and policies - [OpenAPI contract](https://pdfparse.net/openapi.json): Machine-readable REST API schema. - [Remote MCP tool catalog](https://pdfparse.net/mcp/tools.json): OAuth MCP server actions; distinct from browser WebMCP tools. - [Complete documentation as Markdown](https://pdfparse.net/llms-full.txt): All documentation guides in one text response. - [Blog](https://pdfparse.net/blog): Product updates, tutorials, and engineering articles; canonical articles use /blog/. - [Privacy](https://pdfparse.net/privacy): Data handling and privacy policy. - [Terms](https://pdfparse.net/terms-and-conditions): Terms of service. - [Contact](https://pdfparse.net/contact): Contact the PdfParse team. --- # API Reference Source: https://pdfparse.net/docs/api-reference Browse every supported PdfParse REST API operation by resource and HTTP method. Use this directory to find the canonical reference page for every supported API request. Each endpoint page includes its parameters, authentication requirements, request format, and response contract. [Browse the REST API reference](https://pdfparse.net/docs/api-reference) or read the [OpenAPI contract](https://pdfparse.net/openapi.json). --- # Authentication Source: https://pdfparse.net/docs/authentication Authenticate all protected REST API requests with a bearer API key. ## Header Send your API key using the `Authorization` header: ```http Authorization: Bearer ``` ## Request Example ```bash curl -X GET "https://api.pdfparse.net/v1/tables" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" \ -H "Content-Type: application/json" ``` ## Principal Types * Project-scoped user keys can access the active project's tables, rows, documents, and jobs. * Agent keys are scope-checked and may be route-restricted. ## Error Signals * `401` for missing/invalid keys. * `403` for insufficient scope/permission. --- # Get Started Source: https://pdfparse.net/docs/getting-started Create a project key, check authentication, and create your first extraction table. Use this guide to make your first PdfParse API request. ## Before you start You need: * a PdfParse account * a project * a project API key * `curl` Create the API key from **Project → API Keys**. Copy it when the application shows it. Store the key in an environment variable: ```bash export PDFPARSE_API_KEY="replace_with_your_project_key" ``` Do not put the key in browser code. Do not commit it to source control. ## 1. Check the key List the tables in the project: ```bash curl "https://api.pdfparse.net/v1/tables" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" ``` A new project can return an empty array. This result confirms that the key works. * A `401` response means that the key is missing or invalid. * A `403` response means that the key does not have permission for the operation. ## 2. Create a table Create an invoice table with four fields: ```bash curl -X POST "https://api.pdfparse.net/v1/tables" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: getting-started-invoices-v1" \ -d '{ "name": "invoices", "columns": [ { "name": "invoice_number", "prompt": "Invoice number as printed", "type": "text" }, { "name": "invoice_date", "prompt": "Invoice date", "type": "date" }, { "name": "vendor", "prompt": "Vendor name", "type": "text" }, { "name": "total", "prompt": "Final invoice total without a currency symbol", "type": "number" } ] }' ``` Store the returned `id` and `slug`. You need them for row queries and extraction jobs. Use `text` for identifiers that can contain letters or leading zeros. Use `number` for values that you must calculate. ## 3. Confirm the table List the tables again: ```bash curl "https://api.pdfparse.net/v1/tables" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" ``` Confirm that the response contains the `invoices` table. ## Next step Follow [How to Extract Data From a PDF](https://pdfparse.net/docs/how-to-extract-pdf-data) to upload a document, create a job, and query the extracted rows. Use the endpoint reference in the left sidebar when you need request and response details. --- # How to Extract Data From a PDF Source: https://pdfparse.net/docs/how-to-extract-pdf-data Upload a PDF, create an extraction job, wait for completion, and query the structured rows. Use this procedure after you create a table. You need: * a project API key in `PDFPARSE_API_KEY` * the table slug from the create-table response * a synthetic or redacted PDF * Node.js 20 or later ## 1. Install the upload client PdfParse uses the TUS resumable upload protocol. ```bash npm install tus-js-client ``` ## 2. Upload the PDF Save this file as `extract-pdf.mjs`: ```js import fs from "node:fs"; import path from "node:path"; import { Upload } from "tus-js-client"; const apiKey = process.env.PDFPARSE_API_KEY; const tableSlug = process.env.PDFPARSE_TABLE_SLUG; const filePath = process.argv[2]; if (!apiKey || !tableSlug || !filePath) { throw new Error( "Set PDFPARSE_API_KEY and PDFPARSE_TABLE_SLUG, then provide a PDF path.", ); } const file = fs.createReadStream(filePath); const size = fs.statSync(filePath).size; const filename = path.basename(filePath); const uploadResult = await new Promise((resolve, reject) => { const upload = new Upload(file, { endpoint: "https://api.pdfparse.net/v1/uploads", uploadSize: size, headers: { Authorization: `Bearer ${apiKey}`, }, metadata: { filename, name: filename, type: "application/pdf", file_size: String(size), tableSlug, }, retryDelays: [0, 1000, 3000, 5000], removeFingerprintOnSuccess: true, onError: reject, onSuccess() { const encodedUploadId = upload.url?.split("?")[0]?.split("/").filter(Boolean).at(-1); if (!encodedUploadId) { reject(new Error("The upload did not return an upload ID.")); return; } const uploadId = decodeURIComponent(encodedUploadId); resolve({ uploadId, documentKey: uploadId, }); }, }); upload.start(); }); ``` ## 3. Create the extraction job Add this code after the upload code: ```js const baseUrl = "https://api.pdfparse.net/v1"; const headers = { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }; const jobResponse = await fetch(`${baseUrl}/jobs`, { method: "POST", headers: { ...headers, "Idempotency-Key": crypto.randomUUID(), }, body: JSON.stringify({ tableSlug, documentKeys: [uploadResult.documentKey], }), }); if (!jobResponse.ok) { throw new Error(await jobResponse.text()); } const job = await jobResponse.json(); console.log(`Created job ${job.id}`); ``` The job runs asynchronously. ## 4. Wait for completion Add a bounded polling loop for a basic integration: ```js const wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)); let completedJob; for (let attempt = 0; attempt < 60; attempt += 1) { const response = await fetch(`${baseUrl}/jobs/${job.id}`, { headers }); if (!response.ok) { throw new Error(await response.text()); } const currentJob = await response.json(); if (currentJob.status === "completed") { completedJob = currentJob; break; } if (currentJob.status === "failed") { throw new Error(`Job ${job.id} failed.`); } await wait(2000); } if (!completedJob) { throw new Error(`Job ${job.id} did not finish in time.`); } ``` Use a webhook instead of polling for a production integration. ## 5. Query the extracted rows The completed job response contains `table_id`. ```js const rowsResponse = await fetch(`${baseUrl}/rows/search`, { method: "POST", headers, body: JSON.stringify({ table_id: completedJob.table_id, filters: [], page: 1, pageSize: 50, }), }); if (!rowsResponse.ok) { throw new Error(await rowsResponse.text()); } const rows = await rowsResponse.json(); console.log(JSON.stringify(rows, null, 2)); ``` Run the complete script: ```bash export PDFPARSE_TABLE_SLUG="invoices-replace_with_your_slug" node extract-pdf.mjs ./sample-invoice.pdf ``` ## 6. Validate the result Check the extracted values against the source PDF. Confirm that: * required fields are present * codes keep leading zeros * dates use the expected format * amounts use the expected decimal value * repeating rows have the expected count Do not send unvalidated OCR data directly to a financial or operational system. For production event delivery, use the webhook endpoints in the API reference. For authentication errors, read [Authentication](https://pdfparse.net/docs/authentication). --- # How-To: Run an Extraction Job Source: https://pdfparse.net/docs/how-to-run-extraction-job Queue extraction for uploaded documents and poll for status. ## 1. Queue extraction ```bash curl -X POST "https://api.pdfparse.net/v1/jobs" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "tableSlug": "invoice_rows-def67890", "documentKeys": ["file_a", "file_b"] }' ``` Store the returned `id` as `job_id`. ## 2. Poll job status ```bash curl -X GET "https://api.pdfparse.net/v1/jobs/" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" ``` ## 3. Query table rows ```bash curl -X POST "https://api.pdfparse.net/v1/rows/search" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "table_id": "", "filters": [], "page": 1, "pageSize": 50 }' ``` --- # Overview Source: https://pdfparse.net/docs Connect through MCP or use the REST API to upload documents, configure extraction, and query saved data. ## MCP server Connect your AI assistant using OAuth to create tables, upload PDFs, query extracted rows, and set up routing and email workflows. * [Connect to MCP](https://pdfparse.net/docs/mcp) * [Usage examples](https://pdfparse.net/docs/mcp/examples) * [Every MCP action](https://pdfparse.net/docs/mcp/actions) ## Zapier integration Use the native integration in testing to send PDFs into a project and map saved extraction fields into downstream apps. The [Zapier tutorial](https://pdfparse.net/docs/zapier) walks through an invoice-to-Google-Sheets workflow, verification, and current limits. See [availability](https://pdfparse.net/zapier) before setting up native steps. ## Browser agents Use [WebMCP browser tools](https://pdfparse.net/docs/webmcp) to search documentation, query the public sample database, and open a document workflow. Agents can start with [llms.txt](https://pdfparse.net/llms.txt) for a concise index or [llms-full.txt](https://pdfparse.net/llms-full.txt) for the complete guides. ## REST API base URL Use the versioned API base URL: ```txt https://api.pdfparse.net/v1 ``` ## Reference Coverage The OpenAPI reference includes all currently mounted REST handlers under `/v1`, including: * Projects * Tables * Rows * Documents * Jobs * Extraction Attempts * Webhooks * Uploads ## Next Steps * Follow [Get Started](https://pdfparse.net/docs/getting-started) * Follow [How to Extract Data From a PDF](https://pdfparse.net/docs/how-to-extract-pdf-data) * Read [Authentication](https://pdfparse.net/docs/authentication) * Follow [Tutorial: Create a Project and Table](https://pdfparse.net/docs/tutorial-first-project) * Follow [How-To: Run an Extraction Job](https://pdfparse.net/docs/how-to-run-extraction-job) * Browse every supported operation in the [API Reference](https://pdfparse.net/docs/api-reference) --- # Tutorial: Create a Table and Query Rows Source: https://pdfparse.net/docs/tutorial-first-project End-to-end flow to define a table schema and query rows through the flat `/v1` API. ## 1. Create a table ```bash curl -X POST "https://api.pdfparse.net/v1/tables" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "name": "invoice_rows", "columns": [ {"name": "invoice_number", "prompt": "Invoice number", "type": "text"}, {"name": "invoice_date", "prompt": "Invoice date", "type": "date"}, {"name": "total", "prompt": "Invoice total", "type": "number"} ] }' ``` Capture the returned `id` or `slug`. ## 2. Verify table list ```bash curl -X GET "https://api.pdfparse.net/v1/tables" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" ``` ## 3. Query rows for the table ```bash curl -X POST "https://api.pdfparse.net/v1/rows/search" \ -H "Authorization: Bearer ${PDFPARSE_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "table_id": "", "filters": [], "page": 1, "pageSize": 50 }' ``` --- # Browser agents and WebMCP Source: https://pdfparse.net/docs/webmcp Use PdfParse's public documentation and SQL demo from a browser agent, and open a document workflow in the current tab. PdfParse exposes five browser tools through WebMCP on its website. A compatible browser agent can discover them while you visit PdfParse. Browsers without WebMCP continue to use the normal interface. ## Available tools | Tool | What it does | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | `search_pdfparse_docs` | Search the documentation and API reference. Accepts `query` and returns up to eight matching entries. | | `read_pdfparse_guide` | Read a guide as Markdown. Accepts `slug`, such as `getting-started`, `mcp/examples`, or an empty string for the overview. | | `inspect_pdfparse_sqlite_demo` | Read the public sample database schema and supported query IDs. Accepts an empty object. | | `query_pdfparse_sqlite_demo` | Run a curated read-only query against public sample data. Accepts `queryId`. | | `open_pdfparse_workflow` | Open a converter, document demo, or setup guide in the current tab. Accepts `workflow`. | Try asking your browser assistant: > Find PdfParse's instructions for uploading a PDF and starting an extraction job. > Inspect the public SQLite demo, then show totals by carrier. > Open the invoice demo so I can try it. The sample query IDs are `recent-invoices`, `shipments-needing-attention`, `carrier-totals`, `shipment-journey`, and `recent-tracking-events`. These tools query sample shipping invoices and tracking events. They do not read your private project data or run arbitrary SQL. Workflow choices are `pdf-to-csv`, `pdf-to-json`, `pdf-to-sqlite`, `invoice-demo`, `bank-statement-demo`, `receipt-demo`, `purchase-order-demo`, `mcp-setup`, and `api-setup`. Opening a workflow takes you to its entry page. Continue through its normal controls to sign in, complete verification, upload documents, or start processing. ## Connect an assistant to your own documents For authenticated project actions, use the separate [remote MCP server](https://pdfparse.net/docs/mcp). It supports OAuth authorization and account permissions. Browser WebMCP tools do not replace that connection or grant access to private documents. ## Readable content for agents The [llms.txt index](https://pdfparse.net/llms.txt) links to product pages, documentation, the OpenAPI contract, and policies. [llms-full.txt](https://pdfparse.net/llms-full.txt) includes all documentation guides in one response. Each guide also advertises a Markdown version through its page metadata. WebMCP support depends on the browser and agent, and the API remains experimental. Neither WebMCP nor llms.txt guarantees search ranking or inclusion in an AI answer. --- # Zapier: send PDFs in and extracted rows out Source: https://pdfparse.net/docs/zapier Build a two-Zap invoice workflow: upload PDFs to PdfParse, then send saved invoice fields to Google Sheets without writing code. Connect a PdfParse project to Zapier to move documents into an extraction table and use its saved rows in another app. This guide builds one concrete workflow: invoices arriving in a Google Drive folder become rows in a Google Sheet. **Availability:** the native PdfParse app is being prepared for release. These instructions describe the integration in testing; they become usable in the Zap editor once you have access to its private invite or public listing. If PdfParse is absent from the app picker, do not choose another app with a similar name. Check the [integration page](https://pdfparse.net/zapier) for availability. ## What you will build Use two Zaps because document extraction runs in the background: 1. **Document intake:** Google Drive → PdfParse **Upload PDF and Start Extraction**. 2. **Saved data:** PdfParse **New Extracted Row** → Google Sheets **Create Spreadsheet Row**. The first Zap returns a document ID and job ID as soon as extraction is queued. The second reads rows after they have been saved. You do not need to guess how long OCR takes or add a fixed delay. For the example, use the synthetic [invoice PDF](https://pdfparse.net/blog/api-examples/invoice.pdf), which contains invoice `HOS-2026-1042` from Harbor Office Supply, with currency `USD` and total `70.20`. The amount is an example, not an extraction accuracy guarantee. ## Prepare the project, table, and spreadsheet You need a PdfParse account with an active subscription and enough extraction allowance, a Google Drive folder, a Google Sheet, and a Zapier account that supports the triggers and actions you select. Plan requirements and polling schedules depend on Zapier; check them before turning on your Zaps. 1. Open your PdfParse project, or follow [Getting started](https://pdfparse.net/docs/getting-started) to create one. Use a clear project name such as **Accounts Payable**. 2. Create an **Invoices** table with the fields below. If you already use an invoice table, reuse it and adapt the mapping to its field names. 3. Extract the sample invoice in PdfParse first. Inspect the saved record alongside the source PDF before automating downstream work. 4. Create a Google Sheet with these headers in the first row: **Invoice number**, **Supplier**, **Currency**, **Total**, and **Source document ID**. | PdfParse field | Type | Extraction instruction | | ---------------- | ------ | ------------------------------------------------------- | | `invoice_number` | Text | Extract the invoice identifier printed on the document. | | `supplier` | Text | Extract the supplier's business name. | | `currency` | Text | Extract the three-letter currency code. | | `total` | Number | Extract the final invoice total including tax. | Keep the table's automatic integer `id` column. **New Extracted Row** uses it to identify and order records. Do not replace it with an invoice number or an extracted business identifier. **Check the result:** the sample record should contain `HOS-2026-1042`, `Harbor Office Supply`, `USD`, and numeric `70.2`. A spreadsheet can display the amount as `70.20`. If a field is missing or incorrect, adjust the extraction instructions and review the PDF before proceeding. ## Connect the right PdfParse project Each Zapier connection uses a project API key. A connection can access the project that owns the key; typing a different connection name does not change its access. 1. In the project's navigation, open **API Keys** and select **Create API Key**. 2. Label the key **Zapier — Accounts Payable**. Choose an expiration appropriate for the workflow and save the key securely when it is shown. 3. In the Zap editor, select **PdfParse** for the relevant step, then connect an account. 4. Enter the key in **Project API Key** and enter **Accounts Payable** in **Connection Name**. 5. Test the connection. It checks that the key can list the project's tables. The test can succeed when the project has no tables. If **Invoices** does not appear in a step's **Table** list, create it in that project and refresh the fields. To connect another project, create a separate connection with that project's key. Never place the key in a spreadsheet, file URL, or ordinary text field in the Zap. Reconnect when the key expires, is revoked, or is replaced. See [Authentication](https://pdfparse.net/docs/authentication) for the underlying access rules. ## Build the PDF intake Zap This Zap sends a downloadable PDF to the existing Invoices table. 1. Create a Zap with **Google Drive** as the trigger app. Choose the trigger for a new file in a folder and select your invoice intake folder. 2. Test the Drive trigger using the sample PDF. If the folder also receives non-PDF files, add a filter that allows only PDF filenames or PDF MIME types. 3. Add a **PdfParse** action and choose **Upload PDF and Start Extraction**. 4. Select the **Accounts Payable** connection and the **Invoices** table. 5. For **PDF File**, map the Drive trigger's downloadable file. Use the file output rather than a sharing link or browser preview URL. 6. For **PDF Filename**, map the source filename, including its `.pdf` extension. 7. Test the action once. **Expected result:** the action returns `job_id`, `document_id`, `status`, `table_id`, and `filename`. The initial status is normally `queued`. The action deliberately returns identifiers rather than waiting for the invoice fields. **Verify it:** find the uploaded PDF in the PdfParse project and inspect its processing state. If needed, use **Find Extraction Job** with the returned `job_id` to inspect the current job. Wait until a saved invoice record is visible before testing the next Zap. **Recover:** a PDF must be downloadable over HTTPS and at most **8 MiB** for this action. A sharing page, login page, image, or renamed non-PDF file is rejected. If the action fails after uploading, check whether the document or job already exists before replaying the entire action. A full replay can create another upload and another record; the job request is protected against duplicate requests for the same upload, but the whole Zap action is not guaranteed to run only once. ## Build the saved-row Zap This Zap reads the extracted fields and writes one spreadsheet row per saved record. 1. Create another Zap with **PdfParse** as the trigger app. 2. Choose **New Extracted Row**, the **Accounts Payable** connection, and the **Invoices** table. 3. Test the trigger. Select the invoice record you reviewed earlier. 4. Add **Google Sheets** and choose **Create Spreadsheet Row**. Connect your Google account and select the spreadsheet and worksheet prepared above. 5. Map the fields using this table. The invoice fields appear under **Extracted** in the PdfParse output. 6. Test the Sheets action and compare the new spreadsheet row with the source invoice. | Google Sheet header | PdfParse output | Expected sample value | | ------------------- | ---------------------------- | -------------------------- | | Invoice number | Extracted → `invoice_number` | `HOS-2026-1042` | | Supplier | Extracted → `supplier` | `Harbor Office Supply` | | Currency | Extracted → `currency` | `USD` | | Total | Extracted → `total` | `70.2` | | Source document ID | Source Document ID | The uploaded document's ID | **Verify it:** the spreadsheet row should agree with the reviewed PdfParse record. Preserve **Source Document ID** so you can trace a spreadsheet entry back to its input. **Zapier Row ID** identifies the table row and can be used in your own duplicate-prevention logic. If you add or rename extraction fields later, refresh the trigger's fields and review the spreadsheet mapping before restarting the workflow. For repeating invoice items, use the child table as a separate row trigger; its rows are separate records and may require a different worksheet. **Find Extracted Row** returns the first matching record, not every line item belonging to a document. ## Turn on the workflow and verify a fresh document 1. Turn on the saved-row Zap first, then the intake Zap. Testing a Zap can write real rows into the chosen worksheet, so identify and remove test entries as appropriate. 2. Add a new PDF with a different invoice number to the watched Drive folder. 3. Check the intake Zap's history for its job and document IDs. 4. Inspect the extracted record in PdfParse. After the next scheduled poll, confirm that the saved-row Zap creates the corresponding spreadsheet row. 5. Compare the invoice number, supplier, currency, total, and source ID across the document, PdfParse, and spreadsheet. The automation now has a verifiable path from PDF to saved record to spreadsheet. The saved-row trigger starts from new rows; it does not backfill the entire table or run again when you edit an existing record. ### Understand polling and request limits **New Extracted Row** reads the newest **200 rows** ordered by automatic integer `id` on each poll. If more than 200 rows arrive between polls, older unseen rows can fall outside that window. It is intended for moderate-volume tables, not a bulk synchronization pipeline. Polling frequency depends on your Zapier plan. PdfParse project API keys currently allow **1,000 requests per UTC day**, shared by all uses of that key. A five-minute polling schedule makes about 288 requests per day per enabled row Zap; setup, uploads, other Zaps, and lookups add requests. One-minute polling alone would exceed the daily allowance. Use a schedule and number of enabled Zaps that fit the allowance. Do not use multiple keys simply to bypass it. For high-volume or auditable bulk delivery, use the [REST API](https://pdfparse.net/docs/api-reference) with pagination and a durable consumer. Do not depend on this polling trigger for a guaranteed full history. ## Add completion or failure notifications The integration also has two **instant** job triggers: **Extraction Completed** and **Extraction Failed**. These use signed project webhooks and create or remove their subscriptions when the Zap is turned on or off. To monitor failures, create a Zap with **Extraction Failed**, connect the project, and send the resulting job ID and status to your chosen notification app. Test it using a genuine failed job in that project. If no failed jobs exist yet, the test list can be empty; the sample schema is not proof of a live failure. **Extraction Completed** reports that a job has finished. A multi-document job can complete with some documents unsuccessful. Neither job trigger provides invoice fields or approves the data for payment. Use **New Extracted Row** for saved-data delivery, and review documents and amounts before any financial action. ## Troubleshoot the first run | Symptom | What to check | | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | PdfParse is missing from the app picker | Access to the private integration invite or the public listing. The app must be registered and released before native steps are usable. | | Connection fails | The project key is valid, unexpired, unrevoked, and can read tables. | | Wrong tables appear | The connection uses a key from a different project. The connection name is only a label. | | File action rejects the input | Map the downloadable PDF, not the preview page; check the `.pdf` filename and 8 MiB limit. | | Upload succeeds but extraction fails | Check the active subscription, extraction allowance, table selection, and the document's processing details. | | No trigger test records | Save at least one record in the selected table, then retest. | | Some spreadsheet rows are absent | Check Zap history, polling schedule, the 200-row window, and the API key's daily request limit. | | Duplicate spreadsheet rows | Check test runs, manual replays, and repeat uploads. Add downstream lookup logic using the row ID where needed. | | Job trigger stops after reconnecting | Turn the Zap off and on again to refresh the subscription under the intended project connection. | For a programmatic workflow with explicit retries and pagination, follow [Run an extraction job](https://pdfparse.net/docs/how-to-run-extraction-job). For this workflow, the next step is to run one fresh invoice through both Zaps and verify the resulting spreadsheet row. --- # MCP action reference Source: https://pdfparse.net/docs/mcp/actions Every PdfParse MCP action, its OAuth scope, parameters, and input and output schemas. {/* Generated by pnpm --filter mcp run docs:export. Edit the server registrations, not this file. */} The server exposes **29 actions**. This reference is generated from its actual MCP tools/list response. See [Connect to MCP](https://pdfparse.net/docs/mcp) and [Usage examples](https://pdfparse.net/docs/mcp/examples). Download the [machine-readable catalog](https://pdfparse.net/mcp/tools.json). ## All actions | Action | OAuth scope | Behavior | | ------------------------------------------------------------- | ----------- | ------------------------------ | | [`connection.profile`](https://pdfparse.net/docs/mcp/actions#connection-profile) | `mcp:read` | Read | | [`connection.info`](https://pdfparse.net/docs/mcp/actions#connection-info) | `mcp:read` | Read | | [`projects.create`](https://pdfparse.net/docs/mcp/actions#projects-create) | `mcp:write` | Creates or runs | | [`inboxes.list`](https://pdfparse.net/docs/mcp/actions#inboxes-list) | `mcp:read` | Read | | [`workflow.setup`](https://pdfparse.net/docs/mcp/actions#workflow-setup) | `mcp:write` | Creates or runs | | [`tables.list`](https://pdfparse.net/docs/mcp/actions#tables-list) | `mcp:read` | Read | | [`tables.create`](https://pdfparse.net/docs/mcp/actions#tables-create) | `mcp:write` | Creates or runs | | [`routing_rules.list`](https://pdfparse.net/docs/mcp/actions#routing_rules-list) | `mcp:read` | Read | | [`routing_rules.create`](https://pdfparse.net/docs/mcp/actions#routing_rules-create) | `mcp:write` | Creates or runs | | [`routing_rules.update`](https://pdfparse.net/docs/mcp/actions#routing_rules-update) | `mcp:write` | Changes existing configuration | | [`routing_rules.delete`](https://pdfparse.net/docs/mcp/actions#routing_rules-delete) | `mcp:write` | Changes existing configuration | | [`splitters.list`](https://pdfparse.net/docs/mcp/actions#splitters-list) | `mcp:read` | Read | | [`splitters.get`](https://pdfparse.net/docs/mcp/actions#splitters-get) | `mcp:read` | Read | | [`splitters.create_logical`](https://pdfparse.net/docs/mcp/actions#splitters-create_logical) | `mcp:write` | Creates or runs | | [`splitters.update_logical`](https://pdfparse.net/docs/mcp/actions#splitters-update_logical) | `mcp:write` | Changes existing configuration | | [`splitters.create_page_range`](https://pdfparse.net/docs/mcp/actions#splitters-create_page_range) | `mcp:write` | Creates or runs | | [`splitters.update_page_range`](https://pdfparse.net/docs/mcp/actions#splitters-update_page_range) | `mcp:write` | Changes existing configuration | | [`splitters.test_page_range`](https://pdfparse.net/docs/mcp/actions#splitters-test_page_range) | `mcp:read` | Read | | [`splitters.publish`](https://pdfparse.net/docs/mcp/actions#splitters-publish) | `mcp:write` | Changes existing configuration | | [`splitters.run_page_range`](https://pdfparse.net/docs/mcp/actions#splitters-run_page_range) | `mcp:write` | Creates or runs | | [`splitters.archive`](https://pdfparse.net/docs/mcp/actions#splitters-archive) | `mcp:write` | Changes existing configuration | | [`rows.search`](https://pdfparse.net/docs/mcp/actions#rows-search) | `mcp:read` | Read | | [`jobs.create`](https://pdfparse.net/docs/mcp/actions#jobs-create) | `mcp:write` | Creates or runs | | [`jobs.get`](https://pdfparse.net/docs/mcp/actions#jobs-get) | `mcp:read` | Read | | [`documents.upload`](https://pdfparse.net/docs/mcp/actions#documents-upload) | `mcp:write` | Creates or runs | | [`documents.upload_file`](https://pdfparse.net/docs/mcp/actions#documents-upload_file) | `mcp:write` | Creates or runs | | [`documents.get`](https://pdfparse.net/docs/mcp/actions#documents-get) | `mcp:read` | Read | | [`analysis.crosscheck`](https://pdfparse.net/docs/mcp/actions#analysis-crosscheck) | `mcp:read` | Read | | [`analysis.credit_memo`](https://pdfparse.net/docs/mcp/actions#analysis-credit_memo) | `mcp:read` | Read | ## connection profile Action: `connection.profile` Identify the connected PdfParse account using its stable, opaque account ID. Use connection.info when you also need the available projects and their slugs. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | --------- | -------- | ---- | ----------- | | None | — | — | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": {}, "additionalProperties": false } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "id": { "type": "string", "minLength": 1 } }, "required": [ "id" ], "additionalProperties": {} } ``` ## connection info Action: `connection.info` Show the PdfParse account and available projects with their slugs for selecting project\_slug. Use connection.profile when only the stable account ID is needed. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | --------- | -------- | ---- | ----------- | | None | — | — | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": {} } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "user_id": { "type": "string" }, "projects": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "number" }, "name": { "type": "string" }, "slug": { "type": "string" } }, "required": [ "id", "name", "slug" ], "additionalProperties": {} } } }, "required": [ "user_id", "projects" ], "additionalProperties": {} } ``` ## projects create Action: `projects.create` Create an empty project in the connected PdfParse account. Returns its ID and slug for subsequent table and workflow setup. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | --------- | -------- | ------ | ----------- | | `name` | Yes | string | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "name": { "type": "string", "minLength": 2, "maxLength": 100 } }, "required": [ "name" ], "additionalProperties": false } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "project": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "slug": { "type": "string", "minLength": 1 } }, "required": [ "id", "slug" ], "additionalProperties": {} } }, "required": [ "project" ], "additionalProperties": {} } ``` ## inboxes list Action: `inboxes.list` List existing email inboxes in projects you own, including inbox IDs needed to bind a logical splitter. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 } } } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "inboxes": {} }, "required": [ "inboxes" ], "additionalProperties": {} } ``` ## workflow setup Action: `workflow.setup` Set up a coordinated workflow with one new table and routing rule, plus an optional new inbox and published logical splitter, in an existing owned project. Use tables.create, routing\_rules.create, routing\_rules.update, and the splitters tools for individual configuration changes or to reuse existing resources. Create a project separately with projects.create if needed. Preview with dry\_run: true to check ownership, table-name collisions, and splitter conflicts; blocked previews return blockers. Applying requires mcp:write and creates resources; repeating the same intent resumes saved progress. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | ------------------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `dry_run` | No | boolean | Set true to validate ownership and configuration conflicts and preview steps without creating resources. False (the default) applies the intent. Both modes require mcp:write. | | `goal` | Yes | string | Short statement of the requested workflow (10–2000 characters after trimming). The structured fields specify the configuration; the goal alone is not enough. | | `project` | Yes | object | Existing owned project in which to provision this workflow. | | `table` | Yes | object | One new extraction table and its columns. An integer id primary key is added automatically. To reuse an existing table, use the granular routing and splitter tools instead. | | `routing_rule` | Yes | object | New classification rule targeting the table created by this intent; tableId is assigned automatically. | | `inbox` | No | object | Optional new email inbox. classify uses project routing rules; direct routes to the table created by this intent. Omit to leave existing inboxes unchanged. | | `logical_splitter` | No | object | Optional logical splitter to create and publish for the new inbox, or for project uploads when inbox is omitted. Uses project routing rules to choose destinations. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "dry_run": { "default": false, "description": "Set true to validate ownership and configuration conflicts and preview steps without creating resources. False (the default) applies the intent. Both modes require mcp:write.", "type": "boolean" }, "goal": { "type": "string", "minLength": 10, "maxLength": 2000, "description": "Short statement of the requested workflow (10–2000 characters after trimming). The structured fields specify the configuration; the goal alone is not enough." }, "project": { "type": "object", "properties": { "existing_slug": { "type": "string", "minLength": 1, "description": "Owned project slug from connection.info or projects.create. Setup never creates a project." } }, "required": [ "existing_slug" ], "additionalProperties": false, "description": "Existing owned project in which to provision this workflow." }, "table": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "columns": { "minItems": 1, "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "prompt": { "type": "string" }, "primaryKey": { "type": "boolean" }, "unique": { "type": "boolean" }, "autoIncrement": { "type": "boolean" }, "nullable": { "type": "boolean" }, "reanalyzeExisting": { "type": "boolean" }, "type": { "type": "string", "enum": [ "text", "number", "date", "boolean", "foreign_key" ] }, "referencedTable": { "type": "string" }, "referencedColumn": { "type": "string" }, "parentTable": { "type": "string" } }, "required": [ "name", "prompt" ] } } }, "required": [ "name", "columns" ], "description": "One new extraction table and its columns. An integer id primary key is added automatically. To reuse an existing table, use the granular routing and splitter tools instead." }, "routing_rule": { "type": "object", "properties": { "name": { "type": "string", "minLength": 2, "maxLength": 100 }, "prompt": { "type": "string", "minLength": 10 }, "confidenceThreshold": { "type": "integer", "minimum": 60, "maximum": 100 }, "enabled": { "type": "boolean" } }, "required": [ "name", "prompt" ], "description": "New classification rule targeting the table created by this intent; tableId is assigned automatically." }, "inbox": { "description": "Optional new email inbox. classify uses project routing rules; direct routes to the table created by this intent. Omit to leave existing inboxes unchanged.", "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 80 }, "routing": { "default": "classify", "type": "string", "enum": [ "classify", "direct" ] }, "sender_allowlist": { "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "address", "domain" ] }, "value": { "type": "string", "minLength": 1 } }, "required": [ "type", "value" ] } } }, "required": [ "name" ] }, "logical_splitter": { "description": "Optional logical splitter to create and publish for the new inbox, or for project uploads when inbox is omitted. Uses project routing rules to choose destinations.", "type": "object", "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "instructions": { "type": "string", "minLength": 10, "maxLength": 4000 }, "section_types": { "maxItems": 50, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{1,63}$" }, "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "description": { "type": "string", "maxLength": 500 } }, "required": [ "key", "name" ] } }, "review_uncertain_boundaries": { "default": true, "type": "boolean" }, "review_uncertain_destinations": { "default": true, "type": "boolean" } }, "required": [ "name", "instructions", "section_types" ] } }, "required": [ "goal", "project", "table", "routing_rule" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "status": { "type": "string", "description": "One of: preview, blocked, active, in_progress, partial" }, "goal": { "type": "string" }, "setup_id": { "type": "string" }, "blockers": { "type": "array", "items": { "type": "string" } } }, "required": [ "status", "goal" ], "additionalProperties": {} } ``` ## tables list Action: `tables.list` List tables in a project you own, including their extraction columns. Supply project\_slug if your account has multiple projects. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 } } } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "tables": {} }, "required": [ "tables" ], "additionalProperties": {} } ``` ## tables create Action: `tables.create` Create a table with extraction columns in a project you own. An integer primary key named id is added automatically and generated by the database during extraction; do not include it in extraction columns. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `name` | Yes | string | — | | `columns` | Yes | array | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "columns": { "minItems": 1, "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "prompt": { "type": "string" }, "primaryKey": { "type": "boolean" }, "unique": { "type": "boolean" }, "autoIncrement": { "type": "boolean" }, "nullable": { "type": "boolean" }, "reanalyzeExisting": { "type": "boolean" }, "type": { "type": "string", "enum": [ "text", "number", "date", "boolean", "foreign_key" ] }, "referencedTable": { "type": "string" }, "referencedColumn": { "type": "string" }, "parentTable": { "type": "string" } }, "required": [ "name", "prompt" ] } } }, "required": [ "name", "columns" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "table": {} }, "required": [ "table" ], "additionalProperties": {} } ``` ## routing\_rules list Action: `routing_rules.list` List document classification rules and their destination tables in a project. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 } } } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "routing_rules": {} }, "required": [ "routing_rules" ], "additionalProperties": {} } ``` ## routing\_rules create Action: `routing_rules.create` Create a rule that recognizes a document type and routes it to an extraction table. The table must belong to this project. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | --------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `name` | Yes | string | — | | `prompt` | Yes | string | — | | `confidenceThreshold` | No | integer | — | | `tableId` | Yes | string | — | | `enabled` | No | boolean | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 2, "maxLength": 100 }, "prompt": { "type": "string", "minLength": 10 }, "confidenceThreshold": { "type": "integer", "minimum": 60, "maximum": 100 }, "tableId": { "type": "string", "minLength": 1 }, "enabled": { "type": "boolean" } }, "required": [ "name", "prompt", "tableId" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "routing_rule": {} }, "required": [ "routing_rule" ], "additionalProperties": {} } ``` ## routing\_rules update Action: `routing_rules.update` Change a routing rule, including its prompt, destination, confidence threshold, or enabled state. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | --------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `rule_id` | Yes | string | — | | `name` | No | string | — | | `prompt` | No | string | — | | `confidenceThreshold` | No | integer | — | | `tableId` | No | string | — | | `enabled` | No | boolean | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "rule_id": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 2, "maxLength": 100 }, "prompt": { "type": "string", "minLength": 10 }, "confidenceThreshold": { "type": "integer", "minimum": 60, "maximum": 100 }, "tableId": { "type": "string", "minLength": 1 }, "enabled": { "type": "boolean" } }, "required": [ "rule_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "routing_rule": {} }, "required": [ "routing_rule" ], "additionalProperties": {} } ``` ## routing\_rules delete Action: `routing_rules.delete` Delete a routing rule from a project. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `rule_id` | Yes | string | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "rule_id": { "type": "string", "minLength": 1 } }, "required": [ "rule_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "result": {} }, "required": [ "result" ], "additionalProperties": {} } ``` ## splitters list Action: `splitters.list` List page-range and logical splitters, including drafts and published versions, in a project. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 } } } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "splitters": {} }, "required": [ "splitters" ], "additionalProperties": {} } ``` ## splitters get Action: `splitters.get` Inspect a splitter draft and its published versions. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 } }, "required": [ "splitter_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "splitter": {} }, "required": [ "splitter" ], "additionalProperties": {} } ``` ## splitters create\_logical Action: `splitters.create_logical` Create a logical splitter draft for mixed PDF attachments. sourceInboxId binds it to one inbox; null applies to project uploads. Routing uses project routing rules. Publish the draft to activate it. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `name` | Yes | string | — | | `description` | No | union | — | | `config` | Yes | object | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "description": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "null" } ] }, "config": { "type": "object", "properties": { "mode": { "type": "string", "const": "logical" }, "sourceInboxId": { "anyOf": [ { "type": "string", "minLength": 1 }, { "type": "null" } ] }, "instructions": { "type": "string", "minLength": 10, "maxLength": 4000 }, "sectionTypes": { "maxItems": 50, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{1,63}$" }, "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "description": { "type": "string", "maxLength": 500 } }, "required": [ "key", "name" ] } }, "routingMode": { "type": "string", "const": "project_rules" }, "reviewUncertainBoundaries": { "type": "boolean" }, "reviewUncertainDestinations": { "type": "boolean" }, "boundaryConfidenceThreshold": { "type": "integer", "minimum": 0, "maximum": 100 }, "maxSegments": { "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "mode", "sourceInboxId", "instructions", "sectionTypes", "routingMode", "reviewUncertainBoundaries", "reviewUncertainDestinations" ] } }, "required": [ "name", "config" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "splitter": {} }, "required": [ "splitter" ], "additionalProperties": {} } ``` ## splitters update\_logical Action: `splitters.update_logical` Update a logical splitter draft using the revision returned by splitters.get. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | ------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | | `expected_draft_revision` | Yes | integer | — | | `name` | Yes | string | — | | `description` | No | union | — | | `config` | Yes | object | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 }, "expected_draft_revision": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "description": { "anyOf": [ { "type": "string", "maxLength": 500 }, { "type": "null" } ] }, "config": { "type": "object", "properties": { "mode": { "type": "string", "const": "logical" }, "sourceInboxId": { "anyOf": [ { "type": "string", "minLength": 1 }, { "type": "null" } ] }, "instructions": { "type": "string", "minLength": 10, "maxLength": 4000 }, "sectionTypes": { "maxItems": 50, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{1,63}$" }, "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "description": { "type": "string", "maxLength": 500 } }, "required": [ "key", "name" ] } }, "routingMode": { "type": "string", "const": "project_rules" }, "reviewUncertainBoundaries": { "type": "boolean" }, "reviewUncertainDestinations": { "type": "boolean" }, "boundaryConfidenceThreshold": { "type": "integer", "minimum": 0, "maximum": 100 }, "maxSegments": { "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "mode", "sourceInboxId", "instructions", "sectionTypes", "routingMode", "reviewUncertainBoundaries", "reviewUncertainDestinations" ] } }, "required": [ "splitter_id", "expected_draft_revision", "name", "config" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "splitter": {} }, "required": [ "splitter" ], "additionalProperties": {} } ``` ## splitters create\_page\_range Action: `splitters.create_page_range` Create a splitter draft with fixed page ranges and project-owned destination tables. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `name` | Yes | string | — | | `description` | No | string | — | | `config` | Yes | object | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 2, "maxLength": 100 }, "description": { "type": "string", "maxLength": 1000 }, "config": { "type": "object", "properties": { "mode": { "type": "string", "const": "page_range" }, "overlap_policy": { "type": "string", "enum": [ "exclusive", "allowed" ] }, "unassigned_policy": { "type": "string", "enum": [ "review", "ignore", "fallback" ] }, "fallback_section_key": { "type": "string" }, "max_segments": { "type": "integer", "minimum": 1, "maximum": 100 }, "sections": { "minItems": 1, "type": "array", "items": { "type": "object", "properties": { "section_key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{1,63}$" }, "name": { "type": "string", "minLength": 1, "maxLength": 100 }, "description": { "type": "string", "maxLength": 1000 }, "destination_table_id": { "type": "string", "minLength": 1 }, "page_spans": { "minItems": 1, "type": "array", "items": { "type": "object", "properties": { "start_page": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "end_page": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 } }, "required": [ "start_page", "end_page" ] } } }, "required": [ "section_key", "name", "destination_table_id", "page_spans" ] } } }, "required": [ "sections" ] } }, "required": [ "name", "config" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "splitter": {} }, "required": [ "splitter" ], "additionalProperties": {} } ``` ## splitters update\_page\_range Action: `splitters.update_page_range` Update a fixed page-range splitter draft using its current draft revision. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | ------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | | `expected_draft_revision` | Yes | integer | — | | `name` | No | string | — | | `description` | No | union | — | | `config` | No | object | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 }, "expected_draft_revision": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "name": { "type": "string", "minLength": 2, "maxLength": 100 }, "description": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ] }, "config": { "type": "object", "properties": { "mode": { "type": "string", "const": "page_range" }, "overlap_policy": { "type": "string", "enum": [ "exclusive", "allowed" ] }, "unassigned_policy": { "type": "string", "enum": [ "review", "ignore", "fallback" ] }, "fallback_section_key": { "type": "string" }, "max_segments": { "type": "integer", "minimum": 1, "maximum": 100 }, "sections": { "minItems": 1, "type": "array", "items": { "type": "object", "properties": { "section_key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{1,63}$" }, "name": { "type": "string", "minLength": 1, "maxLength": 100 }, "description": { "type": "string", "maxLength": 1000 }, "destination_table_id": { "type": "string", "minLength": 1 }, "page_spans": { "minItems": 1, "type": "array", "items": { "type": "object", "properties": { "start_page": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "end_page": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 } }, "required": [ "start_page", "end_page" ] } } }, "required": [ "section_key", "name", "destination_table_id", "page_spans" ] } } }, "required": [ "sections" ] } }, "required": [ "splitter_id", "expected_draft_revision" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "splitter": {} }, "required": [ "splitter" ], "additionalProperties": {} } ``` ## splitters test\_page\_range Action: `splitters.test_page_range` Preview page assignments and review flags for a fixed page-range splitter without saving a run. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | | `page_count` | Yes | integer | — | | `version` | No | integer | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 }, "page_count": { "type": "integer", "minimum": 1, "maximum": 10000 }, "version": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 } }, "required": [ "splitter_id", "page_count" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "preview": {} }, "required": [ "preview" ], "additionalProperties": {} } ``` ## splitters publish Action: `splitters.publish` Publish a splitter draft. A logical splitter becomes active for its source inbox or project uploads. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | ------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | | `expected_draft_revision` | Yes | integer | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 }, "expected_draft_revision": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 } }, "required": [ "splitter_id", "expected_draft_revision" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "publication": {} }, "required": [ "publication" ], "additionalProperties": {} } ``` ## splitters run\_page\_range Action: `splitters.run_page_range` Run a published fixed page-range splitter on a document in this project. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | | `document_id` | Yes | integer | — | | `version` | No | integer | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 }, "document_id": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 }, "version": { "type": "integer", "minimum": 1, "maximum": 9007199254740991 } }, "required": [ "splitter_id", "document_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "run": {} }, "required": [ "run" ], "additionalProperties": {} } ``` ## splitters archive Action: `splitters.archive` Archive a splitter to stop using it for future documents. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `splitter_id` | Yes | string | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "splitter_id": { "type": "string", "minLength": 1 } }, "required": [ "splitter_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "result": {} }, "required": [ "result" ], "additionalProperties": {} } ``` ## rows search Action: `rows.search` Query extracted rows from a table in a project you own. Use for paginated raw records; use analysis.crosscheck for model-generated consistency findings or analysis.credit\_memo for an underwriting memo. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `table_id` | Yes | string | — | | `filters` | No | array | Row conditions combined with AND. Omit or pass \[] for no filtering. | | `orderBy` | No | object | — | | `page` | No | integer | — | | `pageSize` | No | integer | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "table_id": { "type": "string", "minLength": 1 }, "filters": { "description": "Row conditions combined with AND. Omit or pass [] for no filtering.", "type": "array", "items": { "type": "object", "properties": { "column": { "type": "string", "minLength": 1, "description": "Exact column name from tables.list, or document_record_id to select source file IDs. Unknown columns are rejected." }, "op": { "type": "string", "enum": [ "eq", "ne", "gt", "gte", "lt", "lte", "like", "in" ], "description": "Comparison operator: eq/ne for equality/inequality, gt/gte/lt/lte for ordered comparisons, like for SQL patterns (% matches any sequence, _ one character), or in for membership." }, "value": { "description": "Value matching the column type. Use a scalar for comparisons, a string pattern for like (for example Acme%), or an array for in (a scalar is also accepted as one item; an empty array matches no rows)." } }, "required": [ "column", "op", "value" ] } }, "orderBy": { "type": "object", "properties": { "column": { "type": "string" }, "direction": { "type": "string", "enum": [ "asc", "desc" ] } }, "required": [ "column", "direction" ] }, "page": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "pageSize": { "type": "integer", "exclusiveMinimum": 0, "maximum": 200 } }, "required": [ "table_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "rows": {} }, "required": [ "rows" ], "additionalProperties": {} } ``` ## jobs create Action: `jobs.create` Start extraction for documents already uploaded to a table. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `tableSlug` | Yes | string | — | | `documentKeys` | Yes | array | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "tableSlug": { "type": "string", "minLength": 1 }, "documentKeys": { "minItems": 1, "type": "array", "items": { "type": "string" } } }, "required": [ "tableSlug", "documentKeys" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "job": {} }, "required": [ "job" ], "additionalProperties": {} } ``` ## jobs get Action: `jobs.get` Get an extraction job in a project you own. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `job_id` | Yes | integer | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "job_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "job_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "job": {} }, "required": [ "job" ], "additionalProperties": {} } ``` ## documents upload Action: `documents.upload` Upload a PDF from base64 file bytes and save it. With tableSlug an extraction job is created immediately and returned as job; without it the document is routed automatically by project rules (poll documents.get). Maximum 8 MiB. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `filename` | Yes | string | — | | `data_base64` | Yes | string | — | | `tableSlug` | No | string | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "filename": { "type": "string", "minLength": 1, "maxLength": 255 }, "data_base64": { "type": "string", "minLength": 1, "maxLength": 11200000 }, "tableSlug": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "filename", "data_base64" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "uploadId": { "type": "string" }, "fileId": { "type": "string" }, "status": { "type": "string" }, "file_id": { "type": "string" }, "document_id": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "routing_mode": { "type": "string", "enum": [ "direct", "automatic" ] }, "job": { "anyOf": [ { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} }, { "type": "null" } ] }, "job_error": { "type": "string" }, "next_action": { "type": "object", "properties": { "tool": { "type": "string" }, "arguments": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} } }, "required": [ "tool", "arguments" ], "additionalProperties": {} } }, "required": [ "uploadId", "fileId", "status", "file_id", "document_id", "routing_mode", "job", "next_action" ], "additionalProperties": {} } ``` ## documents upload\_file Action: `documents.upload_file` Upload a user-selected ChatGPT PDF attachment and save it. With tableSlug an extraction job is created immediately and returned as job; without it the document is routed automatically (poll documents.get). Maximum 8 MiB. Use documents.upload for base64 bytes from Codex. OAuth scope: `mcp:write`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `file` | Yes | object | — | | `tableSlug` | No | string | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "file": { "type": "object", "properties": { "download_url": { "type": "string", "format": "uri" }, "file_id": { "type": "string", "minLength": 1, "maxLength": 255 }, "mime_type": { "type": "string" }, "file_name": { "type": "string", "maxLength": 255 } }, "required": [ "download_url", "file_id" ], "additionalProperties": false }, "tableSlug": { "type": "string", "minLength": 1, "maxLength": 255 } }, "required": [ "file" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "uploadId": { "type": "string" }, "fileId": { "type": "string" }, "status": { "type": "string" }, "file_id": { "type": "string" }, "document_id": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "routing_mode": { "type": "string", "enum": [ "direct", "automatic" ] }, "job": { "anyOf": [ { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} }, { "type": "null" } ] }, "job_error": { "type": "string" }, "next_action": { "type": "object", "properties": { "tool": { "type": "string" }, "arguments": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} } }, "required": [ "tool", "arguments" ], "additionalProperties": {} } }, "required": [ "uploadId", "fileId", "status", "file_id", "document_id", "routing_mode", "job", "next_action" ], "additionalProperties": {} } ``` ## documents get Action: `documents.get` Get a saved document by file\_id (from documents.upload) or numeric document\_id, including its status, destination table, extraction job IDs, and processing runs. The numeric id is required by splitters.run\_page\_range. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `file_id` | No | string | — | | `document_id` | No | integer | — | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "file_id": { "type": "string", "minLength": 1 }, "document_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } } } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "document": { "type": "object", "properties": { "id": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "file_id": { "type": [ "string", "null" ] }, "name": { "type": [ "string", "null" ] }, "status": { "type": "string" }, "page_count": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "file_size": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "table_id": { "type": [ "string", "null" ] }, "project_slug": { "type": "string" }, "created_at": { "type": [ "string", "null" ] }, "updated_at": { "type": [ "string", "null" ] }, "processed_at": { "type": [ "string", "null" ] }, "job_ids": { "type": "array", "items": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "processing_runs": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "job_id": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "job_status": { "type": [ "string", "null" ] }, "status": { "type": "string" }, "current_stage": { "type": [ "string", "null" ] }, "failure_code": { "type": [ "string", "null" ] }, "created_at": { "type": [ "string", "null" ] }, "updated_at": { "type": [ "string", "null" ] } }, "required": [ "id", "job_id", "job_status", "status", "current_stage", "failure_code", "created_at", "updated_at" ], "additionalProperties": {} } } }, "required": [ "id", "file_id", "name", "status", "page_count", "file_size", "table_id", "project_slug", "created_at", "updated_at", "processed_at", "job_ids", "processing_runs" ], "additionalProperties": {} }, "next_action": { "anyOf": [ { "type": "object", "properties": { "tool": { "type": "string" }, "arguments": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} } }, "required": [ "tool", "arguments" ], "additionalProperties": {} }, { "type": "null" } ] } }, "required": [ "document", "next_action" ], "additionalProperties": {} } ``` ## analysis crosscheck Action: `analysis.crosscheck` Analyze already extracted rows for consistency issues and underwriting risk contradictions, returning findings with row and field references in this call. Check jobs.get or documents.get and inspect rows.search before analysis; this does not run or wait for extraction or save changes. Requires mcp:read and sends bounded row evidence to an external model: at most 80 rows from the first 200 matches, with long values shortened. Inspect evidence for coverage. Use analysis.credit\_memo for a commercial loan memo; it includes a crosscheck internally. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `table_id` | Yes | string | ID or slug of the table containing already extracted rows, from tables.list in the selected project. Required even with job\_id; the job must belong to this table. | | `job_id` | No | integer | Positive integer extraction job ID from jobs.create, jobs.get, or an upload result. Restricts rows to that job's document file IDs and must belong to table\_id in the selected project. Omitting it adds no job restriction. This selects existing evidence; it does not start or wait for extraction. | | `filters` | No | array | Row conditions combined with AND, also intersected with the job document restriction when job\_id is supplied. Omit or pass \[] for no additional filtering. Uses the same column, op, and value format as rows.search. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "table_id": { "type": "string", "minLength": 1, "description": "ID or slug of the table containing already extracted rows, from tables.list in the selected project. Required even with job_id; the job must belong to this table." }, "job_id": { "description": "Positive integer extraction job ID from jobs.create, jobs.get, or an upload result. Restricts rows to that job's document file IDs and must belong to table_id in the selected project. Omitting it adds no job restriction. This selects existing evidence; it does not start or wait for extraction.", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "filters": { "description": "Row conditions combined with AND, also intersected with the job document restriction when job_id is supplied. Omit or pass [] for no additional filtering. Uses the same column, op, and value format as rows.search.", "type": "array", "items": { "type": "object", "properties": { "column": { "type": "string", "minLength": 1, "description": "Exact column name from tables.list, or document_record_id to select source file IDs. Unknown columns are rejected." }, "op": { "type": "string", "enum": [ "eq", "ne", "gt", "gte", "lt", "lte", "like", "in" ], "description": "Comparison operator: eq/ne for equality/inequality, gt/gte/lt/lte for ordered comparisons, like for SQL patterns (% matches any sequence, _ one character), or in for membership." }, "value": { "description": "Value matching the column type. Use a scalar for comparisons, a string pattern for like (for example Acme%), or an array for in (a scalar is also accepted as one item; an empty array matches no rows)." } }, "required": [ "column", "op", "value" ] } } }, "required": [ "table_id" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "mismatches": { "type": "array", "items": { "type": "object", "properties": { "code": { "type": "string" }, "severity": { "type": "string", "enum": [ "low", "medium", "high" ] }, "message": { "type": "string" }, "row_refs": { "type": "array", "items": { "type": "string" } }, "source_refs": { "type": "array", "items": { "type": "string" } } }, "required": [ "code", "severity", "message", "row_refs", "source_refs" ], "additionalProperties": false } }, "summary": { "type": "string" }, "evidence": { "type": "object", "properties": { "rows_total": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "rows_used": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "truncated": { "type": "boolean" }, "job_id": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "job_document_count": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] } }, "required": [ "rows_total", "rows_used", "truncated", "job_id", "job_document_count" ], "additionalProperties": false } }, "required": [ "mismatches", "summary" ], "additionalProperties": {} } ``` ## analysis credit\_memo Action: `analysis.credit_memo` Generate a first-pass commercial loan credit memo with citations from already extracted rows, returning the memo in this call. Includes a crosscheck internally; use analysis.crosscheck when you only need consistency findings. Check jobs.get or documents.get and inspect rows.search first; this does not run or wait for extraction or save changes. Requires mcp:read and sends bounded row evidence to an external model: at most 80 rows from the first 200 matches, with long values shortened. Inspect evidence for coverage and review citations and assumptions. OAuth scope: `mcp:read`. ### Parameters | Parameter | Required | Type | Description | | -------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `project_slug` | No | string | Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly. | | `table_id` | Yes | string | ID or slug of the table containing already extracted rows, from tables.list in the selected project. Required even with job\_id; the job must belong to this table. | | `job_id` | No | integer | Positive integer extraction job ID from jobs.create, jobs.get, or an upload result. Restricts rows to that job's document file IDs and must belong to table\_id in the selected project. Omitting it adds no job restriction. This selects existing evidence; it does not start or wait for extraction. | | `filters` | No | array | Row conditions combined with AND, also intersected with the job document restriction when job\_id is supplied. Omit or pass \[] for no additional filtering. Uses the same column, op, and value format as rows.search. | | `memo_profile` | Yes | string | Required memo template identifier. The only supported value is commercial-loan-v1, for a first-pass commercial loan underwriting memo. | ### Input schema ```json { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "project_slug": { "description": "Slug of an owned project from connection.info. May be omitted only when the account has exactly one visible project; otherwise select and pass a slug explicitly.", "type": "string", "minLength": 1 }, "table_id": { "type": "string", "minLength": 1, "description": "ID or slug of the table containing already extracted rows, from tables.list in the selected project. Required even with job_id; the job must belong to this table." }, "job_id": { "description": "Positive integer extraction job ID from jobs.create, jobs.get, or an upload result. Restricts rows to that job's document file IDs and must belong to table_id in the selected project. Omitting it adds no job restriction. This selects existing evidence; it does not start or wait for extraction.", "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "filters": { "description": "Row conditions combined with AND, also intersected with the job document restriction when job_id is supplied. Omit or pass [] for no additional filtering. Uses the same column, op, and value format as rows.search.", "type": "array", "items": { "type": "object", "properties": { "column": { "type": "string", "minLength": 1, "description": "Exact column name from tables.list, or document_record_id to select source file IDs. Unknown columns are rejected." }, "op": { "type": "string", "enum": [ "eq", "ne", "gt", "gte", "lt", "lte", "like", "in" ], "description": "Comparison operator: eq/ne for equality/inequality, gt/gte/lt/lte for ordered comparisons, like for SQL patterns (% matches any sequence, _ one character), or in for membership." }, "value": { "description": "Value matching the column type. Use a scalar for comparisons, a string pattern for like (for example Acme%), or an array for in (a scalar is also accepted as one item; an empty array matches no rows)." } }, "required": [ "column", "op", "value" ] } }, "memo_profile": { "type": "string", "const": "commercial-loan-v1", "description": "Required memo template identifier. The only supported value is commercial-loan-v1, for a first-pass commercial loan underwriting memo." } }, "required": [ "table_id", "memo_profile" ] } ``` ### Output schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "risk_score": { "type": "number", "minimum": 0, "maximum": 100 }, "sections": { "type": "array", "items": { "type": "object", "properties": { "title": { "type": "string" }, "content": { "type": "string" }, "citations": { "type": "array", "items": { "type": "string" } } }, "required": [ "title", "content", "citations" ], "additionalProperties": false } }, "assumptions": { "type": "array", "items": { "type": "string" } }, "memo_profile": { "type": "string", "const": "commercial-loan-v1" }, "evidence": { "type": "object", "properties": { "rows_total": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "rows_used": { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "truncated": { "type": "boolean" }, "job_id": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] }, "job_document_count": { "anyOf": [ { "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "null" } ] } }, "required": [ "rows_total", "rows_used", "truncated", "job_id", "job_document_count" ], "additionalProperties": false } }, "required": [ "risk_score", "sections", "assumptions", "memo_profile" ], "additionalProperties": {} } ``` --- # MCP usage examples Source: https://pdfparse.net/docs/mcp/examples Prompts and concrete MCP requests for PDF extraction, multiple tables, email routing, and splitter workflows. Use these prompts in your connected assistant. The JSON samples are tool arguments, not REST requests. Replace example slugs and IDs with values returned by your own account. ## Discover and create a project > Show my projects. Create a project called Purchasing if I do not already have one. 1. Call `connection.info` with `{}`. 2. If requested, call `projects.create` with `{"name":"Purchasing"}`. 3. Use the returned `project.slug` in later actions. ## Create a table and extract a PDF > Create a Purchase orders table in Purchasing. Extract the purchase order number, supplier, and total from this PDF, then show the saved rows. Call `tables.create`: ```json { "project_slug": "purchasing", "name": "Purchase orders", "columns": [ { "name": "po_number", "type": "text", "prompt": "The purchase order number printed on the document." }, { "name": "supplier", "type": "text", "prompt": "The supplier company name." }, { "name": "total", "type": "number", "prompt": "The final purchase order total, as a number." } ] } ``` Inspect the result or call `tables.list` to get the table's actual ID and slug. Then call `documents.upload` with the actual PDF bytes: ```json { "project_slug": "purchasing", "filename": "purchase-order.pdf", "data_base64": "", "tableSlug": "" } ``` The base64 placeholder must be replaced before calling the action. A local filename alone does not upload anything. Supplying `tableSlug` selects the extraction destination; omitting it uses the project's routing path. If you already have stored document keys for that table, `jobs.create` starts extraction: ```json { "project_slug": "purchasing", "tableSlug": "", "documentKeys": [""] } ``` Use `jobs.get` with `project_slug` and the returned numeric `job_id` to inspect progress. Avoid creating another extraction job for an upload that already started processing. Verify the results with `rows.search`: ```json { "project_slug": "purchasing", "table_id": "", "page": 1, "pageSize": 50 } ``` ## Preview an email workflow > In my Purchasing project, prepare an inbox that classifies supplier purchase orders and extracts their order number and total. Only accept mail from my supplier domain. Show me the configuration before applying it. The assistant calls `workflow.setup` with a structured intent: ```json { "dry_run": true, "goal": "Organize supplier purchase orders received by email.", "project": { "existing_slug": "purchasing" }, "table": { "name": "Emailed purchase orders", "columns": [ { "name": "po_number", "type": "text", "prompt": "The purchase order number." }, { "name": "total", "type": "number", "prompt": "The final purchase order total." } ] }, "routing_rule": { "name": "Purchase orders", "prompt": "A purchase order issued to a supplier, containing an order number and ordered goods.", "confidenceThreshold": 85, "enabled": true }, "inbox": { "name": "Supplier purchase orders", "routing": "classify", "sender_allowlist": [{ "type": "domain", "value": "supplier.example" }] } } ``` Replace the supplier domain, review the preview, then send the same configuration with `dry_run: false`. Inspect the returned resources and use `inboxes.list` to confirm the inbox address. A preview describes planned steps; it does not create resources or prove an email has been processed. ## Route into multiple tables > Use separate tables for purchase orders and invoices, and route incoming PDFs to the matching table. 1. Call `tables.create` once for each table. 2. Call `routing_rules.create` for each document type using the corresponding returned `tableId`. 3. Inspect `routing_rules.list` and upload a representative document through the routing path. 4. Check saved rows and review uncertain classifications before treating the workflow as verified. Example routing rule: ```json { "project_slug": "purchasing", "name": "Supplier invoices", "prompt": "An invoice requesting payment for goods or services, with an invoice number and amount due.", "tableId": "", "confidenceThreshold": 85, "enabled": true } ``` `workflow.setup` currently creates one table per intent. Its input does not accept a `tables` array. ## Split a mixed document > Prepare a logical splitter that separates purchase orders from invoices in mixed PDF attachments, using my project's routing rules. Let me review it before publishing. Call `splitters.create_logical`: ```json { "project_slug": "purchasing", "name": "Purchasing packet", "config": { "mode": "logical", "sourceInboxId": null, "instructions": "Separate each purchase order and invoice into its own document section.", "sectionTypes": [ { "key": "purchase_order", "name": "Purchase order" }, { "key": "invoice", "name": "Invoice" } ], "routingMode": "project_rules", "reviewUncertainBoundaries": true, "reviewUncertainDestinations": true } } ``` `sourceInboxId: null` targets project uploads. Use an inbox ID from `inboxes.list` to bind the splitter to that inbox instead. Creating a draft does not activate it. Inspect it with `splitters.get`, then call `splitters.publish` with its `splitter_id` and current `expected_draft_revision` after reviewing the configuration. For known page layouts, use `splitters.create_page_range`, then `splitters.test_page_range` to preview assignments. Publish the draft before `splitters.run_page_range` processes an existing document. There is no separate logical-splitter test action in the current MCP catalog. ## Analyze saved data > Crosscheck the extracted rows for inconsistencies and show the source references for each finding. Wait for extraction using `jobs.get` or `documents.get`, then inspect `rows.search`. Call `analysis.crosscheck` for consistency findings, or `analysis.credit_memo` for a commercial loan memo. Memo generation includes a crosscheck internally, so a separate crosscheck call is unnecessary when you only need the memo. Both require `mcp:read`, return their model-generated analysis in the same call, and leave saved data unchanged. Pass a table ID or slug from `tables.list` as `table_id`. Optional `job_id` must identify a job for that table in the selected project; it restricts evidence to the job's document file IDs. Filters are combined with AND and further narrow that selection. For example, call `analysis.credit_memo` with: ```json { "project_slug": "purchase-orders", "table_id": "your-table-id", "job_id": 17, "memo_profile": "commercial-loan-v1", "filters": [{ "column": "document_record_id", "op": "in", "value": ["your-file-id"] }] } ``` Omit `job_id` to analyze without a job restriction, and omit `filters` or pass `[]` for no additional filtering. `commercial-loan-v1` is the only supported memo profile. Use `connection.info` to select `project_slug`; omission works only when the account has exactly one visible project. Analysis sends bounded evidence to an external model: at most 80 rows from the first 200 matches, with long values shortened. Inspect the returned `evidence` coverage and review citations and assumptions before relying on the result. Use `rows.search` for paginated access to the raw records. See the [complete action reference](https://pdfparse.net/docs/mcp/actions) for all input constraints and output schemas. --- # Connect to the PdfParse MCP server Source: https://pdfparse.net/docs/mcp Connect an AI assistant to PdfParse to upload PDFs, create extraction tables, query saved data, and configure document workflows. PdfParse exposes document processing actions through a remote Model Context Protocol (MCP) server. Your assistant can discover the available actions and call them on your behalf after you authorize access to your PdfParse account. ## Connection settings | Setting | Value | | ---------------- | ------------------------------ | | Server URL | `https://mcp.pdfparse.net/mcp` | | Transport | Streamable HTTP | | Authentication | OAuth | | Read permission | `mcp:read` | | Write permission | `mcp:write` | Add the URL as a remote MCP server in a client that supports Streamable HTTP and OAuth. Follow the sign-in and consent flow. Project API keys do not authenticate this MCP endpoint. The documentation lives here on `pdfparse.net`; the MCP subdomain is the protocol endpoint. ## First conversation Start with: > Show my PdfParse projects and the tables in the project I choose. The assistant uses `connection.info` to discover your projects and `tables.list` to inspect a selected project. Supply `project_slug` explicitly when working across projects. Actions operate on projects owned by the connected account. Then try: > Create a purchase-orders table in my selected project, with purchase order number, supplier, order date, and total columns. Upload this PDF into that table and show the extracted rows when processing finishes. See the [usage examples](https://pdfparse.net/docs/mcp/examples) for the exact action sequence and request inputs. Tables created through MCP include an automatic integer primary key named `id`, just like tables created in the dashboard. Supply only the fields you want extracted; the database generates `id` when a row is saved. This also applies to tables provisioned by `workflow.setup`. ## Available capabilities * **Accounts and projects:** identify the connected account, list owned projects, and create a project. * **Tables and data:** list or create extraction tables and query saved rows. * **Documents and jobs:** upload PDFs, start extraction for existing document keys, and inspect job status. * **Routing:** list, create, update, and delete document classification rules. * **Splitters:** create logical or fixed page-range drafts, inspect and update them, publish or archive them, and preview or run fixed page-range splitting. * **Email workflows:** list inboxes and provision an inbox as part of workflow setup. * **Workflow setup:** preview a structured intent, then provision a table, routing rule, optional inbox, and optional logical splitter in an existing project. * **Analysis:** crosscheck extracted data and generate a commercial loan credit memo with citations. The [action reference](https://pdfparse.net/docs/mcp/actions) lists every action, its permission, parameters, and schemas. ## Uploading a local document The remote server cannot read a path on your computer. A client with local file access must read the PDF and pass its bytes as `data_base64` to `documents.upload`. PDFs must be no larger than **8 MiB before base64 encoding**. `documents.upload_file` accepts a client-provided attachment object containing `download_url` and `file_id`. It requires a configured, approved download host. If the server reports that attachment downloads are not configured, use `documents.upload` with PDF bytes from a client that can read the file. Attaching a PDF in a chat does not guarantee the client can deliver it through MCP. Uploads return `uploadId`, `fileId`, and `status`. These acknowledge ingestion; they do not prove extraction has finished. Check job status when a job ID is available and query saved rows before reporting success. Do not substitute `fileId` for a numeric job ID or assume it is an extraction document key. ## Workflow setup limits `workflow.setup` takes structured fields, rather than a free-text goal alone. The assistant turns your request into a table schema, classification prompt, and optional inbox or splitter configuration. Use it for coordinated creation of a new table and routing rule, optionally with a new inbox and published logical splitter. To reuse an existing table or make individual configuration changes, use `tables.create`, `routing_rules.create`, `routing_rules.update`, and the relevant `splitters` actions. * Use an existing project. Call `projects.create` separately if you need a new one. * Preview with `dry_run: true`, review the configuration, then apply with `dry_run: false`. * Each intent provisions one table. Use separate table actions for additional tables. * Identical applied intents reuse saved progress. Inspect `in_progress` or partial/error results before retrying; saved checkpoints are not a guarantee of atomic setup across services. * Publishing a splitter activates configuration for future documents. Review the destination and inbox before publishing. ## Troubleshooting | Result | Next step | | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | Authentication required | Reconnect using OAuth and finish sign-in and consent. | | Missing `mcp:read` or `mcp:write` | Reauthorize with the permission needed by the action. Even a workflow preview requires write permission. | | Select a `project_slug` | Call `connection.info`, select an owned project, and pass its slug. | | Attachment downloads are not configured | Send PDF bytes through `documents.upload` from a client with local file access. | | Draft revision conflict | Call `splitters.get`, review the current draft, and use its revision in the update or publish request. | | No extracted rows yet | Check the extraction job and table configuration. An accepted upload can still be processing or awaiting routing/review. | Errors can be returned as MCP tool results with `isError: true`; an HTTP 200 alone does not mean the action succeeded. Analysis output is a first pass and should be reviewed against the cited source data.