PapermarkDocs

Brand a data room

Put your logo and colors on every data room with a team brand, then give one room its own look.

Every data room you share has a look: a logo, a banner, brand colors, a welcome message on the access screen, a viewer layout, and the preview card the link unfurls into. You set that look once as a team brand and every data room and link picks it up. When one deal deserves its own banner and welcome text, you give that room custom branding without touching the rest.

How branding resolves

Two objects, one rule.

A team brand is a named, reusable set of viewer settings (GET /v1/brands). A team can have several, for example one per fund or one per portfolio company, and exactly one of them is the default (is_default: true). The first brand you create becomes the default; after that you move the default by setting is_default: true on another brand. Every data room and link that does not say otherwise shows the default brand.

A data room's branding is one of three modes. Visitors see exactly one source. There is no field-by-field mix between a brand and a room.

modeVisitors seeThe room's own custom settings are
team_defaultThe team's default brand, whichever brand that is right nowDiscarded (deleted from the room)
team_brandThe one brand pinned in brand_idKept, dormant, restored if you switch back to custom
customThe room's own settings, including its own imagesIn use

Three consequences worth knowing before you start:

  • The first switch to custom starts from the brand visitors currently see (the pinned brand, else the team default), then applies the fields you send. You never start from a blank room.
  • Pinning a room to a team brand keeps its custom settings on disk. Switching back to custom later restores them as they were, with no reseed.
  • team_default is the destructive one. It deletes the room's custom settings and releases their images.

New data rooms start in team_brand mode, pinned to whichever brand is the default when the room is created. Changing the default later does not move existing rooms. To make a room follow the default as it changes, set it to team_default. So the common path is: create your brand and make it the default first, then create rooms, and only reach for per-room modes on the rooms that need them.

The script

Create a brand with a logo and make it the default, pin it on one room, give a second room custom branding with its own banner, hide that banner, and reset the room to the team default.

# 1. Create the brand. Image flags take a local file (uploaded right
#    after the brand is created) or an https URL. --default makes it
#    the team default.
BRAND_ID=$(papermark brands create \
  --name "Acme" \
  --brand-color '#0f172a' \
  --logo ./acme-logo.png \
  --default \
  --json | jq -r '.data.id')

# Same logo from a hosted image instead of a local file
papermark brands update "$BRAND_ID" --logo https://acme.com/brand/logo.png

# Make an existing brand the default later
papermark brands update "$BRAND_ID" --default

# 2. Pin the brand on a room. New rooms already follow the default;
#    pin when a room must keep this brand even if the default moves.
papermark datarooms branding set dr_K8mN2pQr --mode team_brand --brand "$BRAND_ID"

# 3. Give one room its own branding. Field and image flags are only
#    accepted with --mode custom.
papermark datarooms branding set dr_aBc456 --mode custom \
  --welcome-message "Welcome to the Acme Series B data room" \
  --banner ./series-b-banner.png

# 4. Hide that room's banner
papermark datarooms branding set dr_aBc456 --mode custom --banner hidden

# 5. Back to the team default. This drops the room's custom branding.
papermark datarooms branding set dr_aBc456 --mode team_default

Check what a room shows at any point:

papermark datarooms branding get dr_aBc456

The full flag list, with plan notes per field, is on papermark brands.

TOKEN=pm_live_…

# 1. Create the brand. The logo comes from a public https URL and the
#    brand becomes the team default.
BRAND_ID=$(curl -sX POST https://api.papermark.com/v1/brands \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme",
    "brand_color": "#0f172a",
    "logo": { "source_url": "https://acme.com/brand/logo.png" },
    "is_default": true
  }' | jq -r '.id')

# Upload a logo from a local file instead: raw bytes in the body,
# Content-Type set to the file's real type.
curl -X PUT "https://api.papermark.com/v1/brands/$BRAND_ID/images/logo" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: image/png" \
  --data-binary @./acme-logo.png

# Make an existing brand the default later
curl -X PATCH "https://api.papermark.com/v1/brands/$BRAND_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "is_default": true }'

# 2. Pin the brand on a room
curl -X PATCH https://api.papermark.com/v1/datarooms/dr_K8mN2pQr/branding \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{ \"mode\": \"team_brand\", \"brand_id\": \"$BRAND_ID\" }"

# 3. Give one room its own branding. The first switch to custom
#    starts from the brand visitors currently see, then applies
#    the fields you send.
curl -X PATCH https://api.papermark.com/v1/datarooms/dr_aBc456/branding \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "custom",
    "welcome_message": "Welcome to the Acme Series B data room"
  }'

# Then upload the room's own banner. The room must already be in
# custom mode, or this returns 409.
curl -X PUT https://api.papermark.com/v1/datarooms/dr_aBc456/branding/images/banner \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: image/png" \
  --data-binary @./series-b-banner.png

# 4. Hide that room's banner
curl -X PATCH https://api.papermark.com/v1/datarooms/dr_aBc456/branding \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "mode": "custom", "banner": { "hidden": true } }'

# 5. Back to the team default. This deletes the room's custom branding.
curl -X PATCH https://api.papermark.com/v1/datarooms/dr_aBc456/branding \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "mode": "team_default" }'

GET /v1/datarooms/{id}/branding tells you what a room shows. custom is the room's stored settings (null if it never had any), effective is what visitors see right now:

{
  "object": "dataroom_branding",
  "dataroom_id": "clxy9abc1234567890",
  "dataroom_pid": "dr_aBc456",
  "mode": "team_brand",
  "brand_id": "clxbrand1234567890",
  "custom": { "welcome_message": "Welcome to the Acme Series B data room", "banner_hidden": true, "...": "..." },
  "effective": { "logo_url": "https://…/branding/team_…/logo-abc123.png", "brand_color": "#0f172a", "...": "..." }
}

Required scopes: branding.write for the brand calls, datarooms.write for the room calls. See the Branding reference for every field.

Create a Papermark brand called "Acme" with brand color #0f172a and the logo at https://acme.com/brand/logo.png, and make it the team default. Pin it on the "Acme Series B" data room. Then give the "Acme Seed" data room its own branding: welcome message "Welcome to the Acme Seed data room" and the banner at https://acme.com/brand/seed-banner.png.

The agent chains list_brands (names are unique per team) → create_brand with is_default: true and logo: { source_url }search_dataroomsupdate_dataroom_branding with mode: "team_brand"update_dataroom_branding with mode: "custom" and banner: { source_url }.

Follow-ups map to the same tool:

  • "Hide the banner on Acme Seed" → update_dataroom_branding with mode: "custom" and banner: { "hidden": true }.
  • "Put Acme Seed back on the team default" → update_dataroom_branding with mode: "team_default". The agent checks get_dataroom_branding first and confirms with you when custom is set, because that saved branding is deleted.

Local image files are a stdio-only path (Claude Desktop, Claude Code). "Use ~/brand/logo.png as the Acme logo" → upload_brand_image with the file_path; "use ~/brand/seed-banner.png on Acme Seed" → upload_dataroom_branding_image, which needs the room in custom mode first. Over HTTP (claude.ai, ChatGPT) the server cannot read your disk, so host the image and pass its source_url.

Image rules

Four image slots, each with its own cap. The same limits apply to a team brand and to a room's custom branding.

SlotAcceptedMax sizeNotes
logoPNG, JPEG2 MBnull removes it and the Papermark logo shows; hide_logo: true shows no logo at all
bannerPNG, JPEG4 MB{ "hidden": true } hides the banner; null restores the Papermark default banner
link_preview_imagePNG, JPEG4 MB1200x630 recommended; Business or Data Rooms plan
link_preview_faviconPNG, ICO1 MBBusiness or Data Rooms plan

No SVG and no WebP, in any slot. That matches the dashboard uploader and avoids sanitizing SVG. The 4 MB cap on banners and preview images is lower than the dashboard's 5 MB because API request bodies stop at 4.5 MB.

Two ways to set an image:

  • source_url in the JSON body of POST /v1/brands, PATCH /v1/brands/{id}, or PATCH /v1/datarooms/{id}/branding (custom mode). It must be a public https:// URL. Papermark downloads the file and detects the type from its bytes, not from the remote server's Content-Type.
  • Raw upload with PUT /v1/brands/{id}/images/{slot} or PUT /v1/datarooms/{id}/branding/images/{slot}. The body is the file bytes and Content-Type must be the file's real type (image/png, image/jpeg, image/x-icon). A declared type that does not match the bytes is rejected with 422.

PUT /v1/datarooms/{id}/branding/images/{slot} only works while the room is in custom mode. In any other mode it returns 409 conflict with the message Dataroom branding is in team_default mode. Set mode to custom first with PATCH /v1/datarooms/{id}/branding. (the mode name reflects the room's actual mode). Switch the mode first, then upload.

Plan gating

Colors, logo, banner, and hide_logo work on every plan that can create a brand. Other fields need a plan:

FieldsPlan
welcome_message, cta_label, cta_url, custom_link_preview_enabled, link_preview_title, link_preview_description, link_preview_image, link_preview_faviconBusiness or Data Rooms
card_layout, show_folder_tree, viewer_layout_preset, viewer_header_style, hide_folder_icons_in_mainData Rooms
default_language other than enData Rooms Plus

A gated write returns 403 plan_restriction. details.fields lists every field the plan blocked, so you can drop them and retry:

{
  "error": {
    "code": "plan_restriction",
    "message": "Welcome message and call to action; Dataroom layout are not available on the pro plan.",
    "doc_url": "https://www.papermark.com/docs/api/errors#plan_restriction",
    "details": {
      "feature": "custom_messaging",
      "fields": ["welcome_message", "card_layout"],
      "current_plan": "pro"
    }
  }
}

Resetting a field to its default value is never gated, so a downgraded team can always clean up. The number of brands per team is also capped by plan; creating one past the cap returns 403 plan_restriction with details.feature: "brands", the current usage, the limit, and the plans that lift it.

Errors

StatusWhen
403 plan_restrictionA field or image slot the plan does not include (details.fields), or the brand cap.
403 forbiddenThe data room is frozen; branding cannot change. Also a token missing branding.write or datarooms.write.
404 not_foundUnknown brand id, unknown image slot, or a brand_id that belongs to another team.
409 conflictA brand name already used in the team, or an image upload to a room not in custom mode.
422 unprocessable_entityBad hex color, a non-https source_url or cta_url, an oversized file, a Content-Type that does not match the bytes, or fields sent with the wrong mode (for example brand_id with custom).

Deleting a brand

DELETE /v1/brands/{id} removes the brand and its images. Rooms and links pinned to it fall back to the team default. Deleting the default brand promotes the oldest remaining brand to default. A room in custom mode is unaffected, because it does not reference the brand.

Required scopes

OperationScope
List and get brandsbranding.read
Create, update, delete brands; upload brand imagesbranding.write
Read a data room's brandingdatarooms.read
Set a data room's mode; upload its custom imagesdatarooms.write

apis.read covers branding.read. papermark login requests branding.read and branding.write by default, so existing CLI sessions need a fresh papermark login to pick them up.

On this page