Your first asset

This guide ships an animated mp4 to a real page. We'll do it three different ways — pick whichever fits your stack.

1

Sign up + grab your project key

Create an account. Dashboard creates a default project for you. Open Project → Settings → Proxy and copy the Project key (pk_…).

2

Set allowed origins

Add the origin where you'll embed the proxy URL (e.g. https://localhost:3000 for dev, https://acme.com for prod). Without this, every request returns 403.

For server-rendered URLs across origins, switch to signed mode instead.

3

Pick a source image

Any public URL works. For this walkthrough, we'll use https://cdn.acme.com/hero.png. Replace it with one of yours.

The image must be publicly fetchable from Cloudflare — no auth headers, no IP allowlists. Sources behind auth need to be uploaded via POST /api/v1/upload first.

4

Construct the proxy URL

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

Strip the https:// from the source URL. Keep the rest as-is. End with .mp4 for video, .jpg for poster.

5

Embed it

The React component is the most polished surface — it ships with hover effects, lazy loading, callbacks, and SSR-safe progressive enhancement. Use plain HTML only when you can't run JS.

bash
npm install @motioness/proxy-client
tsx
import { MotionessImg } from '@motioness/proxy-client/react';export function Hero() { return ( <MotionessImg projectKey="pk_YOUR_KEY" src="https://cdn.acme.com/hero.png" motion="medium" durSeconds={4} style={{ width: '100%' }} /> );}
6

Watch the first request

The <video> element will:

  1. Show the poster jpg immediately (the source image).
  2. Hit the mp4 URL — first time, server returns 202 Accepted and Retry-After: 30.
  3. After ~20-60 seconds, the mp4 finalizes; the next request streams it.

For faster feedback during development, append ?wait_ms=8000:

text
…/hero.png.mp4?wait_ms=8000

Server long-polls up to 8 seconds before returning 202.

7

Inspect the lifecycle (optional)

Open browser devtools → Network → click the mp4 row. Look at response headers:

text
X-Motioness-Asset-Id: a25b330a71e2bc6bX-Motioness-Stage: queued | stage1 | stage2 | merge | readyX-Motioness-Eta-Ms: 28000X-Request-Id: req_a1b2c3d4Retry-After: 30

To watch the asset finalize live:

bash
curl -N "https://motioness.com/v1/pk_YOUR_KEY/events/a25b330a71e2bc6b"

Each event arrives as id: <ms> / event: <type> / data: <json>. See SSE streaming.

8

Refresh

Reload the page. The mp4 streams from the edge cache in ~5ms. The asset is permanent — same URL, same bytes, forever.

What went wrong?

SymptomLikely causeFix
403 on every requestOrigin not in allowlistAdd your origin in Project → Settings, or use signed mode
403 with "unknown project key"Wrong pk_… valueDouble-check the dashboard
415 unsupported typeSource isn't png/jpg/webpRe-encode or upload via /api/v1/upload
413 file too largeSource > 10 MBResize before fetching
429 monthly limit reachedFree tier exhaustedUpgrade or wait until reset
502 last generation failedVision/i2v failed permanentlyCheck error_code in asset.failed event; try regenerate with ?prompt=…

Next

Webhooks

Get notified when assets finalize.

Learn More
Signed URLs

Generate short-lived URLs server-side.

Learn More
Regenerate

Iterate without changing the URL.

Learn More
Errors + retries

Understand the failure surface.

Learn More
Ask a question... ⌘I