{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cueframe-ai/json-schema/cueframe-ai-compose-create-request-schema.json",
  "title": "ComposeCreateRequest",
  "description": "POST /projects/:id/compose body.",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cueframe-ai-compose-api-openapi.yml#/components/schemas/ComposeCreateRequest",
  "type": "object",
  "properties": {
    "suggestionId": {
      "type": "string",
      "minLength": 1
    },
    "fromComposition": {
      "description": "Reuse the project's current composition as the compose starting point (critique-retry path). The Director RE-AUTHORS graphics: if the current composition is client-authored and contains graphic clips (overlay/component/card), the request is refused (validation_error naming the clips) — render it verbatim with create_render instead. The director's own output (critique-retry) is exempt.",
      "type": "boolean"
    },
    "briefId": {
      "description": "Compose from a persisted Brief (create_brief) — the intent-first door: every Brief field is HONORED or the request is refused loudly naming the field (window from beat moment-pinning; seeded graphics carried VERBATIM as locked clips; exclusions enforced; locale + caption emphasis threaded to the Director). Exactly ONE of suggestionId | fromComposition | briefId.",
      "type": "string",
      "minLength": 1
    },
    "format": {
      "description": "Optional format override. Phase 2 ignores this — format precedence is project.compositionFormat → 9:16 fhd 30fps default.",
      "$ref": "#/$defs/Format"
    },
    "scope": {
      "description": "RequestScope discriminated union (per compose-api-contract.md). Editor-only scopes (captions/overlay-track/broll/overlay-instance/segment) require an editor-session token; API tokens get 403 on those."
    },
    "critique": {
      "description": "Structured critique block (per compose-api-contract.md decision #11). Capped at 2KB total; per-criterion blocks capped at 500 chars.",
      "type": "string",
      "maxLength": 2000
    },
    "parentJobId": {
      "description": "Pointer to the prior compose job this run iterates on. Surfaced on the resulting compose job as baselineComposeJobId.",
      "type": "string"
    },
    "maxCandidates": {
      "description": "Ensemble size, 1–5. Defaults to one; explicit multi-candidate runs divide the job budget across candidates and admit at most two concurrently. A held editorial checkpoint always uses one candidate.",
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "budgetUsd": {
      "description": "Per-job budget cap (USD). Clamped at the route against the org's composeMaxBudgetUsdPerJob setting.",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "qualityThreshold": {
      "description": "Composite-score accept threshold. Server default per contract.",
      "type": "number",
      "minimum": 0,
      "maximum": 10
    },
    "seed": {
      "description": "Deterministic seed for replay.",
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "clientNonce": {
      "description": "Opaque caller token that disambiguates intentional same-critique retries. Without it, identical (project, sug, seed, critique) tuples deduplicate; with it, retries create a fresh execution.",
      "type": "string",
      "maxLength": 64
    },
    "holdAt": {
      "description": "Opt-in checkpoint gates. Each named stage pauses the compose at its boundary (status → awaiting_input) for client review via resume. Absent/empty ⇒ fully autonomous. Non-empty ⇒ the run is a single spine.",
      "maxItems": 3,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "content",
          "layout",
          "motion"
        ]
      }
    }
  },
  "additionalProperties": false,
  "$defs": {
    "Format": {
      "type": "object",
      "properties": {
        "aspectRatio": {
          "type": "string",
          "enum": [
            "16:9",
            "9:16",
            "1:1",
            "4:5"
          ]
        },
        "fps": {
          "anyOf": [
            {
              "type": "number",
              "const": 24
            },
            {
              "type": "number",
              "const": 25
            },
            {
              "type": "number",
              "const": 30
            },
            {
              "type": "number",
              "const": 60
            }
          ]
        },
        "resolution": {
          "type": "string",
          "enum": [
            "hd",
            "fhd",
            "4k"
          ]
        },
        "platform": {
          "type": "string"
        }
      },
      "required": [
        "aspectRatio"
      ]
    }
  }
}