URL Signing
URL signing enables browsers to access Editframe's media endpoints without exposing your API key.
The Problem
Your backend has an API key. Your browser needs to play video from Editframe's CDN. You cannot put the API key in the browser — it would grant full access to your account.
URL signing solves this: your backend generates a short-lived, scoped token that authorizes the browser to access a specific URL. The token expires after a set time (typically 1 hour) and only works for the URL it was created for.
When You Need URL Signing
You need URL signing if:
- Your application renders Editframe compositions in a browser
- You use
<ef-video>,<ef-audio>, or other media elements withsrcpointing to Editframe URLs - You need browser access to
/api/v1/transcode/*endpoints for adaptive streaming
You don't need URL signing if:
- You only render videos server-side (using
createRenderanddownloadRender) - All media playback happens in your backend
How It Works
- Browser needs to access a media URL
- Browser requests a token from your server
- Your server calls
createURLTokenwith your API key - Editframe returns a signed JWT
- Browser uses the JWT to access the media URL
Implementation
Server-Side: Token Generation
Create an endpoint that proxies to /api/v1/url-token:
// server.jsimport express from "express";import { Client, createURLToken } from "@editframe/api";const app = express();const client = new Client(process.env.EDITFRAME_API_KEY);app.post("/sign-url", express.json(), async (req, res) => {try {const { url } = req.body;// Generate signed tokenconst token = await createURLToken(client, url);res.json({ token });} catch (error) {console.error("Failed to sign URL:", error);res.status(500).json({ error: "Failed to sign URL" });}});app.listen(3000);
Client-Side: Configuration
In your Editframe Elements project, configure the signing endpoint:
<!-- Configure signing URL --><ef-configuration signingURL="/sign-url"></ef-configuration><!-- Media elements automatically use signed URLs --><ef-timegroup mode="contain" class="w-[1280px] h-[720px]"><ef-video src="https://editframe.com/api/v1/transcode/manifest.m3u8?url=..."></ef-video></ef-timegroup>
Set up an Elements project with npm create @editframe if you haven't already. See the editframe-create skill for setup instructions.
When <ef-video> loads, it:
- Detects the
srcrequires authentication - POSTs to
/sign-urlwith{url: "https://editframe.com/api/v1/transcode/..."} - Receives
{token: "jwt..."} - Adds
Authorization: Bearer jwt...to the media request
Token Lifecycle
Tokens are valid for 1 hour by default. The browser caches tokens and reuses them for the same URL until they expire.
For transcode endpoints, the browser signs the base URL once and reuses the token for all segments:
Base URL: https://editframe.com/api/v1/transcodeSegments: /1080p/init.m4s, /1080p/1.m4s, /1080p/2.m4s, ...
One token covers all segments for a given source video.
Alternative: Anonymous Tokens
If your application uses session cookies (users logged into editframe.com), you can use the anonymous token flow:
// server.js (session-based)app.post("/sign-url", async (req, res) => {const { url } = req.body;// No API key needed — relies on session cookieconst response = await fetch("https://editframe.com/ef-sign-url", {method: "POST",headers: { "Content-Type": "application/json" },credentials: "include", // Include session cookiebody: JSON.stringify({ url }),});const { token } = await response.json();res.json({ token });});
This pattern is less common. Most applications use API key authentication.
Integration with Composition Skills
URL signing coordinates with the elements-composition and react-composition skills:
- elements-composition: Use
<ef-configuration signingURL>to set up signing for HTML compositions - react-composition: Use
<Configuration signingURL>component for React-based compositions
Both skills document the client-side integration. This skill documents the server-side token generation.
Debugging
If media fails to load:
- Check browser console for 401 errors
- Verify
/sign-urlendpoint is accessible - Confirm API key is valid:
curl -H "Authorization: Bearer $API_KEY" https://editframe.com/api/v1/organization - Check token expiry: decode the JWT and inspect the
expclaim
Tokens are standard JWTs. Use jwt.io to inspect them.