---
title: "Create a project"
method: POST
path: "/v1/projects"
tags: ["projects"]
---

# Create a project

`POST /v1/projects`

## Request

- Base URL: `https://api.cueframe.ai`
- URL: `https://api.cueframe.ai/v1/projects`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.cueframe.ai/api/auth/mcp/authorize`, token URL `https://api.cueframe.ai/api/auth/mcp/token`, scopes: `projects:write`)
  - API key in header `PAYMENT-SIGNATURE`

Create a video project — the container for a composition (the editable timeline), its media, brand kit, and renders. Every other authoring call (import or generate media, apply composition ops, compose, render, export) takes this project's id. Set the output format here (aspectRatio, fps, resolution).

## Request body

- ProjectCreateRequest: POST /projects body.
  - `name` string, required
  - `description` string
  - `format` Format
    - `aspectRatio` '16:9' | '9:16' | '1:1' | '4:5', required
    - `fps` union
      - 24
      - 25
      - 30
      - 60
    - `resolution` 'hd' | 'fhd' | '4k'
    - `platform` string
  - `brandKitId` string
  - `width` number
  - `height` number

## Response `201`

Project created.

- ProjectResponse: Project response per §Projects.
  - `id` string, required
  - `name` string, required
  - `description` string, nullable, required
  - `format` Format, required
    - `aspectRatio` '16:9' | '9:16' | '1:1' | '4:5', required
    - `fps` union
      - 24
      - 25
      - 30
      - 60
    - `resolution` 'hd' | 'fhd' | '4k'
    - `platform` string
  - `brandKitId` string, nullable, required
  - `activeCompositionId` string, nullable, required
  - `composition` ProjectCompositionSummary, required: Summary of a project's stored composition.
    - `hasComposition` boolean, required
    - `sceneCount` integer, required
    - `duration` number, nullable, required
    - `updatedAt` string, nullable, required
  - `lastRender` ProjectLastRender, nullable, required: Most recent render for a project, if any.
    - `id` string, required
    - `status` string, required
    - `createdAt` string, required
    - `outputUrl` string, nullable, required
    - `outputExpiresAt` string, nullable, required
  - `webUrl` string, nullable, required: A browser URL that opens THIS project, or null when CueFrame exposes no web view for a project. Null today: the console serves account surfaces (keys, usage, billing) and has no per-project page, so there is no link to give. Do NOT synthesise one — a guessed console path 404s. Show the user rendered output (create_render → outputUrl) or a preview still instead. This field becoming non-null is the signal that a real project view exists.
  - `createdAt` string, required

## Other responses

- `400`: Bad request — validation_error / invalid_cursor / invalid_query.
- `401`: Missing or invalid Authorization header.
- `402`: Payment required. Returned when the caller presents no API key on a priced operation: the body AND the `Payment-Required` header carry the x402 v2 challenge (accepted scheme, network, USDC asset, amount, payTo). Sign the EIP-3009 authorization and retry with a `PAYMENT-SIGNATURE` header. A KEYED caller sees this status instead when their plan lacks or has exhausted the feature (`billing_required`).
- `403`: Forbidden — permission insufficient.
- `404`: Resource not found.
- `422`: Unprocessable — invalid_composition / media_in_use / session_in_use / render_not_cancellable.
- `429`: Rate limited. Retry-After header present.
- `500`: Internal error.

---

[API](https://skmtc.dev/cueframe/apis/cueframe-api.md) · [All operations](https://skmtc.dev/cueframe/apis/cueframe-api/llms.txt) · [OpenAPI document](https://skmtc.dev/cueframe/apis/cueframe-api/revisions/8f9bfe362b4a?raw)
