PapermarkDocs

Share a password-protected link

Upload a document and create a link with a password and expiry.

The classic flow: you have a PDF on your laptop, you want to share it with one person, with a password the email can't be screenshotted around, that expires after a deadline.

One command does it all if you don't need a custom name:

papermark documents upload ./pitch.pdf --link

For full control, do it in two steps so you can pass the access controls:

$ DOC_ID=$(papermark documents upload ./pitch.pdf --json \
    | jq -r '.data.id')

$ papermark links create \
    --document "$DOC_ID" \
    --name "Acme — read-only" \
    --password "Open-Sesame-2026" \
    --expires 2026-05-31T17:00:00Z \
    --email-protected
ID:    link_abcd1234
URL:   https://papermark.com/view/abcd1234efgh

--email-protected requires viewers to enter their email before seeing the doc — useful for getting a record of who looked, paired with the password as an authentication factor.

Three calls: get a presigned URL, PUT the file to S3, register the document, then create the link. The CLI bundles steps 1–3 — for clarity, here they are unwrapped:

TOKEN=pm_live_…

# 1. Get a presigned upload URL
UPLOAD=$(curl -X POST https://api.papermark.com/v1/documents/upload-url \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"filename":"pitch.pdf","contentType":"application/pdf"}')

UPLOAD_URL=$(echo "$UPLOAD" | jq -r '.data.uploadUrl')
S3_KEY=$(echo "$UPLOAD" | jq -r '.data.key')

# 2. Upload the file
curl -X PUT "$UPLOAD_URL" \
  --upload-file ./pitch.pdf \
  -H "Content-Type: application/pdf"

# 3. Register the document
DOC=$(curl -X POST https://api.papermark.com/v1/documents \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"Pitch Deck\",\"key\":\"$S3_KEY\"}")

DOC_ID=$(echo "$DOC" | jq -r '.data.id')

# 4. Create the protected link
curl -X POST https://api.papermark.com/v1/links \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"documentId\": \"$DOC_ID\",
    \"name\": \"Acme — read-only\",
    \"password\": \"Open-Sesame-2026\",
    \"expiresAt\": \"2026-05-31T17:00:00Z\",
    \"emailProtected\": true
  }"

Required scopes: documents.write for steps 1–3, links.write for step 4.

Once the MCP server is wired into Claude or ChatGPT:

Upload ~/Desktop/pitch.pdf to Papermark and create a share link protected with the password "Open-Sesame-2026", expiring May 31, 2026 at 5pm UTC, that requires viewers to enter their email.

The agent calls upload_document (stdio transport only) followed by create_link with the right arguments and gives you the URL.

For browser-hosted clients (claude.ai Connectors, ChatGPT Apps) that can't read your filesystem, attach the file in the chat first and then ask the agent to share it.

What the recipient sees

  1. They open the URL.
  2. If emailProtected: true, they enter their email.
  3. They enter the password.
  4. They see the document inline (no download by default — pass --allow-download / allowDownload: true if you want them to be able to save a copy).

After expiresAt, the URL returns a friendly "this link has expired" page. The document itself isn't deleted — you can mint a new link any time without re-uploading.

Revoking early

papermark links delete link_abcd1234

Works immediately. Anyone with the URL gets the expired page on their next request.

On this page