February 28, 2026

The Developer's Guide to Building Secure Document Sharing into Your App

If your application handles sensitive documents — investor updates, legal contracts, training materials, sales proposals — you need more than a file upload and a public URL. You need watermarks, view tracking, access controls, and expiry. Cloak's API lets you add all of this with a few REST calls or our Node.js SDK. This guide covers the core integration patterns.

Creating a secure link

The fundamental operation in Cloak is creating a link. Upload a file (PDF, DOCX, MP4, or any supported format), set your security rules, and get back a tokenized URL. The recipient views the content in Cloak's browser-based viewer — no downloads.

// Node.js SDK
import Cloak from '@cloakshare/sdk';

const cloak = new Cloak('ck_live_xxx');

const link = await cloak.links.create({
  file: './quarterly-report.pdf',
  watermark: true,
  email_required: true,
  expires_in: '7d',
  password: 'deal-room-2026',
  allow_download: false,
});

console.log(link.secure_url);
// https://view.cloakshare.dev/s/lnk_mN7pR3

The same endpoint handles video files. Upload an MP4 and Cloak transcodes it to HLS automatically. The returned link streams the video with the same watermark and analytics features.

// Video upload — same API, different file
const videoLink = await cloak.links.create({
  file: './product-demo.mp4',
  watermark: true,
  email_required: true,
  expires_in: '30d',
});

console.log(videoLink.type);
// "video"

Setting security rules

Every link supports a combination of security controls. Mix and match based on your use case.

  • + watermark: true — overlay the viewer's email on every page or video frame
  • + email_required: true — gate access behind email verification
  • + password: "secret" — require a password before viewing
  • + expires_in: "72h" — auto-expire after a duration
  • + max_views: 10 — limit total number of views
  • + allow_download: false — disable the download button
  • + domain_whitelist: ["acme.com"] — restrict to specific email domains

These can be set at creation time or updated later via PATCH /v1/links/:id.

Tracking analytics via webhooks

Polling the analytics API works, but webhooks give you real-time data. Register a webhook endpoint and Cloak will POST events as they happen — link viewed, page turned, video watched, download attempted.

// Register a webhook
await cloak.webhooks.create({
  url: 'https://your-app.com/api/cloak-events',
  events: ['link.viewed', 'link.completed', 'video.watched'],
  secret: 'whsec_your_signing_secret',
});

// Your webhook handler
app.post('/api/cloak-events', (req, res) => {
  const event = req.body;

  if (event.type === 'link.viewed') {
    console.log(`${event.data.viewer_email} viewed ${event.data.link_id}`);
    console.log(`Time on page: ${event.data.duration_seconds}s`);
  }

  if (event.type === 'video.watched') {
    console.log(`Watch time: ${event.data.watch_time_seconds}s`);
    console.log(`Completion: ${(event.data.completion_rate * 100).toFixed(0)}%`);
  }

  res.sendStatus(200);
});

Webhook payloads are signed with your secret using HMAC-SHA256. Verify the signature in your handler to ensure the request came from Cloak.

Querying analytics directly

For batch reporting or dashboard integrations, pull analytics via the REST API. Get per-link summaries or per-viewer breakdowns.

// Get analytics for a specific link
const analytics = await cloak.links.analytics('lnk_mN7pR3');

console.log(analytics.total_views);       // 47
console.log(analytics.unique_viewers);     // 12
console.log(analytics.avg_completion);     // 0.82
console.log(analytics.avg_time_seconds);   // 234

// Per-viewer breakdown
for (const viewer of analytics.viewers) {
  console.log(`${viewer.email}: ${viewer.pages_viewed}/${analytics.total_pages} pages`);
}

Using the Node.js SDK

The examples above use the official @cloakshare/sdk package. Install it from npm and initialize with your API key.

$ npm install @cloakshare/sdk

The SDK wraps all REST endpoints with TypeScript types, handles multipart file uploads, verifies webhook signatures, and retries on transient failures. If you prefer raw HTTP, every SDK method maps 1:1 to a REST endpoint documented at GitHub Docs.

Get started

Sign up at app.cloakshare.dev and get a free API key in seconds. The free tier gives you 50 links and 500 views per month — enough to build and test your integration. Scale to the Pro or Enterprise plan when you're ready.

Cloak is open source. Explore the code, file issues, or contribute at github.com/cloakshare/cloakshare. Self-host for unlimited usage with no per-user fees.