Read full docsRun data rooms from your terminal. Full CLI reference
Install
npm install -g papermark
papermark --version
# papermark/0.x.x darwin-arm64 node-20Authenticate
Two ways. Pick the one that fits the machine.
Device flow (interactive)
papermark login
# → Open https://app.papermark.com/oauth/device
# → Enter code: WDJB-MJHTStatic token (CI)
Mint a dashboard token at app.papermark.com/settings/tokens ↗ and either export it or pass it inline:
export PAPERMARK_TOKEN=pm_live_…
# or
papermark login --token pm_live_…The CLI resolves credentials in this order. First match wins:
PAPERMARK_TOKENenvironment variablePAPERMARK_CREDENTIALS_FILEpointing to JSON- Local config at
~/.config/papermark/config.json
Command groups
papermark auth # login, logout, whoami, export, set
papermark datarooms # create, list, get, update, delete, analytics
papermark documents # upload, list, get, search, update, delete, versions
papermark folders # create, list, get, update, move, delete
papermark links # create, list, get, update, revoke, views
papermark views # get, analytics
papermark visitors # list, get, views
papermark config # set api-url, color, output
papermark doctor # health checkExamples
papermark datarooms create \
--name "Q4 Investors" \
--description "FY2026 board materials"DOC=$(papermark documents upload deck.pdf --json | jq -r '.data.id')
DR=$(papermark datarooms create --name "Acme Series A" --json | jq -r '.data.id')
papermark datarooms attach $DR --document $DOCpapermark links create \
--dataroom $DR \
--password pelican-42 \
--expires 2026-12-31 \
--require-emailpapermark links views $LINK_ID --since 2026-05-01 --json \
| jq '.data[] | {email: .visitor.email, viewed: .viewed_at, duration: .duration_seconds}'Global flags
--json. Machine-readable output. Stable contract.--dry-run. Print the HTTP request that would execute, with the token redacted. Great for debugging or PR review.--no-color. Disable ANSI colors. Useful in logs.--api-url. Override the base URL (self-hosted Papermark).--token. Pass a token inline, bypassing the resolver.
Output shape
With --json, every command emits the same envelope as the REST API:
{
"ok": true,
"data": { … },
"meta": { "next_cursor": "cur_…" }
}Errors set ok: false and exit non-zero. Pair with set -e in shell scripts.
CI patterns
GitHub Actions
name: Share investor deck
on:
push:
paths: ['decks/**']
jobs:
share:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm install -g papermark
- name: Upload and link
env:
PAPERMARK_TOKEN: ${{ secrets.PAPERMARK_TOKEN }}
run: |
DOC=$(papermark documents upload decks/latest.pdf --json | jq -r '.data.id')
papermark links create --document $DOC --password "${{ secrets.LINK_PASSWORD }}" --jsonCron / scheduled tasks
# Snapshot dataroom analytics every morning
0 9 * * * PAPERMARK_TOKEN=$(cat ~/.papermark.token) \
papermark datarooms analytics dr_01HX7 --json > /var/log/dataroom-$(date +%F).jsonWhen not to use the CLI
The CLI spawns a Node process per call. Expect 50-150 ms of overhead. For high-throughput or latency-sensitive code, call the REST API directly or use an SDK.