Allowlist vs signed URLs
Two ways to authorize proxy URLs — pick one per project.
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.
texthttps://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:
bashcurl -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.
texthttps://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:
bashcurl -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
tsimport { 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
| Capability | Allowlist | Signed |
|---|---|---|
| Hand-writeable URLs | ✅ | ❌ (need HMAC) |
| Source origins fixed | ✅ (via allowed_origins) | ❌ (sign any URL) |
| Short-lived URLs | ❌ | ✅ (exp controls) |
| Cross-origin | ❌ | ✅ |
| Hot-link protection | Origin-based | Token-based |
| Setup cost | Lowest | Server-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:
textimg-src 'self' https://motioness.com;media-src 'self' https://motioness.com;