PapermarkDocs

Changelog

Release notes for the API, CLI, and MCP server.

Hand-curated, one section per package. Releases follow Changesets on each repo; this page surfaces the human-readable summary.

The CONTRACT version for the CLI's machine-readable output is covered separately on Output contract. A new CLI minor version doesn't mean a new contract version; those are deliberately decoupled.

REST API

2026-09-23: Team brands and per-dataroom branding

Branding is now settable over the API. GET/POST /v1/brands and GET/PATCH/DELETE /v1/brands/{id} manage the team's named brands (logo, banner, colors, welcome message and call to action, dataroom layout, link preview, viewer language); exactly one brand is the team default (is_default), and the first brand you create becomes it. GET/PATCH /v1/datarooms/{id}/branding choose what a dataroom shows: team_default, a pinned team_brand, or its own custom branding, which starts from the brand visitors currently see the first time you switch to it.

Images go in one of two ways: { "source_url": "https://..." } on any write, or the raw file bytes to PUT /v1/brands/{id}/images/{slot} and PUT /v1/datarooms/{id}/branding/images/{slot} with the real Content-Type. PNG and JPEG (ICO for the favicon), 2 MB logo, 4 MB banner and preview image, 1 MB favicon, no SVG. The dataroom image route returns 409 conflict unless the room is in custom mode.

Plan-gated fields return 403 plan_restriction with details.fields naming every blocked field; resetting a field to its default is never gated. New scopes branding.read and branding.write cover /v1/brands*; the dataroom branding routes use datarooms.read and datarooms.write. apis.read already includes branding.read. See the guide Brand a data room.

POST /v1/links accepts an optional preset_id that seeds every preset-controlled setting; any field you also pass overrides the preset. The preset's social-card metadata (custom OG tags — title, description, image, favicon) is applied too. Because there's no image-upload path in the API, a preset is the only way to set a link's preview metadata.

New settable fields on POST /v1/links and PATCH /v1/links/{id}: welcome_message, enable_notification, show_banner, and custom_fields (custom form fields with per-field config; on update they full-replace the existing set, and [] clears them). The link object now returns these fields. The number of custom_fields per link is capped by plan.

password, expires_at, and watermark_config now accept an explicit null on create, so you can clear a preset's value for a single link.

2026-05-08: Strict request validation

Every v1 endpoint now rejects unknown fields with 422 unprocessable_entity instead of silently dropping them. Both request bodies and query strings are validated. The error envelope names the offending key in details.formErrors[0], e.g. "Unrecognized key(s) in object: 'dataroom_id'". Conforming requests are unaffected.

If you were relying on any of these footguns, the request was already a no-op; the field was being silently discarded:

  • POST /v1/documents { folder_path: "..." } was never accepted. Use folder_id, and create the folder first via POST /v1/folders if it doesn't exist yet (paths are derived server-side and read-only).
  • POST /v1/folders { name, dataroom_id } was never creating a dataroom-scoped folder, just a top-level team-library folder. For folders inside a dataroom, use POST /v1/datarooms/{id}/folders.
  • parent_folder_id is not an accepted alias of parent_id. The canonical key, on every folder endpoint, library and dataroom, is parent_id.

The generated OpenAPI spec now carries additionalProperties: false on every *Request component, so SDK generators inherit the constraint downstream.

2026-04-30: api.papermark.com scoped to /v1

The api.papermark.com host now serves only the public /v1 surface. Every other path returns 404 (including /api/*, /oauth/*, and /.well-known/*); the root / redirects to the docs. OAuth, OIDC discovery, and the MCP HTTP transport were never intended to live on the API host, but the broad rewrite that mapped api.papermark.com/* to the app meant they incidentally worked. This change locks the host down to its public contract.

If you discover OAuth via OIDC, nothing changes; the CLI does this automatically and third-party clients should too. If you hard-coded https://api.papermark.com/oauth/... URLs, switch to the canonical issuer (see Authentication).

2026-04-29: Upload contract: upload_id

POST /v1/documents/upload-url now returns an opaque one-time upload_id instead of upload_key + storage_type, and POST /v1/documents accepts upload_id in place of source_key. The two-step upload flow is unchanged; only the field names. Several response payloads also moved from camelCase to snake_case (contentType → content_type, numPages → num_pages) to match the rest of the API.

2026-04-29: Supported file types widened

Added MIME support for .tif/.tiff, .ecw, .bak, and .eml, plus the .err / .prj / .jgw extensions under text/plain. A new "other" value joins the document simple-type enum. Affects POST /v1/documents/upload-url (the accepted content_type set widened) and the upload tooling in the CLI and MCP server.

v1.0: initial public release

  • 25 endpoints across documents, links, datarooms, visitors, analytics
  • OAuth 2.1 device flow + dashboard tokens (pm_live_…)
  • Per-token rate limits (60 RPM default), X-RateLimit-* headers on every response
  • Structured error envelope with code / message / doc_url

The API is versioned in the URL path (/v1/). Breaking changes go to /v2/; existing clients keep working until announced deprecation. No deprecations on the table today.

CLI: papermark on npm

2026-09-23: brands commands and datarooms branding

New papermark brands group: list, get, create, update, delete. New papermark datarooms branding get|set with --mode team_default|team_brand|custom and --brand <id> for team_brand. Brand and custom dataroom branding share one set of flags named after the API fields (--brand-color, --welcome-message, --card-layout, and so on; "" clears). Image flags (--logo, --banner, --link-preview-image, --link-preview-favicon) take a local PNG/JPEG/ICO file, an https:// URL, or "" to remove; --banner hidden hides the banner. Local files are checked for type and size before anything is sent.

papermark login now also requests branding.read and branding.write; sessions created earlier need a fresh login to use the new commands. --dry-run summarizes a binary request body as <N bytes type from path> instead of printing it.

links create gains --preset <id> (seed the link from a saved preset) plus --welcome-message, --notification <on|off>, --banner, and --custom-fields <json>. links update gains --welcome-message, --notification <on|off>, --banner <on|off>, and --custom-fields (full replace). When --preset is used, boolean flags left unset defer to the preset instead of forcing the setting off.

0.1.0: first public alpha

  • 7 command groups, 25 commands total: login, logout, whoami, auth export, auth set, doctor, documents (5), datarooms (8: list, get, create, update, links, viewers, stats, documents), links (4), views (1), config (3)
  • OAuth 2.1 device flow + token paste
  • Three-place credential resolution (PAPERMARK_TOKEN → PAPERMARK_CREDENTIALS_FILE → config file)
  • Output contract v1: stable JSON envelopes, exit code mapping, retryable semantics
  • Skill manifest (SKILL.md) and OpenAI App manifest (openai.yaml) shipped in the tarball for auto-discovery

The 0.1.0 version means "expect minor breaking changes between versions while we're in alpha." The output contract is stable and versioned independently.

MCP server: @papermark/mcp-server on npm

2026-09-23: Branding tools

Nine new tools, listed under Branding (9). list_brands, get_brand, create_brand, update_brand, and delete_brand manage the team's named brands; get_dataroom_branding and update_dataroom_branding choose whether a dataroom follows the team default, pins a team brand, or uses its own custom branding. Images can be set from a public https:// source_url in any write tool on both transports, or uploaded from a local file with upload_brand_image and upload_dataroom_branding_image on stdio only. The brand tools need the new branding.read / branding.write scopes; the dataroom branding tools use datarooms.read / datarooms.write.

The seven shared tools ship on the hosted HTTP transport at mcp.papermark.com as well. Tool counts are now 66 on stdio and 65 over HTTP.

create_link accepts preset_id to seed a link from a saved preset (including the preset's social-card metadata), and both create_link and update_link gain welcome_message, enable_notification, show_banner, and custom_fields (full replace on update). Applies to both the stdio server and the hosted HTTP transport at mcp.papermark.com.

2026-04-30: upload_document follows the new upload contract

Mirrors the API change: the UploadUrlResponse shape now exposes upload_id instead of upload_key + storage_type, and the upload_document tool's file_path branch passes that opaque id to POST /v1/documents. Behavioral semantics are unchanged: same single-call upload-and-create flow.

0.1.0: first public alpha

  • 18 tools across documents (4), links (3), datarooms (5), visitors (2), analytics (4)
  • Stdio transport (run via npx @papermark/mcp-server)
  • Auth via PAPERMARK_TOKEN env (same token as the API and CLI)
  • Real API calls, no mocks or stubs

Hosted HTTP transport: mcp.papermark.com

  • Same 18-tool surface (minus upload_document, which requires filesystem access)
  • OAuth 2.1 device flow with WWW-Authenticate discovery
  • Streamable HTTP, JSON response mode, stateless
  • Production endpoint live at https://mcp.papermark.com

The HTTP variant ships as part of the main Papermark app at /api/mcp, so self-hosters get it automatically.

How to track upcoming releases

All three repos use Changesets, so the release notes for any version are committed alongside the code that ships it.

On this page