Nova Studio

API

The HTTP endpoints this application exposes. Everything listed here exists in the running app; nothing is planned or illustrative.

Authentication

Canvas and community endpoints authenticate with the session cookie set at sign-in, so a request from the app carries credentials automatically.

Billing endpoints authenticate with a bearer token instead — the Supabase access token from the browser session — because they are also reachable from server-side integrations.

Guest sessions are accepted only where a run costs nothing. Publishing, liking, sharing and live generation all require an account.

Generation

A run is asynchronous. The submit returns as soon as the job is on the queue, and the result is collected by polling. A synchronous endpoint cannot survive a client disconnect or outlive a request timeout, which is what a minute-long video render routinely does.

Every response carries `retryAfterMs`. Honour it rather than polling on a fixed interval: it reflects the model's real latency and, when the run is queued behind others, how far back it is.

Credits are reserved at submit and settled at collection, so a failed run gives its reservation back. Identical requests that are still in flight resolve to the same task rather than starting a second run.

GET /api/ai/capabilities
What this session can run: the available models, the task types each one serves, and the inputs it accepts.
POST /api/ai/run
Starts one run. Reserves credits, then returns a task id — it does not wait for the result.
GET /api/ai/status/[taskId]
Where that run has got to, and the asset once it succeeds. Poll at the interval the previous response asked for.
GET /api/canvas/usage
Runs used today, the daily limit, in-flight count, and when the window resets.
POST /api/canvas/generate
Retired. Returns 410; use POST /api/ai/run.
POST /api/ai/run
{
  "taskType": "image.generate",
  "modelId": "auto",
  "prompt": "a lighthouse in fog",
  "params": { "aspectRatio": "16:9" },
  "inputs": []
}

200 OK
{
  "success": true,
  "taskId": "5f1c…",
  "status": "running",
  "retryAfterMs": 2000
}

GET /api/ai/status/5f1c…

200 OK
{
  "success": true,
  "taskId": "5f1c…",
  "status": "succeeded",
  "asset": {
    "kind": "image",
    "url": "/api/canvas/assets/<owner>/2026/08/<uuid>.png",
    "sample": false,
    "label": "fal-ai/flux/dev"
  }
}

Assets

Stored assets are served from a private bucket. The redirect means video range requests go straight to storage, so seeking works and large files do not stream through the application server.

GET /api/canvas/assets
Lists the generations this account owns, newest first.
GET /api/canvas/assets/{key}
Redirects to a short-lived signed URL after checking the key belongs to the caller.

Community

Counters are maintained by database triggers over the like and use tables, and are not writable by any client — including the work’s owner.

GET /api/community/works
The feed. Accepts category, sort, q and mine.
POST /api/community/works
Publishes one stored generation. Rejects media the caller does not own.
DELETE /api/community/works/{id}
Unpublishes. Restricted to the owner by row level security.
POST · DELETE /api/community/works/{id}/like
Likes or unlikes; returns the count read back after the write.
POST /api/community/works/{id}/use
Records a use and returns the prompt and model so the caller can build on it.

Projects and sharing

Invitations are keyed by email address and are never confirmed or denied against the user table, so the endpoint cannot be used to discover which addresses are registered.

GET · POST /api/canvas/projects
Lists and creates cloud projects.
GET · PATCH /api/canvas/projects/{id}
Reads and updates one project and its workflow document.
GET · POST · DELETE /api/canvas/projects/{id}/members
Members and pending invitations.
POST /api/canvas/invitations
Claims any invitations addressed to the signed-in account.

Deployment configuration

Generation is off until a provider key is present. Setting one is what turns it on; NOVA_LIVE_GENERATION_ENABLED=false is the kill switch that overrides it without removing the key.

Model identifiers are overridable per kind and tier, because hosted models are renamed and retired on the provider’s schedule.

FAL_KEY=...                     # or REPLICATE_API_TOKEN
NOVA_GENERATION_PROVIDER=       # pin one when several keys are set
NOVA_LIVE_GENERATION_ENABLED=true

NOVA_MAX_CONCURRENT_RUNS=3
NOVA_MAX_RUNS_PER_MINUTE=10
NOVA_MAX_RUNS_PER_DAY=50

# NOVA_<PROVIDER>_MODEL_<KIND>_<ROUTE>
NOVA_FAL_MODEL_VIDEO_QUALITY=fal-ai/kling-video/v1.6/pro/text-to-video