Base URL
https://api.qmotion.ai/api/v1On a local or self-hosted deployment this is your gateway origin followed by /api/v1.
Authentication
Authenticate every request with a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEYCreate and revoke keys on the API Keys page. A key is shown only once at creation — store it in a secret manager. Anyone with the key can act as your account.
| Method | Path | Description |
|---|---|---|
| GET | /projects | List your projects, newest first (paginated with ?page & ?limit). |
| POST | /projects | Create a new project. Requires a title and a prompt. |
| GET | /projects/{id} | Retrieve a single project together with all of its scenes. |
| GET | /public/projects/{id}public | Read-only fetch of a project its owner has marked public. No auth required. |
Create a project
curl -X POST https://api.qmotion.ai/api/v1/projects \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Launch teaser",
"prompt": "A 30-second cinematic teaser for a productivity app",
"settings": { "aspectRatio": "16:9", "resolution": "1080p" }
}'Returns 201 with { "success": true, "data": { ...project } }. The new project starts as a draft.
List your projects
curl https://api.qmotion.ai/api/v1/projects?page=1&limit=10 \
-H "Authorization: Bearer YOUR_API_KEY"Returns { "success": true, "data": [ ... ], "meta": { page, limit, total, totalPages } }.
Fetch a shared (public) project — no auth
curl https://api.qmotion.ai/api/v1/public/projects/PROJECT_IDOnly returns a project whose owner has marked it public; otherwise 404.
Events
Choose which events each endpoint receives on the Webhooks page. You can also send a test delivery from there.
Payload
Every delivery is a JSON body with the same envelope. The data object varies by event.
{
"event": "project.completed",
"data": {
"projectId": "6650f0c2a1b2c3d4e5f60789",
"title": "Launch teaser",
"exportUrl": "https://cdn.qmotion.ai/exports/launch-teaser.mp4"
},
"timestamp": "2026-08-13T12:34:56.000Z"
}For project.failed, data is { projectId, title, error } instead.
Verifying the signature
Each request carries an X-Webhook-Event header and an X-Webhook-Signature header of the form sha256=<hex>. The signature is an HMAC-SHA256 of the raw request body keyed with your webhook signing secret (shown once at creation). Compute the same HMAC and compare before trusting a payload.
import crypto from 'crypto';
function verify(rawBody, signatureHeader, secret) {
const expected =
'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
// Use a constant-time comparison in production.
return signatureHeader === expected;
}
// Express: capture the RAW body (e.g. express.raw()) so the bytes you
// hash match exactly what Qmotion signed.
app.post('/webhooks/qmotion', (req, res) => {
const ok = verify(req.body, req.header('X-Webhook-Signature'), SIGNING_SECRET);
if (!ok) return res.status(401).end();
res.status(200).end();
});