Allowlist vs signed URLs

Every Motioness project picks one of two auth modes. Each protects the same thing — preventing third parties from burning your generation quota by hot-linking proxy URLs.

Allowlist mode (default)

Source URL is plain text in the path. The worker resolves the source origin and rejects requests where it isn't in your allowed_origins list.

text
https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4 └────────────┬────────────┘ cdn.acme.com must be in allowed_origins

Best for: first-party use, where the source images live on a domain you control.

Trade-off: anyone who knows your project key + a source URL on your allowlist can hit the proxy. That's fine for public marketing assets, less fine for paywalled or short-lived content.

Configure

Project → Settings → Proxy → Allowed origins, or via API:

bash
curl -X PUT https://motioness.com/api/projects/$PROJECT_ID/proxy-config \ -H 'Content-Type: application/json' -b cookie.txt \ -d '{ "allowed_origins": ["https://acme.com", "https://cdn.acme.com"] }'

Subdomain matching: https://acme.com accepts https://www.acme.com, https://app.acme.com, etc.

Signed mode

Source URL is base64url-encoded in the path. Path includes ?sig=…&exp=…. The worker verifies an HMAC-SHA256 against your project's signing secret.

text
https://motioness.com/v1/pk_abc/aHR0cHM6Ly9jZG4uYWNtZS5jb20vaGVyby5wbmc.mp4 ?sig=a7e3f1...&exp=1714808400

Best for: server-to-server use, ephemeral URLs, sharing across origins, paywalled content.

Trade-off: can't be hand-written. The signing secret never leaves your backend; URLs are minted server-side and embedded in pages.

Enable

Project → Settings → Proxy → Enable signing OR set enable_signing: true:

bash
curl -X PUT https://motioness.com/api/projects/$PROJECT_ID/proxy-config \ -H 'Content-Type: application/json' -b cookie.txt \ -d '{ "enable_signing": true }'

Toggling it ON mints a fresh signing secret on first save. Toggling it OFF revokes the secret. Use POST /api/projects/:id/keys/rotate?which=signing to rotate without changing the toggle.

Sign URLs server-side

ts
import { buildProxyUrl } from '@motioness/proxy-client';const exp = Math.floor(Date.now() / 1000) + 60 * 60; // 1hconst srcUrl = 'https://cdn.acme.com/hero.png';const projectKey = 'pk_abc';// HMAC-SHA256(secret, `${projectKey}:${srcUrl}:${exp}`) → hexconst sig = await hmacSha256Hex(SIGNING_SECRET, `${projectKey}:${srcUrl}:${exp}`);const urls = buildProxyUrl({ origin: 'https://motioness.com', projectKey, src: srcUrl, signature: sig, exp,});// urls.mp4 is now signed and expires in 1h

See signed URLs guide for the full HMAC recipe in Node, Workers, Python, and Go.

Comparison

CapabilityAllowlistSigned
Hand-writeable URLs❌ (need HMAC)
Source origins fixed✅ (via allowed_origins)❌ (sign any URL)
Short-lived URLs✅ (exp controls)
Cross-origin
Hot-link protectionOrigin-basedToken-based
Setup costLowestServer-side signing required

Both at once?

Not supported per project. A request hitting a project keyed for one mode but using the other mode's auth shape returns 403. If you need both — e.g. some pages signed, some allowlist — create two projects and use the right key on each surface.

What about CSP?

Both modes survive any CSP. The browser sees a normal mp4 URL on motioness.com; you just need:

text
img-src 'self' https://motioness.com;media-src 'self' https://motioness.com;
Ask a question... ⌘I