Skip to main content

Signed URL for video transcodes

Private video transcodes need a signed URL. A signed URL carries an expiry time and a signature that FileSpin checks before serving the video.

You'll need these, besides the asset ID and the transcode name (such as 480p-video.mp4):

ParameterTypeDescription
API KeystringYour API Key. This is available in your Authorization Settings page. Keep it on your server.
EXPIRYintegerWhen the URL stops working, in seconds since the Unix epoch.
ACCESS_IDstringAccess Id that must be used to sign URLs. You can obtain your account's Access Id from the Authorization Settings page.
warning

Sign URLs on your server. Never put the API key in browser or mobile app code.

How to sign a transcode URL​

  1. Build the string to sign: {ASSET_ID}/transcodes/{TRANSCODE}?expiry={EXPIRY}&accessId={ACCESS_ID}. For example, f99255d2bf8142b29561641491e9940c/transcodes/480p-video.mp4?expiry=1452894790&accessId=IZJTAMBQGAYDAMBQGAYDAMBQGAYDANKT.
  2. Calculate the HMAC-SHA1 of the string to sign, using your API key as the key.
  3. Encode the result as URL-safe base64, keeping the = padding: use - and _ in place of + and /. Then URL-encode it.
  4. Add it as the signature parameter: https://cdn.filespin.io/api/v1/assets/{string to sign}&signature={signature}.

Only expiry and accessId are signed. You can add delivery=download&dl_prefix=… to a signed MP4 URL to download it as a file.

Example signed video URL​

With the example API key 0c3c6d026858460abc4de1dcb4de15ac:

https://cdn.filespin.io/api/v1/assets/f99255d2bf8142b29561641491e9940c/transcodes/480p-video.mp4?expiry=1452894790&accessId=IZJTAMBQGAYDAMBQGAYDAMBQGAYDANKT&signature=fPsKf_315aye5jTizI-bzHmNXGg%3D

Code examples​

Each example reads the API key and Access Id from the FILESPIN_API_KEY and FILESPIN_ACCESS_ID environment variables, and prints a URL that's valid for one hour.

Python​

import base64, hashlib, hmac, os, time
from urllib.parse import quote

API_KEY = os.environ["FILESPIN_API_KEY"]
ACCESS_ID = os.environ["FILESPIN_ACCESS_ID"]
asset_id = "f99255d2bf8142b29561641491e9940c"
transcode = "480p-video.mp4"
expiry = int(time.time()) + 3600 # valid for one hour

string_to_sign = f"{asset_id}/transcodes/{transcode}?expiry={expiry}&accessId={ACCESS_ID}"
digest = hmac.new(API_KEY.encode(), string_to_sign.encode(), hashlib.sha1).digest()
signature = quote(base64.urlsafe_b64encode(digest).decode(), safe="")
signed_url = f"https://cdn.filespin.io/api/v1/assets/{string_to_sign}&signature={signature}"
print(signed_url)

Node.js​

const crypto = require("crypto");

const API_KEY = process.env.FILESPIN_API_KEY;
const ACCESS_ID = process.env.FILESPIN_ACCESS_ID;
const assetId = "f99255d2bf8142b29561641491e9940c";
const transcode = "480p-video.mp4";
const expiry = Math.floor(Date.now() / 1000) + 3600; // valid for one hour

const stringToSign = `${assetId}/transcodes/${transcode}?expiry=${expiry}&accessId=${ACCESS_ID}`;
// URL-safe base64 that keeps the "=" padding (digest("base64url") drops it, so don't use it)
const signature = encodeURIComponent(
crypto.createHmac("sha1", API_KEY).update(stringToSign).digest("base64")
.replace(/\+/g, "-").replace(/\//g, "_")
);
const signedUrl = `https://cdn.filespin.io/api/v1/assets/${stringToSign}&signature=${signature}`;
console.log(signedUrl);

Java​

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class SignedVideoUrl {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("FILESPIN_API_KEY");
String accessId = System.getenv("FILESPIN_ACCESS_ID");
String assetId = "f99255d2bf8142b29561641491e9940c";
String transcode = "480p-video.mp4";
long expiry = System.currentTimeMillis() / 1000 + 3600; // valid for one hour

String stringToSign = assetId + "/transcodes/" + transcode + "?expiry=" + expiry + "&accessId=" + accessId;
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(apiKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
byte[] digest = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
String signature = URLEncoder.encode(Base64.getUrlEncoder().encodeToString(digest), StandardCharsets.UTF_8);
String signedUrl = "https://cdn.filespin.io/api/v1/assets/" + stringToSign + "&signature=" + signature;
System.out.println(signedUrl);
}
}

PHP​

<?php
$api_key = getenv('FILESPIN_API_KEY');
$access_id = getenv('FILESPIN_ACCESS_ID');
$asset_id = 'f99255d2bf8142b29561641491e9940c';
$transcode = '480p-video.mp4';
$expiry = time() + 3600; // valid for one hour

$string_to_sign = "$asset_id/transcodes/$transcode?expiry=$expiry&accessId=$access_id";
$digest = hash_hmac('sha1', $string_to_sign, $api_key, true);
$signature = urlencode(strtr(base64_encode($digest), '+/', '-_'));
$signed_url = "https://cdn.filespin.io/api/v1/assets/$string_to_sign&signature=$signature";
echo $signed_url . "\n";