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.
mode | Visitors see | The room's own custom settings are |
|---|---|---|
team_default | The team's default brand, whichever brand that is right now | Discarded (deleted from the room) |
team_brand | The one brand pinned in brand_id | Kept, dormant, restored if you switch back to custom |
custom | The room's own settings, including its own images | In use |
Three consequences worth knowing before you start:
- The first switch to
customstarts 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
customlater restores them as they were, with no reseed. team_defaultis 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_defaultCheck what a room shows at any point:
papermark datarooms branding get dr_aBc456The 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_datarooms → update_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_brandingwithmode: "custom"andbanner: { "hidden": true }. - "Put Acme Seed back on the team default" →
update_dataroom_brandingwithmode: "team_default". The agent checksget_dataroom_brandingfirst and confirms with you whencustomis 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.
| Slot | Accepted | Max size | Notes |
|---|---|---|---|
logo | PNG, JPEG | 2 MB | null removes it and the Papermark logo shows; hide_logo: true shows no logo at all |
banner | PNG, JPEG | 4 MB | { "hidden": true } hides the banner; null restores the Papermark default banner |
link_preview_image | PNG, JPEG | 4 MB | 1200x630 recommended; Business or Data Rooms plan |
link_preview_favicon | PNG, ICO | 1 MB | Business 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_urlin the JSON body ofPOST /v1/brands,PATCH /v1/brands/{id}, orPATCH /v1/datarooms/{id}/branding(custom mode). It must be a publichttps://URL. Papermark downloads the file and detects the type from its bytes, not from the remote server'sContent-Type.- Raw upload with
PUT /v1/brands/{id}/images/{slot}orPUT /v1/datarooms/{id}/branding/images/{slot}. The body is the file bytes andContent-Typemust be the file's real type (image/png,image/jpeg,image/x-icon). A declared type that does not match the bytes is rejected with422.
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:
| Fields | Plan |
|---|---|
welcome_message, cta_label, cta_url, custom_link_preview_enabled, link_preview_title, link_preview_description, link_preview_image, link_preview_favicon | Business or Data Rooms |
card_layout, show_folder_tree, viewer_layout_preset, viewer_header_style, hide_folder_icons_in_main | Data Rooms |
default_language other than en | Data 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
| Status | When |
|---|---|
403 plan_restriction | A field or image slot the plan does not include (details.fields), or the brand cap. |
403 forbidden | The data room is frozen; branding cannot change. Also a token missing branding.write or datarooms.write. |
404 not_found | Unknown brand id, unknown image slot, or a brand_id that belongs to another team. |
409 conflict | A brand name already used in the team, or an image upload to a room not in custom mode. |
422 unprocessable_entity | Bad 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
| Operation | Scope |
|---|---|
| List and get brands | branding.read |
| Create, update, delete brands; upload brand images | branding.write |
| Read a data room's branding | datarooms.read |
| Set a data room's mode; upload its custom images | datarooms.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.