Share Links
Share Links API
Create shareable links for your videos with advanced access controls. HesedVid’s sharing system provides both web app links and direct video URLs, perfect for controlled content distribution, client previews, and secure video sharing.
Overview
The Share Links API allows you to:
- Generate Shareable Links: Create both web app and direct video URLs
- Control Access: Set expiration times, view limits, and email restrictions
- Track Usage: Monitor who accessed your shared content
- Secure Distribution: Protect sensitive content with time-limited access
Generate Share Link
/{orgID}/videos/{publicID}/share
Generate shareable links for a video with optional access controls.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
orgID | string | Yes | Your organization’s unique identifier |
publicID | string | Yes | The public ID of the video asset |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
expirationHours | int | No | Link expires after this many hours (1-168) |
maxViews | int | No | Maximum number of views allowed (1-1000) |
viewerEmail | string | No | Restrict access to specific email address |
Response
{ "body": { "webAppUrl": "https://app.hesedvid.com/share/pubvid_AbCdEf?token=abc123", "webAppUrlType": "private", "directUrl": "https://worker.hesedvid.com/pubvid_AbCdEf/master.m3u8?token=abc123", "directUrlType": "private", "expiresAt": "2024-01-16T10:30:00Z", "publicId": "pubvid_AbCdEf", "videoName": "My Video", "token": "abc123" }}Response Fields
| Field | Type | Description |
|---|---|---|
webAppUrl | string | Full-featured web app share link with player |
webAppUrlType | string | Access type: “public” or “private” |
directUrl | string | Direct video stream URL for embedding |
directUrlType | string | Access type: “public” or “private” |
expiresAt | string | ISO 8601 timestamp when link expires |
publicId | string | Video’s public identifier |
videoName | string | Display name of the video |
token | string | Access token for private links |
Example Request
# Basic share link (no restrictions)curl -X POST "https://api.hesedvid.com/v1/api/org_123456789/videos/pubvid_AbCdEf/share" \ -H "X-Api-Key: hv_live_123456789abcdefghijklmnopqrstuvwxyz" \ -H "Content-Type: application/json" \ -d '{}'
# Share link with expiration and view limitcurl -X POST "https://api.hesedvid.com/v1/api/org_123456789/videos/pubvid_AbCdEf/share" \ -H "X-Api-Key: hv_live_123456789abcdefghijklmnopqrstuvwxyz" \ -H "Content-Type: application/json" \ -d '{ "expirationHours": 24, "maxViews": 10, "viewerEmail": "[email protected]" }'// Basic share linkconst generateBasicShareLink = async () => { const response = await fetch('https://api.hesedvid.com/v1/api/org_123456789/videos/pubvid_AbCdEf/share', { method: 'POST', headers: { 'X-Api-Key': 'hv_live_123456789abcdefghijklmnopqrstuvwxyz', 'Content-Type': 'application/json' }, body: JSON.stringify({}) }); return response.json();};
// Share link with restrictionsconst generateRestrictedShareLink = async () => { const response = await fetch('https://api.hesedvid.com/v1/api/org_123456789/videos/pubvid_AbCdEf/share', { method: 'POST', headers: { 'X-Api-Key': 'hv_live_123456789abcdefghijklmnopqrstuvwxyz', 'Content-Type': 'application/json' }, body: JSON.stringify({ expirationHours: 24, maxViews: 10, }) }); return response.json();};import requestsfrom datetime import datetime, timedelta
def generate_share_link(expiration_hours=None, max_views=None, viewer_email=None): url = "https://api.hesedvid.com/v1/api/org_123456789/videos/pubvid_AbCdEf/share" headers = { "X-Api-Key": "hv_live_123456789abcdefghijklmnopqrstuvwxyz", "Content-Type": "application/json" } data = {}
if expiration_hours: data["expirationHours"] = expiration_hours if max_views: data["maxViews"] = max_views if viewer_email: data["viewerEmail"] = viewer_email
response = requests.post(url, headers=headers, json=data) return response.json()
# Generate basic share linkbasic_link = generate_share_link()
# Generate restricted share linkrestricted_link = generate_share_link( expiration_hours=24, max_views=10,)Link Types Explained
Web App Links
Web app links provide a full-featured viewing experience:
- Player Interface: Complete video player with controls
- Responsive Design: Optimized for all devices
- Analytics: View tracking and engagement metrics
- Branding: Customizable player appearance
Example Web App Link:
https://app.hesedvid.com/share/pubvid_AbCdEf?token=abc123Direct Video Links
Direct links provide raw video streams for embedding:
- HLS Stream: Direct access to video segments
- Embedding: Perfect for iframe embedding
- Player Integration: Works with any HLS-compatible player
- CDN Delivery: Fast global content delivery
Example Direct Link:
https://worker.hesedvid.com/pubvid_AbCdEf/master.m3u8?token=abc123Access Control Options
Expiration Control
Set automatic link expiration:
// Link expires in 24 hoursconst shareLink = await generateShareLink({ expirationHours: 24});
// Link expires in 7 daysconst weeklyLink = await generateShareLink({ expirationHours: 168 // 7 days * 24 hours});View Limits
Control how many times the link can be accessed:
// Allow only 5 viewsconst limitedLink = await generateShareLink({ maxViews: 5});
// Single-use linkconst singleUseLink = await generateShareLink({ maxViews: 1});Email Restrictions
Restrict access to specific email addresses:
// Client-specific accessconst clientLink = await generateShareLink({});
// Team member accessconst teamLink = await generateShareLink({});Combined Restrictions
Use multiple restrictions together:
// Highly restricted linkconst secureLink = await generateShareLink({ expirationHours: 48, // Expires in 2 days maxViews: 3, // Maximum 3 views});Common Use Cases
Client Video Reviews
// Generate review link for client feedbackconst generateClientReviewLink = async (videoId, clientEmail) => { const response = await generateShareLink({ expirationHours: 72, // 3 days to review maxViews: 5, // Allow multiple views viewerEmail: clientEmail // Restrict to client });
return { webAppUrl: response.webAppUrl, expiresAt: response.expiresAt, instructions: "Please review the video and provide feedback within 3 days" };};Team Collaboration
// Generate team sharing linkconst generateTeamLink = async (videoId, teamMemberEmail) => { const response = await generateShareLink({ expirationHours: 168, // 1 week access maxViews: 20, // Allow team to view multiple times viewerEmail: teamMemberEmail });
return response.webAppUrl;};Public Demos
// Generate public demo link (no restrictions)const generatePublicDemo = async (videoId) => { const response = await generateShareLink({});
return { webAppUrl: response.webAppUrl, directUrl: response.directUrl, isPublic: response.webAppUrlType === 'public' };};Embedding in Websites
// Generate embeddable linkconst generateEmbedLink = async (videoId) => { const response = await generateShareLink({ expirationHours: 720, // 30 days maxViews: 100 // Allow many views });
return { embedUrl: response.directUrl, iframeCode: `<iframe src="${response.directUrl}" width="640" height="360" frameborder="0"></iframe>` };};Integration Examples
React Component
import React, { useState } from 'react';
const VideoShareComponent = ({ videoId }) => { const [shareLink, setShareLink] = useState(null); const [loading, setLoading] = useState(false);
const generateShareLink = async (options = {}) => { setLoading(true); try { const response = await fetch(`/api/videos/${videoId}/share`, { method: 'POST', headers: { 'X-Api-Key': process.env.REACT_APP_HESEDVID_API_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify(options) });
const data = await response.json(); setShareLink(data); } catch (error) { console.error('Failed to generate share link:', error); } finally { setLoading(false); } };
return ( <div className="share-component"> <h3>Share Video</h3>
<div className="share-options"> <button onClick={() => generateShareLink()}> Generate Public Link </button>
<button onClick={() => generateShareLink({ expirationHours: 24 })}> Generate 24h Link </button>
<button onClick={() => generateShareLink({ maxViews: 5 })}> Generate Limited Link </button> </div>
{loading && <p>Generating share link...</p>}
{shareLink && ( <div className="share-result"> <h4>Share Link Generated</h4> <p><strong>Web App:</strong> <a href={shareLink.webAppUrl} target="_blank">{shareLink.webAppUrl}</a></p> <p><strong>Direct URL:</strong> <code>{shareLink.directUrl}</code></p> {shareLink.expiresAt && ( <p><strong>Expires:</strong> {new Date(shareLink.expiresAt).toLocaleString()}</p> )} </div> )} </div> );};WordPress Integration
<?php// WordPress plugin for HesedVid sharingclass HesedVidShare { private $api_key; private $base_url = 'https://api.hesedvid.com/v1/api';
public function __construct($api_key) { $this->api_key = $api_key; }
public function generate_share_link($org_id, $video_id, $options = []) { $url = "{$this->base_url}/{$org_id}/videos/{$video_id}/share";
$headers = [ 'X-Api-Key: ' . $this->api_key, 'Content-Type: application/json' ];
$data = json_encode($options);
$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch); curl_close($ch);
return json_decode($response, true); }
public function create_shortcode($atts) { $atts = shortcode_atts([ 'video_id' => '', 'org_id' => '', 'expiration_hours' => null, 'max_views' => null, 'viewer_email' => null ], $atts);
if (empty($atts['video_id']) || empty($atts['org_id'])) { return '<p>Error: Video ID and Organization ID required</p>'; }
$options = []; if ($atts['expiration_hours']) $options['expirationHours'] = intval($atts['expiration_hours']); if ($atts['max_views']) $options['maxViews'] = intval($atts['max_views']); if ($atts['viewer_email']) $options['viewerEmail'] = $atts['viewer_email'];
$share_data = $this->generate_share_link($atts['org_id'], $atts['video_id'], $options);
if (isset($share_data['body']['webAppUrl'])) { return '<a href="' . esc_url($share_data['body']['webAppUrl']) . '" target="_blank">Watch Video</a>'; }
return '<p>Error generating share link</p>'; }}
// Register shortcode: [hesedvid_share video_id="pubvid_AbCdEf" org_id="org_123456789"]add_shortcode('hesedvid_share', [new HesedVidShare(get_option('hesedvid_api_key')), 'create_shortcode']);?>Security Considerations
Token-Based Access
All private share links include secure tokens:
- Unique Tokens: Each link gets a unique access token
- Token Validation: Tokens are validated on each request
- Automatic Expiration: Tokens expire with the link
- View Tracking: Each token access is logged
Access Restrictions
Implement proper access controls:
// Secure sharing functionconst createSecureShareLink = async (videoId, restrictions) => { // Validate input if (restrictions.expirationHours && restrictions.expirationHours > 168) { throw new Error('Maximum expiration is 168 hours (7 days)'); }
if (restrictions.maxViews && restrictions.maxViews > 1000) { throw new Error('Maximum views is 1000'); }
// Generate secure link const response = await generateShareLink(restrictions);
// Log sharing activity console.log(`Share link created for video ${videoId}`, { expiresAt: response.expiresAt, maxViews: restrictions.maxViews, viewerEmail: restrictions.viewerEmail });
return response;};Error Handling
Common Errors
| Status Code | Error | Description | Solution |
|---|---|---|---|
| 400 | Bad Request | Invalid parameters | Check expiration hours (1-168) and max views (1-1000) |
| 401 | Unauthorized | Invalid API key | Verify API key is correct and active |
| 403 | Forbidden | Video doesn’t belong to organization | Ensure video belongs to your organization |
| 404 | Not Found | Video not found | Verify video public ID is correct |
| 422 | Unprocessable Entity | Invalid email format | Use valid email address format |
| 429 | Too Many Requests | Rate limit exceeded | Wait before making more requests |
Error Response Example
{ "title": "Bad Request", "status": 400, "detail": "Invalid share link parameters", "errors": [ { "message": "Expiration hours must be between 1 and 168", "location": "body.expirationHours", "value": 200 }, { "message": "Max views must be between 1 and 1000", "location": "body.maxViews", "value": 2000 } ]}Rate Limits
| Operation | Limit | Window |
|---|---|---|
| Share link generation | 20 requests | 1 hour |
| Link access | 1000 requests | 1 hour |
Tip
Share links are designed for controlled distribution. Use expiration and view limits to protect sensitive content and track usage.
Caution
Never expose share links with tokens in client-side code. Always generate them server-side and pass the URLs securely to clients.