Proxy URL

Every Motioness embed is built from one URL pattern. Once you understand it, you can hand-write proxy URLs without an SDK.

The pattern

text
https://motioness.com/v1/{projectKey}/{srcWithoutScheme}.{format}[?params]
SegmentDescription
{projectKey}Public proxy key, prefixed pk_…. One per project. Find it in Project → Settings → Proxy.
{srcWithoutScheme}Source URL with https:// stripped — e.g. cdn.acme.com/hero.png.
{format}.mp4 returns the animated loop. .jpg returns the poster (always immediate).
?paramsOptional motion / mode / duration / prompt / seed / idem / aspect / wait_ms / sig+exp.

Examples

text
https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4

Two auth modes

A project can use either allowlist auth or signed auth — pick one per project.

Allowlist (default)

Source URL is plain text. The worker resolves the origin and rejects requests where the origin doesn't match allowed_origins. Best for first-party use where the source images live on a domain you control.

text
https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4

Signed

Source URL is base64url-encoded. Path includes ?sig=…&exp=…. The worker verifies the HMAC against the project's signing secret. Best for server-to-server use, sharing across domains, or short-lived URLs.

text
https://motioness.com/v1/pk_abc/{base64url(srcUrl)}.mp4?sig={hmacSha256}&exp={unixSeconds}

See allowlist vs signed for the trade-off, and signed URLs for the signing recipe.

Format selection

Path suffixReturnsGeneration cost
.jpgPoster image (the source, optionally re-encoded)Free, ~5ms cached
.mp4Animated loop / hover videoCounts against monthly quota, 20–60s first hit

A common pattern is to load the poster eagerly and the mp4 lazily:

html
<video src="https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4" poster="https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.jpg" autoplay muted loop playsinline preload="metadata"/>

Cache key

The proxy cache key is content-addressed:

ts
cache_key = canonicalize(url, stripParams: ['wait_ms', 'sig', 'exp'])asset_id = sha256(src_url || motion || mode || dur_seconds || prompt || seed || idem || aspect)[0:16]

So:

  • Two browsers requesting https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4 always hit the same cache entry.
  • Adding ?wait_ms=5000 doesn't busted the cache.
  • Adding ?motion=kinetic does — it's a content param and changes asset_id.
  • Adding ?idem=variant-a does — it forces a distinct asset from the same source.

Anatomy diagram

text
https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4?motion=medium&dur=4└─────┬─────┘ └┬┘ └─┬──┘ └──────────┬─────────┘ └┬┘ └─────────┬──────────┘ │ │ │ │ │ │ │ │ │ │ │ └─ Optional params │ │ │ │ │ (cache-busting where content-affecting) │ │ │ │ └─ Format: mp4 (animated) or jpg (poster) │ │ │ └─ Source URL (https:// stripped, OR base64url if signed) │ │ └─ Project key (public, scopes to your project) │ └─ API version (currently always v1) └─ Origin

Programmatic construction

The SDK does this for you:

ts
import { buildProxyUrl } from '@motioness/proxy-client';const urls = buildProxyUrl({ origin: 'https://motioness.com', projectKey: 'pk_abc', src: 'https://cdn.acme.com/hero.png', motion: 'medium', durSeconds: 4,});urls.mp4 // → https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.mp4?motion=medium&dur=4urls.jpg // → https://motioness.com/v1/pk_abc/cdn.acme.com/hero.png.jpg

For full options including signing, see the SDK reference.

Ask a question... ⌘I