Skip to main content
All endpoints require an Authorization: Bearer sm_… header and live under https://useshareable.com/api/v1.

The page object

string
Unique page ID.
string
URL slug. The page is served at /p/{slug}.
string
Full public URL.
string | null
Display title.
string
link, people, private, password, or email_gate. See access levels.
string
Your permission on the page (owner for pages you created via the API).
string[]
Invited emails (when access is people).
object[]
The invite list as { email, role } objects (role is view). Kept in sync with allowed_emails.
string
The page password, for you to share (only on single-page responses — create, get, update, publish — when access is password; omitted from the list).
string
The page’s accent color (e.g. indigo).
string
How the page was created (e.g. mcp, upload).
boolean
Whether search engines may index the page. Default false.
string
single for a one-file page, or bundle for a multi-page deck.
string | null
For a bundle, the file served at the deck root (e.g. index.html).
number
Number of HTML files (always 1 for a single page).
boolean
Whether a published version is live.
boolean
Whether the draft differs from the published version.
string | null
ISO timestamp of last publish.
string
string
number
Total recorded views.
string | null
If set, the link stops working after this ISO 8601 datetime.
number | null
If set, the link closes after this many views.
boolean
View-only: for a PDF/image, the download button is hidden and the file is shown inline only.
boolean
Whether the owner is emailed each time the page is opened.
boolean
Whether viewers can comment on the page.
boolean
Whether commenters must confirm an email first (false = anonymous).
boolean
Pro. Collect email-verified client sign-off — designated approvers Approve / Request changes on the page. Set approver_emails too.
string[]
The designated approver emails (used with collect_approvals).
string
owner (default — decisions private to you) or shared (approvers see each other’s decisions).
boolean
Add a one-question poll to the page. Set poll_question + poll_options too.
string | null
The poll question.
string[]
The poll options (2–12).
boolean
Poll identity: true = verified email (one per person); false = anonymous (one per device).
string
Who sees results: public (default), vote (after voting), or owner (only you).
boolean
Show who voted for what (only with poll_require_email).
string | null
If set, the poll stops accepting votes after this ISO 8601 datetime.
boolean
For people access, whether invitees must sign in (vs the account-free email-confirm path).
boolean
For people access, whether blocked viewers can request access.
boolean
For email_gate access, whether personal email domains are blocked.
string[]
For email_gate access, the email domains allowed in (empty = any email).
string | null
Owner-set link-preview (unfurl) title, or null to fall back to the page’s own OG tags.
string | null
Owner-set link-preview (unfurl) description, or null to fall back to the page’s own OG tags.

Create a page

POST /api/v1/pages Pass html (or html_base64 / html_url) for a single page, files for a multi-page deck, or file_base64 for a PDF or image — one of these per request.
string
Complete, self-contained HTML document (all assets inlined). For a single page, provide this or html_base64 or html_url. Up to your plan’s per-file cap (Free 5 MB, Pro 50 MB).
string
The single page’s HTML, base64-encoded. base64 is ASCII, so it can’t be mangled in transit — use it to send HTML inline without risking emoji/Unicode (ZWJ) corruption. The server decodes it. Still inline, so the request body cap applies (~3–4 MB) — for larger HTML use html_url. The HTML must be valid UTF-8 and non-empty, or you get a 400.
string
A public https URL the server fetches the single page’s HTML from, instead of inlining it — so large HTML never passes through the model’s token stream. Same SSRF protections as file_url (private/internal/loopback/metadata hosts blocked, redirects re-checked per hop); up to your plan’s per-file cap.
string
Optional. Hex SHA-256 of the HTML bytes. The server hashes what it receives (from html, html_base64, or html_url) and returns 422 on mismatch — a byte-perfect integrity guarantee.
object[]
Array of { path, html } for a multi-page deck. Link between pages with relative (team.html), root-relative (/team.html), or folder (about/, which serves that folder’s index.html) paths. Limits: up to 60 files, your plan’s per-file cap for each HTML file and for the whole deck (HTML + assets combined), up to a 32 MB ceiling — so 5 MB on Free and 32 MB on Pro/Team. A single page can go higher (50 MB on Pro/Team); a deck is capped at 32 MB.Over the API, the whole request body must stay under about 4 MB — a larger one is rejected by the platform before it reaches us, with a plain-text Request Entity Too Large rather than our usual JSON error. That ceiling applies to files and assets together, so it, not the deck total, is the practical limit when you publish a deck in one call. Upload a bigger deck through the app, or add assets in separate calls.
object[]
For a deck: non-HTML files its pages reference with relative paths — images (PNG/JPG/WebP/GIF/SVG/ICO), CSS, JS, fonts (WOFF/WOFF2/TTF/OTF), JSON. Array of { path, data_base64 }, e.g. { "path": "images/logo.png", "data_base64": "iVBOR…" }. Up to 150 assets per deck, 5 MB each, within the deck total above (and, as with files, within your plan’s per-file cap). Base64 also adds ~33% to the request body, which the API caps well below these figures — for a deck of large assets, upload it in the dashboard instead. Assets are served behind the same access controls as the deck’s pages.
string
A PDF or image (PNG/JPG/WebP/GIF), shown inline. Base64-encoded; pass filename (and optionally mime). The file must fit your plan’s per-file cap (Free 5 MB, Pro 50 MB), and inlining base64 also adds ~33% to the request body — for larger files prefer file_url. SVG, Office docs, and spreadsheets aren’t supported — export to PDF first.
string
A public https URL to fetch a PDF or image from instead of inlining it (up to your plan’s per-file cap — Free 5 MB, Pro 50 MB). Private, internal, loopback, and cloud-metadata hosts are blocked, and redirects are re-checked per hop.
string
Original filename for a file_base64/file_url upload, e.g. report.pdf — sets the title/download and the file type. Inferred from the URL when omitted with file_url.
string
For a deck, which file is the landing page. Defaults to index.html, else the shallowest file.
string
Display title.
string
default:"link"
link, people, private, password, or email_gate.
string[]
Emails allowed to view when access is people.
string
Password to protect the page when access is password. If omitted, one is generated and returned in the response.
boolean
default:"true"
When false, saves a private draft without going live.
boolean
default:"false"
Allow search-engine indexing.
Every field below is optional — omit them all for a simple share. They can also be set later via update.
string | null
Link control — ISO 8601 datetime after which the link stops working (e.g. 2026-07-01T17:00:00Z).
number | null
Link control — close the link after this many views.
boolean
default:"false"
Link control — view-only: hide the download button on a PDF/image and force inline viewing.
boolean
default:"false"
Email you each time the page is opened.
string | null
Link-preview (unfurl) title shown when the link is pasted in iMessage/Slack/social. Wins over the page’s own OG tags; null/omitted falls back to them.
string | null
Link-preview (unfurl) description. Wins over the page’s own OG tags.
boolean
default:"false"
Show a comments widget; everyone who can see the page sees the thread.
boolean
default:"false"
Comments identity. false (default) = anonymous: anyone can comment with no account (a display name is optional). true = each commenter confirms a one-time email link first; their email stays private.
boolean
default:"false"
For people access, require invitees to sign in instead of the email-confirm path.
boolean
default:"false"
For people access, let a viewer who isn’t invited request access.
boolean
default:"false"
For email_gate access, block personal email domains (gmail, etc.).
string[]
For email_gate access, only allow these email domains, e.g. ["acme.com"].
boolean
default:"false"
Pro. Collect email-verified client sign-off — designated approvers Approve / Request changes on the page. Set approver_emails too.
string[]
The designated approver emails (used with collect_approvals), e.g. ["client@acme.com"].
string
default:"owner"
owner (decisions private to you) or shared (approvers see each other’s decisions).
boolean
default:"false"
Add a one-question poll to the page. Set poll_question + poll_options too.
string | null
The poll question.
string[]
The poll options (2–12), e.g. ["Look A","Look B"].
boolean
default:"false"
Poll identity: true = verified email (one per person); false = anonymous (one per device).
string
default:"public"
Who sees results: public, vote (after voting), or owner (only you).
boolean
default:"false"
Show who voted for what (only with poll_require_email).
string | null
ISO 8601 datetime after which the poll stops accepting votes.
A free account that enables a Pro setting (e.g. collect_approvals) gets a 402 with an explanatory message; the page isn’t created. Titles are unique per account — a duplicate returns 409.
Returns the page object with status 201.
Expiring, view-limited link
Multi-page deck
Every file — assets included — is served at /p/{slug}/{path}. /p/{slug} is still the link you share: it redirects (307) to the entry file’s own URL, /p/{slug}/{entry_path}, so that a relative reference inside the entry page resolves against the deck rather than one directory above it. Any HTTP client that follows redirects (a browser, a link unfurler, curl -L, fetch) lands on the entry page as before.

List pages

GET /api/v1/pages Returns an array of the authenticated account’s pages, most recently edited first (same order as the dashboard).
number
default:"100"
How many pages to return (1–200). Defaults to 100.
number
default:"0"
Skip this many results for paging through a large account.
The response includes a next_offset field — an integer to pass as the next offset when more pages remain, or null when you’ve reached the end.

Retrieve a page

GET /api/v1/pages/

Retrieve a page’s HTML

GET /api/v1/pages//html Returns the page’s current HTML — the editable working copy, identical to what’s live unless there are unpublished changes. Read this to patch a page surgically instead of rebuilding it from scratch. For a single page the response is { kind: "single", html, has_unpublished_changes, elided }; for a deck it’s { kind: "bundle", entry, files: [{ path, html }], has_unpublished_changes, elided }. A PDF/image artifact has no HTML and returns 400.
boolean
default:"false"
By default, long inlined data: URIs (base64 images and fonts, 1,000+ characters) are replaced in the returned HTML with a short ELIDED-BY-SHAREABLE-<n>-CHARS placeholder, and elided: { count, chars } reports what was cut. The stored page is untouched. This keeps a read cheap for an agent that is about to edit part of the page — it never needs those bytes. Pass full=true for the raw HTML. Elided HTML is rejected by every full-replace write (400), so placeholders can’t be published by mistake.

Edit a page’s HTML

PATCH /api/v1/pages//html Apply find-and-replace edits to the page’s current HTML without resending the whole document. Every byte you don’t name stays exactly as it was, so inlined images and fonts never have to round-trip through an agent. The write counterpart to GET /pages/{id}/html.
object[]
required
Ordered list of { find, replace, replace_all? } (max 200). find is plain text (no regex) and must be non-empty; replace may be "" to delete. Each find must match exactly once in the current HTML unless replace_all is true. Edits apply in sequence, each against the previous result.
string
For a deck, which file to edit. Defaults to the entry page. Not allowed on a single page.
boolean
default:"false"
Also publish the result live in the same call. Otherwise the edit is saved as a draft — call publish.
Edits are all-or-nothing: a find that matches zero times or, without replace_all, more than once returns 422 naming the offending edit, and nothing is written. Also 422: a replace_all that would hit more than 1,000 places (use a longer snippet), or edits that would leave the page empty. The result is size-gated like a full update (413 — per-page, per-file, and deck total), and a batch is capped at 200 edits with fewer allowed per call on a multi-megabyte page (the error says how many). If the page was changed by another write between the read and this edit, 409 is returned and nothing is written — re-read and apply again. A PDF/image artifact returns 400. The response is the page object under data, plus an edits summary:
changes echoes what each edit matched (before) and what replaced it (after) so you can verify the result — each side is capped at 200 characters, with before_truncated / after_truncated marking a cut. previous_version is a checkpoint of the HTML from just before the edit and version the checkpoint after it, so restore of previous_version is an exact undo (pass publish: true to the restore if the edit was published).

Update a page

PATCH /api/v1/pages/ Updating the HTML or files changes the draft only — call publish to push it live.
string
New HTML (saved as draft). Single pages only — not decks. Or send it byte-faithfully with html_base64 / html_url. Up to your plan’s per-file cap (Free 5 MB, Pro 50 MB). To change only part of a page, use PATCH /pages/{id}/html with find/replace edits instead of resending the document.
string
New HTML as base64 (ASCII-safe — avoids emoji/Unicode corruption). Decoded server-side and saved as draft.
string
A public https URL the server fetches the new HTML from (SSRF-guarded), so large HTML skips the token stream. Saved as draft.
string
Optional hex SHA-256 of the HTML bytes; 422 on mismatch.
object[]
For a deck, the full new set of { path, html } files (saved as draft). Files not included are removed; same limits as create (60 files, and your plan’s per-file cap applied both to each file and to the deck total). Optionally pass entry to set the landing page.
string
For a deck, re-point the landing page to an existing file path.
string
string
link, people, private, password, or email_gate.
string[]
string
Set/replace the password (when access is password).
boolean
string | null
Link control — expiry datetime, or null to remove it.
number | null
Link control — view cap, or null to remove it.
boolean
Link control — view-only for a PDF/image.
boolean
Email you each time the page is opened.
boolean
When access is people, let a viewer who isn’t invited request access — you approve or deny by email or in the app. See access levels.
boolean
Show a comments widget on the page; everyone sees the thread. Anonymous by default — pair with comments_require_email: true to require a verified email. You moderate (hide/delete) from the Share dialog.
boolean
Comments identity. false (default) = anonymous (no account needed; display name optional). true = commenters confirm a one-time email link first; their email stays private.
boolean
For people access, require invitees to sign in.
boolean
For email_gate access, block personal email domains.
string[]
For email_gate access, the allowed email domains, e.g. ["acme.com"].
string | null
Link-preview (unfurl) title. Wins over the page’s own OG tags; null clears it.
string | null
Link-preview (unfurl) description. Wins over the page’s own OG tags; null clears it.
boolean
Email you each time the page is opened.
boolean
Pro. Collect email-verified client sign-off. Set approver_emails too.
string[]
The designated approver emails (used with collect_approvals).
string
owner or shared.
boolean
Add a one-question poll. Set poll_question + poll_options too.
string | null
The poll question.
string[]
The poll options (2–12).
boolean
Poll identity: verified email vs anonymous.
string
Who sees results: public, vote, or owner.
boolean
Show who voted for what (only with poll_require_email).
string | null
ISO 8601 datetime after which the poll closes, or null to remove.
Same error responses as create: enabling a Pro setting on a free account returns 402, and a duplicate title returns 409.
Add an expiration + view-only

Delete a page

DELETE /api/v1/pages/ Permanently deletes the page. Returns status 204.

Versions

A version is saved automatically on each publish and each edit (deduplicated by content). Named versions are kept forever; older unnamed ones are pruned.

List versions

GET /api/v1/pages//versions Returns { version_no, source, label, size_bytes, created_at }[], newest first. source is publish, edit, or restore.

Get a version

GET /api/v1/pages//versions/ Returns the version’s metadata plus its full content — html for a single page, or files + entry for a deck. (The MCP get_version tool previews long content by default; pass full: true there for the whole thing. To read the current page’s HTML rather than a past version, use GET /pages/{id}/html.)

Restore a version

POST /api/v1/pages//versions//restore
boolean
default:"false"
When true, also publish the restored content live. Otherwise it’s restored to the draft only.
Restoring appends a new restore version. Returns the updated page object.

Name a version

PATCH /api/v1/pages//versions/
string | null
A name for the version (named versions are never pruned). null clears it.