Authentication
Authentication & Security
HesedVid uses two authentication methods designed for different use cases.
Tip
Most integrations only need API keys. WorkOS sessions are used for the web dashboard.
Authentication Methods
1. API Keys (Recommended)
For programmatic access and server-to-server communication:
curl -X GET https://api.hesedvid.com/v1/api/org_123/environments/prod/videos \ -H "X-Api-Key: hv_live_AbCdEfGhIjKlMnOp123456"Or in JavaScript:
const response = await fetch( 'https://api.hesedvid.com/v1/api/org_123/environments/prod/videos', { headers: { 'X-Api-Key': 'hv_live_AbCdEfGhIjKlMnOp123456' } } );API keys are created through the HesedVid dashboard:
- Log in to your HesedVid dashboard
- Navigate to Settings → API Keys
- Click “Create New Key”
- Configure key name and permissions
- Copy the generated key immediately
Caution
API keys are only shown once when created. Save them securely - they cannot be retrieved again.
| Key Type | Access Level | Use Case |
|---|---|---|
| Full Access | All environments | Admin operations, CI/CD |
| Environment-Scoped | Single environment | Production servers |
| System | Cross-organization | Internal services only |
Caution
Full access keys should only be used for administrative tasks. Use environment-scoped keys for production.
2. WorkOS Sessions (Dashboard)
Used for web dashboard authentication:
- OAuth/SAML SSO support
- Session-based authentication
- Automatic refresh handling
- Organization membership validation
Note
WorkOS sessions are managed automatically by the dashboard. You don’t need to implement this for API access.
Private Video Playback
Videos with allowPublicAccess: false require signed URLs for playback.
How It Works
Client requests video: User wants to watch a private video
Server validates access: Your backend checks user permissions
Server requests signed URL: Call HesedVid API to get signed playback URL
Client plays video: Use the signed URL in any HLS player
Implementation
// Express.js example app.get('/api/video/:id/play-url', requireAuth, async (req, res) => { // 1. Validate user has access to this video const hasAccess = await checkUserVideoAccess(req.user, req.params.id); if (!hasAccess) { return res.status(403).json({ error: 'Access denied' }); }
// 2. Request signed URL from HesedVid const response = await fetch( `https://api.hesedvid.com/v1/api/${ORG_ID}/videos/${req.params.id}/signed-url?expiration=2h`, { headers: { 'X-Api-Key': `${process.env.HESEDVID_API_KEY}` } } );
const { body } = await response.json();
// 3. Return to client res.json({ playbackUrl: body.signed_url });});// React componentfunction PrivateVideoPlayer({ videoId }) { const [videoUrl, setVideoUrl] = useState(null); const [loading, setLoading] = useState(true);
useEffect(() => { async function fetchVideoUrl() { try { // Get signed URL from YOUR backend const response = await fetch(`/api/video/${videoId}/play-url`, { credentials: 'include' // Include auth cookies });
if (!response.ok) { throw new Error('Access denied'); }
const { playbackUrl } = await response.json(); setVideoUrl(playbackUrl); } catch (error) { console.error('Failed to load video:', error); } finally { setLoading(false); } }
fetchVideoUrl(); }, [videoId]);
if (loading) return <div>Loading...</div>; if (!videoUrl) return <div>Unable to load video</div>;
return <VideoPlayer src={videoUrl} />;}Token Security
Signed URLs include JWT tokens with:
| Property | Description | Example |
|---|---|---|
| Video ID | Locked to specific video | vid_AbCdEfGh |
| Expiration | Time-limited access | 1-24 hours |
| Issuer | Verified by our CDN | hesedvid |
| Audience | Intended recipient | Video public ID |
Caution
Never generate signed URLs directly in client-side code. Always use your backend to validate access first.
Security Best Practices
Protect API Keys
- Store in environment variables
- Never commit to version control
- Never expose in client-side code
Use Appropriate Key Scopes
- Environment-scoped for production
- Full access only for admin tasks
- Rotate keys regularly
Implement Access Control
- Validate user permissions server-side
- Log access attempts
- Monitor for unusual patterns
Secure Video Delivery
- Use signed URLs for private content
- Set appropriate expiration times
- Consider IP restrictions for sensitive content
CORS Configuration
Our infrastructure handles CORS automatically:
| Service | CORS Policy | Headers |
|---|---|---|
| CDN | Permissive | Access-Control-Allow-Origin: * |
| API | Restricted | Configured origins only |
| Worker | Permissive | All methods allowed |
Tip
Video playback works from any domain. API calls require authentication regardless of origin.
Rate Limiting
API endpoints are rate-limited per organization:
| Endpoint Type | Limit | Window |
|---|---|---|
| General API | 10,000 | 1 hour |
| Upload URLs | 100 | 1 hour |
| Analytics | 1,000 | 1 hour |
| Video Playback | Unlimited | - |
Rate limit headers:
X-RateLimit-Limit: 10000X-RateLimit-Remaining: 9999X-RateLimit-Reset: 1640995200Troubleshooting
Common Authentication Issues
| Error | Cause | Solution |
|---|---|---|
401 Unauthorized | Missing/invalid API key | Check Authorization header |
403 Forbidden | Valid key, wrong scope | Use correct environment key |
429 Too Many Requests | Rate limit exceeded | Implement backoff |
Token expired | Signed URL timeout | Request fresh URL |
Debug Authentication
# Test API keycurl -I https://api.hesedvid.com/v1/api/org_123/environments \ -H "X-Api-Key: YOUR_API_KEY"
# Check rate limitscurl -I https://api.hesedvid.com/v1/api/org_123/videos \ -H "X-Api-Key: YOUR_API_KEY" \ | grep X-RateLimit