# Mosaic Motion API Mosaic Motion creates durable Rio Motion-agent video generation jobs from prompts. Create a job, poll its status, and submit followups after completion. Base URL: ```txt https://api.motion.so/api/motion ``` Authentication: ```http Authorization: Bearer motion_your_api_key ``` Mosaic Motion API keys start with `motion_`. API jobs require available Mosaic Motion credits on the API key owner's account. ## AI Agents (MCP) AI agents can connect over the Model Context Protocol, guarded by an OAuth 2.1 authorization server. - MCP server: `https://mcp.motion.so/mcp` - Protected resource metadata (RFC 9728): `https://mcp.motion.so/.well-known/oauth-protected-resource` - Authorization server metadata (RFC 8414): `https://mcp.motion.so/.well-known/oauth-authorization-server` - Device verification page (for humans): `https://motion.so/device` Connecting with no credential returns HTTP 401 with an RFC 9728 `WWW-Authenticate` challenge, so MCP clients run the OAuth flow automatically — no API key needed. Ways to authenticate: 1. Browser authorization (default) — the agent registers itself (Dynamic Client Registration) and runs the OAuth flow; the user authorizes in a browser (signing up if new), via authorization_code+PKCE or the device flow at `motion.so/device`. No API key. 2. Service account (autonomous) — an agent self-registers at `POST /oauth/service-accounts/register` (when enabled; discoverable as `service_account_registration_endpoint`), then `POST /oauth/token` with `grant_type=client_credentials` (client_id + client_secret). Its own identity, credits, and billing. Registration returns a `payment_setup_url` — add a card to the agent's wallet there once (or call `setup_payment_method`); after that `purchase_credits` and auto top-up charge it directly with no checkout form. No API key, no device code. 3. API key (fallback) — set `Authorization: Bearer motion_...` as the connector credential if browser authorization isn't available, you prefer a key, or you're running directly against your account. OAuth grants: `authorization_code`+PKCE (S256), `refresh_token`, `client_credentials`, and `urn:ietf:params:oauth:grant-type:device_code` (RFC 8628). Clients register via `POST /oauth/register` (RFC 7591) or CIMD; autonomous agents self-register a service account via `POST /oauth/service-accounts/register` (when enabled). Access tokens are RS256 JWTs with `aud=https://mcp.motion.so/mcp`. MCP tools: `create_video`, `create_followup`, `get_session_status`, `job_status` (app-only; the video widget calls it), `show_plans_and_credits`, `get_credit_balance`, `list_plans`, `subscribe_to_plan`, `purchase_credits`, `setup_payment_method`, `set_auto_topup`, `register_service_account`, `list_api_keys`, `create_api_key`, `revoke_api_key`, `get_settings`, `whoami`. ChatGPT app: create a ChatGPT app named `Motion` with MCP URL `https://mcp.motion.so/mcp`; the server supports streaming HTTP, OAuth 2.1, DCR, and CIMD. Interactive widgets (MCP Apps): in hosts like ChatGPT Apps and Claude, tools render inline UI served as `ui://motion/*.html` (`text/html;profile=mcp-app`); a tool opts in via `_meta.ui.resourceUri` and the ChatGPT alias `_meta["openai/outputTemplate"]`, then the host pushes the tool's `structuredContent`. The video widget (`create_video`/`create_followup`/`get_session_status`) updates itself live and plays the result — it polls the app-only `job_status` tool on a server-driven cadence (`poll_after_seconds`), so the agent never polls. The plans widget (`show_plans_and_credits`) shows plan cards (monthly/annual) + credit top-ups with one-click checkout (`subscribe_to_plan`/`purchase_credits`/`setup_payment_method`). On insufficient credits a generation tool returns `structuredContent.recovery_tool="show_plans_and_credits"` so the agent opens the upgrade widget, then retries. Hosts without MCP Apps get the same data as JSON. Scopes: `motion:sessions:read`, `motion:sessions:write`, `motion:account:read`, `motion:account:manage`, `motion:credits:read`, `motion:credits:purchase`, `motion:credits:manage`, `mcp`. Full MCP guide: `https://docs.motion.so/guides/mcp` ChatGPT app guide: `https://docs.motion.so/guides/chatgpt-app` ## Create Job `POST /sessions` Required body: ```json { "prompt": "Create a 15 second product launch video for a new AI calendar app." } ``` Optional config: - `aspect_ratio`: `16:9`, `9:16`, `1:1`, `4:5`, or `21:9`. - `duration`: `<10s`, `10-30s`, `30s-1min`, or `1-5min`. - `design_system_id`: `mosaic`, `apple`, `claude`, `cursor`, `linear`, `vercel`, `stripe`, `figma`, `notion`, `spotify`, `supabase`, `raycast`, `framer`, `resend`, `mintlify`, `sentry`, `tesla`, `nike`, `shopify`, `airbnb`, or `posthog`. - `design_md`: custom DESIGN.md content as a string or `{ "filename": "DESIGN.md", "content": "..." }`. - `style_reference_url`: YouTube URL. - `attachments`: up to 10 public signed URL attachments with `url`, optional `name`, optional `type`, and optional `content_type`. If both `design_system_id` and `design_md` are sent, `design_md` content is used. Example: ```bash curl https://api.motion.so/api/motion/sessions \ -H "Authorization: Bearer motion_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Create a 15 second product launch video for a new AI calendar app.", "aspect_ratio": "16:9", "duration": "10-30s", "design_system_id": "stripe" }' ``` Successful response status: `202 Accepted`. ```json { "job_id": "405d47cf-f72b-4852-b570-0de2446dbba1", "status": "queued", "status_url": "/api/motion/sessions/405d47cf-f72b-4852-b570-0de2446dbba1" } ``` ## Follow Up `POST /sessions/{job_id}/followups` Uses the same body as `POST /sessions`. The job must already be `completed`; otherwise the API returns HTTP 409 with `error: "followup_requires_completed_job"`. ## Poll `GET /sessions/{job_id}` Poll until `status` is `completed` and `output.download_url` is non-null. The Mosaic Motion API does not expose a separate public output or download endpoint. The response can also include `sources`, an additive array of source assets currently used in the composition. Sources include `source_kind` (`licensed_library`, `article`, `web_search`, `web`, `connector`, `upload`, `generated`, `unknown`), `provider`, source/display URLs when available, `media_type`, `rights_status`, and `usages` with timestamps/scene placement. Internal storage paths and GCS URIs are not exposed. Completed response shape: ```json { "job_id": "405d47cf-f72b-4852-b570-0de2446dbba1", "status": "completed", "created_at": "2026-04-28T23:01:04.198Z", "updated_at": "2026-04-28T23:06:43.695Z", "completed_at": "2026-04-28T23:05:58.695Z", "error": null, "pending_user_input": false, "output": { "status": "completed", "download_url": "https://storage.googleapis.com/...", "expires_at": "2026-04-29T00:06:43.695Z", "completed_at": "2026-04-28T23:06:41.112Z", "error": null }, "sources": [] } ``` Statuses: `queued`, `created`, `running`, `awaiting_user_input`, `completed`, or `failed`. ## Errors Errors are JSON. Common responses: - HTTP 400: validation error. - HTTP 401: missing or invalid Mosaic Motion API key. - HTTP 402: insufficient credits. - HTTP 404: job not found. - HTTP 409: followup requires a completed job. ## Important Behavior - All API initiated jobs are owned by the API key owner. - Credit purchases and auto top-up settings must be managed in the frontend at https://motion.so, not through the API. - A Mosaic Motion API key cannot poll another user's job. - Attachment URLs must be public to Motion servers without extra headers or cookies. - YouTube style references must be YouTube URLs. - The public API intentionally exposes only job creation, completed-job followups, and polling. Full documentation: `/llms-full.txt` OpenAPI schema: `/openapi.json`