/dev/papermark

Build on top of Papermark Data Rooms. Documents, links, visitors, and analytics over REST, CLI, or MCP.

npm install -g papermark
GET /v1/datarooms/dr_3qpL

Acquisition Data Room

live312 pages26 visitors
All documentsFinancialsLegalDiligenceContracts
DocumentIDStatusTop visitorRead
PDFCIM v4doc_cim_v4viewed · 41xvsvs_3m9k87%
XLSOperating model FY26doc_model_FY3downloadedvsvs_8m2k62%
PDFCap table · post-moneydoc_cap_v2NDA acceptedvsvs_7Tq264%
PDFTerm sheet · draft 3doc_term_03draftvsvs_2pqj-
$papermark documents list
GET /v1/documents · 200
312 results · 26 pages
ok · 142ms
[Q]01 Quickstart

From signup to your first
API call in five minutes.

Three steps. Create an account, mint a scoped token, make a request. Tokens look like pm_live_... and act as a long-lived bearer credential.

Data RoomAcquisition312 pages · synced
Documents
Folders
Links
Visitors
Analytics
first-call.sh
# 1. set your token (mint one in Settings → API Tokens)
export PAPERMARK_TOKEN=pm_live_AbCdEfGhIjKlMnOpQrStUvWxYz

# 2. list your documents
curl https://api.papermark.com/v1/documents \
  -H "Authorization: Bearer $PAPERMARK_TOKEN"

# →
{
  "data": [
    { "id": "doc_pitch_v4", "name": "Pitch Deck.pdf" }
  ],
  "next_cursor": null
}
# 1. install the CLI
$ npm install -g papermark

# 2. log in via OAuth device flow
$ papermark login
 open https://app.papermark.com/device
 token stored · ~/.config/papermark/auth.json

# 3. list your documents
$ papermark documents list --json
[
  { "id": "doc_pitch_v4", "name": "Pitch Deck.pdf" }
]
// 1. install the SDK
// npm install papermark

import { Papermark } from "papermark";

const pm = new Papermark({ apiKey: process.env.PAPERMARK_TOKEN });

// 2. list your documents
const { data } = await pm.documents.list();

// → [ { id: "doc_pitch_v4", name: "Pitch Deck.pdf" } ]
  • Scoped tokens. Pick exactly what each token can do. Read-only for an LLM agent, full access for a CI job.
  • OAuth 2.1 device flow. The CLI and MCP server walk users through a browser-based device-code login. No copy-paste tokens.
  • One auth, three surfaces. The same token works in the curl example, the papermark CLI, and @papermark/mcp-server.
[A]02 REST API

43 operations. 6 resources.
One bearer token.

A small, deliberately boring REST surface: HTTP + JSON + bearer tokens. Data Rooms, documents, folders, links, visitors, and analytics. The full spec lives at /docs/openapi.json and generates every reference page on the site, so nothing drifts.

  • {}Data Rooms. Create, list, update, delete; attach documents; manage folders. The primary access boundary for a set of documents.
  • Links. Mint a share link for a document or a dataroom. Set password, expires_at, email_gate, and download permission.
  • Visitors & analytics. List visitors, list_visitor_views, and pull page-by-page durations through get_view_analytics.
  • S3 presigned uploads. Large files use direct-to-S3 presigned URLs. No 10 MB multipart limit, no streaming gymnastics in your code.
create-link.ts
// create a password-gated link to a Data Room
const res = await fetch(
  "https://api.papermark.com/v1/links",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.PAPERMARK_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      dataroom_id: "dr_8K2m",
      password: "series-b-2026",
      expires_at: "2026-06-10T00:00:00Z",
      email_gate: true,
      allow_download: false,
    }),
  },
);

const { id, url } = await res.json();
# create a password-gated link to a Data Room
import os, requests

res = requests.post(
    "https://api.papermark.com/v1/links",
    headers={
        "Authorization": f"Bearer {os.environ['PAPERMARK_TOKEN']}",
        "Content-Type": "application/json",
    },
    json={
        "dataroom_id": "dr_8K2m",
        "password": "series-b-2026",
        "expires_at": "2026-06-10T00:00:00Z",
        "email_gate": True,
        "allow_download": False,
    },
)

link = res.json()
print(link["url"])
# create a password-gated link to a Data Room
curl -X POST https://api.papermark.com/v1/links \
  -H "Authorization: Bearer $PAPERMARK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "dataroom_id": "dr_8K2m",
    "password": "series-b-2026",
    "expires_at": "2026-06-10T00:00:00Z",
    "email_gate": true,
    "allow_download": false
  }'
[G]03 Agent tools

43 typed MCP tools.
Drop Papermark into Claude.

@papermark/mcp-server on npm exposes the full API to any MCP client. Stdio for local clients (Claude Desktop, Claude Code), HTTP at mcp.papermark.com/mcp for browser clients (claude.ai Connectors, ChatGPT Apps). Same 43 tools, same shapes.

@papermark/mcp-server
connected
DR
create_dataroom
name, description, folder structure
tool
UP
upload_document
file_path or source_url, dataroom_id?
tool
LK
create_link
document_id | dataroom_id, password?, expires_at?
tool
LV
list_link_views
link_id, since?, until?
tool
LS
search_documents
query, limit, cursor
tool
AN
get_view_analytics
view_id - page-by-page durations
tool
~/Library/.../Claude/
{
  "mcpServers": {
    "papermark": {
      "command": "npx",
      "args": ["-y", "@papermark/mcp-server"],
      "env": {
        "PAPERMARK_TOKEN": "pm_live_..."
      }
    }
  }
}

// then in Claude: "list my papermark documents"
// or: "create a Data Room called Series B and
// upload every PDF in ~/acme/"
# remote MCP server (no install required)
# works with Cursor, Continue, Claude Code, any MCP client

{
  "papermark": {
    "url": "https://mcp.papermark.com",
    "transport": "http",
    "headers": {
      "Authorization": "Bearer pm_live_..."
    }
  }
}

# 43 tools available out of the box:
# create_dataroom, upload_document, create_link,
# search_documents, get_view_analytics, ...
[V]04 Visitors & analytics

Every viewer interaction
is a queryable event.

Track who opened which link, which page they spent time on, where they dropped off. Roll up by document, by link, by Data Room, or by an individual view. Real-time, page-level, per-visitor.

Pull the events you need, when you need them.

  • Per-visitor history. GET /v1/visitors/:id/views returns every document opened, with timing and dwell per page.
  • Per-link analytics. list_link_views filtered by date returns who clicked, who verified, and how far through each viewer got.
  • Page-level engagement. get_view_analytics(view_id) returns the page-by-page durations. Find where prospects drop off in your deck.
GET /v1/view-analytics/vw_3m9k
{
  "view_id": "vw_3m9k",
  "link_id": "lk_8K2m",
  "document_id": "doc_pitch_v4",
  "visitor": {
    "email": "alex@olivetree.vc",
    "verified": true
  },
  "engagement": {
    "pages_viewed": 14,
    "completed": 0.87,
    "duration_ms": 412300,
    "top_page": 12,
    "page_durations_ms": [
      2100, 14200, 8900, 41300,
      28100, 12400, ...
    ]
  }
}
[C]05 CLI

The same surface,
from your terminal.

papermark on npm. One binary, the same token as the API, every command with --json for pipelines and machine-readable error codes. CI-friendly by design.

~/.config/papermark/
$ npm install -g papermark

# OAuth 2.1 device flow
$ papermark login
 open https://app.papermark.com/device
 enter code: WBKR-FXPL
 token stored · ~/.config/papermark/auth.json

# or skip the browser and use a long-lived token
$ papermark login --token pm_live_...

$ papermark whoami
leila@papermark.com · team_zenith · scopes: documents.*, datarooms.*
# list every Data Room you can access
$ papermark datarooms list --json
[
  { "id": "dr_3qpL", "name": "Acquisition", "pages": 312 },
  { "id": "dr_8K2m", "name": "Series B", "pages": 148 },
  { "id": "dr_4nfP", "name": "LP update Q4", "pages": 24 }
]

# list documents inside one Data Room
$ papermark documents list --dataroom dr_3qpL
doc_pitch_v4   Pitch Deck.pdf      2.1 MB
doc_model_FY3  FY26 Model.xlsx     1.4 MB
doc_cap_v2     Cap Table.pdf       180 KB
# upload a single file
$ papermark documents upload ./pitch.pdf
 uploading pitch.pdf (2.1 MB) ok
 doc_pitch_v5 created

# upload a folder into a Data Room
$ papermark documents upload ./diligence/ \
    --dataroom dr_3qpL --recursive
 12 files queued · 148 pages
 uploading model.xlsx ok
 uploading nda_v3.pdf ok
 uploading cap_table.pdf ok
 12/12 uploaded · dr_3qpL
$ papermark datarooms create
# create a Data Room from the CLI
$ papermark datarooms create \
    --name "Series B" --json

{ "id": "dr_8K2m", "name": "Series B" }

# upload every PDF in a folder
$ papermark documents upload ./pitch.pdf \
    --dataroom dr_8K2m --json

 uploading pitch.pdf (2.1 MB) ok
 attached to dr_8K2m ok

# mint a password-gated link
$ papermark links create --dataroom dr_8K2m \
    --password series-b-2026 --json

 https://papermark.com/view/abc...
[P]06 Platform

One Papermark,
four ways in.

Pick the surface that fits your stack. Same models, same auth.

REST APIapi.papermarkVersioned HTTPS for every Data Room resource: documents, folders, links, visitors, analytics. 43 operations, idempotency keys, paginated cursors.
POST /v1/datarooms
POST /v1/documents
POST /v1/links
GET  /v1/visitors/:id/views
CLIpapermarkpapermark on npm. Single binary. Same token as the API. --json output on every command for pipelines and CI.
$ npm install -g papermark
$ papermark login
$ papermark documents list --json
MCP server/mcp43 typed tools wrapping the API. Stdio for Claude Desktop and Claude Code, HTTP for claude.ai Connectors and ChatGPT Apps.
stdio: @papermark/mcp-server
http:  https://mcp.papermark.com/mcp
OpenAPIopenapi.jsonThe whole surface as a single OpenAPI document. Generate clients, drive contract tests, or render your own docs site. Reference docs on papermark.com generate from this.
GET /docs/openapi.json
$ openapi-typescript ./openapi.json \
-o ./papermark.d.ts
[X]07 The document graph

Every surface, one
resolvable graph.

Documents, folders, Data Rooms, links, visitors, and views all live in the same graph. Scopes, audit logs, and analytics roll up automatically, so the CLI, an agent on MCP, and your own backend all see the same picture.

Inputs
UPDirect upload
S3S3 presigned URL
CLCLI upload
MCMCP upload_document
APREST POST /v1/documents
Papermarkdocument graphlive
Surfaces
VWHosted viewer
LKShare links
AGAgents (MCP)
ANView analytics
AUAudit log

Ship Data Room workflows.

Open source on GitHub. Hosted on papermark.com. Self-hostable on your own infrastructure.

npm install -g papermark