Core Resources
View as Markdown

Share Link

A tokenized URL for sharing a Droplet — internal (SSO) or external (public domain), optionally gated by password, email verification, or an allow-list.

A Share Link is the external-sharing primitive for Droplets. Internal links live on the CloudFront domain and require Hi Marley SSO; external links live on the public fromhimarley.com domain and can be additionally gated by magic-link email verification, a password, or an allow-list of exact emails / apex domains / wildcard subdomains. Default external expiry is 30 days; default magic-link verification is on for external links.

The Share Link object

Every Share Link carries these attributes.

Attributes

name
string
Owner-facing label for the link (e.g. "For design review", "Board presentation"). Shown in the owner's share-links panel and in audit events; never shown to recipients.
token
string
The opaque token in the share URL (?token={token}). Globally unique. Lambda@Edge looks it up in DynamoDB to enforce access rules before the asset is served.
isExternal
boolean
false (default) — internal link on the CloudFront domain, requires Hi Marley SSO. true — external link on fromhimarley.com, accessible to anyone (subject to the gates below).
requireVerifiedEmail
boolean
Magic-link verification before viewing. Recipient enters their email, we email them a one-time link + OTP, we record the verified email on every view. Defaults to `true` for external links.
allowedEmails
string[]
Optional allow-list. Each entry is one of: an exact email (alice@acme.com), an apex domain (@acme.com), or a wildcard subdomain (*.acme.com). Patterns with fewer than 2 labels after the wildcard (e.g. *.com) are rejected server-side. Empty array = no restriction.
expiresAt
timestamp· nullable
When the link stops working. External links default to 30 days from creation; pass null (subject to your role) to remove expiry. After expiry, the edge returns 410.
enabled
boolean
Set false to immediately disable the link. The edge cache is re-synced and CloudFront is invalidated on disable. The link is preserved (re-enabling restores access).
appId
string
The id of the Droplet this link grants access to. Set at creation and immutable thereafter.
More attributes+ Show 7
id
string
CUID primary key. Used as {linkId} in PATCH / DELETE paths.
passwordHash
string· nullable
Argon2 hash of the link password, if one was set. Never returned in API responses — the API exposes hasPassword: boolean instead.
edgePasswordHash
string· nullable
Companion edge-friendly hash (HMAC-SHA256) used by Lambda@Edge for the same password check. Kept in sync with passwordHash on every write.
requireEmail
boolean
(Legacy) Unverified email capture before viewing — the recipient typed an email, we trusted them. Superseded by requireVerifiedEmail (magic-link). Preserved for old links; new external links default to requireVerifiedEmail: true.
createdById
string· nullable
The User who created the link. Non-owner editors can only modify links they themselves created.
createdAt
timestamp
ISO 8601 timestamp of creation.
updatedAt
timestamp
ISO 8601 timestamp of last modification.
THE SHARE LINK OBJECT
{
  "id": "clx6pqr...",
  "appId": "clx1abc...",
  "token": "abc123def456",
  "name": "For Acme partner review",
  "isExternal": true,
  "requireEmail": false,
  "requireVerifiedEmail": true,
  "allowedEmails": [
    "alice@acme.com",
    "@acme-legal.com",
    "*.partner.com"
  ],
  "expiresAt": "2026-07-14T12:00:00.000Z",
  "enabled": true,
  "createdById": "usr_alex",
  "createdAt": "2026-06-14T12:00:00.000Z",
  "updatedAt": "2026-06-14T12:00:00.000Z"
}

Methods

Endpoints to operate on a Share Link. The example switches between curl, drop CLI, and MCP via the dropdown — your choice persists across the page.

GET

List share links

/api/apps/{slug}/shares

Return every share link for a Droplet, with view counts and the rendered URL. Owners and editors only.

Parameters

slug
string· path· required
The Droplet slug.
GET/api/apps/{slug}/shares
drop shares list q2-retro-board
Response200
[
  {
    "id": "clx6pqr",
    "token": "abc123def456",
    "name": "For design review",
    "hasPassword": false,
    "requireEmail": false,
    "requireVerifiedEmail": true,
    "expiresAt": "2026-07-14T12:00:00.000Z",
    "enabled": true,
    "createdAt": "2026-06-14T12:00:00.000Z",
    "viewCount": 5,
    "isExternal": true,
    "allowedEmails": [],
    "url": "https://fromhimarley.com/q2-retro-board?token=abc123def456"
  }
]
POST

Create a share link

/api/apps/{slug}/shares

Create a new share link. External links default to a 30-day expiry and use the public fromhimarley.com domain. Internal links use the CloudFront domain and require Hi Marley SSO. Optional gates: password, requireVerifiedEmail (magic-link), allowedEmails (exact / apex-domain / wildcard subdomain).

Parameters

slug
string· path· required
The Droplet slug.
name
string· body· required
Display name for the link.
isExternal
boolean· body
External (public domain) vs internal (SSO). Default false.
password
string· body
Optional password to protect the link.
requireEmail
boolean· body
(Legacy) unverified email capture.
requireVerifiedEmail
boolean· body
Magic-link verification. Default true for external.
allowedEmails
string[]· body
Allow-list: exact email / @domain / *.subdomain.
expiresAt
string· body
ISO timestamp expiry.
POST/api/apps/{slug}/shares
drop shares create q2-retro-board --name "For Acme partner review" --is-external --require-verified-email --allowed-emails alice@acme.com,@acme-legal.com,*.partner.com
Response200
{
  "id": "clx6pqr",
  "token": "abc123def456",
  "name": "For Acme partner review",
  "hasPassword": false,
  "requireEmail": false,
  "requireVerifiedEmail": true,
  "expiresAt": "2026-07-14T12:00:00.000Z",
  "enabled": true,
  "createdAt": "2026-06-14T12:00:00.000Z",
  "viewCount": 0,
  "isExternal": true,
  "allowedEmails": [
    "alice@acme.com",
    "@acme-legal.com",
    "*.partner.com"
  ],
  "url": "https://fromhimarley.com/q2-retro-board?token=abc123def456"
}
PATCH

Update a share link

/api/apps/{slug}/shares/{linkId}

Partial update — only supply fields you want to change. Common cases: toggle enabled to disable / re-enable, extend expiresAt, replace allowedEmails, rotate the password. Allow-list edits emit a SHARE_LINK_ALLOWLIST_UPDATED audit event with the sorted before/after diff. Allow-list validation is all-or-nothing — one bad entry rejects the whole list.

Parameters

slug
string· path· required
The Droplet slug.
linkId
string· path· required
The share link id.
name
string· body
New name.
enabled
boolean· body
Toggle enabled (disable invalidates the edge cache).
password
string | null· body
New password, or null to clear.
requireEmail
boolean· body
Require unverified email capture.
requireVerifiedEmail
boolean· body
Require magic-link verification.
allowedEmails
string[]· body
Replace the allow-list.
expiresAt
string | null· body
ISO timestamp, or null to clear.
PATCH/api/apps/{slug}/shares/{linkId}
drop shares update q2-retro-board clx6pqr --allowed-emails alice@acme.com,bob@acme.com,@partner.com
Response200
{
  "id": "clx6pqr",
  "token": "abc123def456",
  "name": "For Acme partner review",
  "hasPassword": false,
  "requireEmail": false,
  "requireVerifiedEmail": true,
  "expiresAt": "2026-07-14T12:00:00.000Z",
  "enabled": true,
  "createdAt": "2026-06-14T12:00:00.000Z",
  "isExternal": true,
  "allowedEmails": [
    "alice@acme.com",
    "bob@acme.com",
    "@partner.com"
  ]
}
DELETE

Delete a share link

/api/apps/{slug}/shares/{linkId}

Delete the link and remove it from the edge access cache. The link stops working immediately. There is no soft-delete — use enabled: false via Update for recoverable disable.

Parameters

slug
string· path· required
The Droplet slug.
linkId
string· path· required
The share link id.
DELETE/api/apps/{slug}/shares/{linkId}
drop shares delete q2-retro-board clx6pqr
Response200
{
  "success": true
}
GET

List views

/api/apps/{slug}/shares/{linkId}/views

Return the view log for a share link — one row per view with email (if captured / verified), IP address, and timestamp. Useful for after-the-fact "who actually opened this" auditing on external shares. Up to 100 most recent rows.

Parameters

slug
string· path· required
The Droplet slug.
linkId
string· path· required
The share link id.
GET/api/apps/{slug}/shares/{linkId}/views
drop shares views q2-retro-board clx6pqr
Response200
[
  {
    "id": "clxview1",
    "email": "alice@acme.com",
    "verified": true,
    "ipAddress": "203.0.113.***",
    "viewedAt": "2026-06-15T14:22:00.000Z"
  },
  {
    "id": "clxview2",
    "email": "bob@acme.com",
    "verified": true,
    "ipAddress": "203.0.113.***",
    "viewedAt": "2026-06-15T15:08:00.000Z"
  }
]