{
 "openapi": "3.1.0",
 "info": {
  "title": "Reelsmith API",
  "version": "1",
  "description": "Send a film script, dry-run it, render it on your own provider keys, poll and download the MP4.\n\n**Auth:** `Authorization: Bearer rs_live_…` — create a key in Settings → Developer API (shown once). The API is part of the **Studio plan**; keys stop working (403) if the account leaves it. A key acts as its owner: their films, provider keys, storage and spending cap. Cookies are never read on `/v1`.\n\n**Billing:** usage credits (1 credit = €0.01, VAT included); provider charges go to your own provider keys. Errors are `{\"error\": true, \"message\"}`.\n\nScript format: `docs/script-format.md`. Overview and an example: `docs/api.md`."
 },
 "servers": [
  {
   "url": "/",
   "description": "This Reelsmith host"
  }
 ],
 "security": [
  {
   "bearer": []
  }
 ],
 "tags": [
  {
   "name": "Account"
  },
  {
   "name": "Films"
  },
  {
   "name": "Renders"
  }
 ],
 "paths": {
  "/v1/account": {
   "get": {
    "tags": [
     "Account"
    ],
    "summary": "Your account",
    "description": "Email, credit balance and prices. Free. 300 / 10 min.",
    "operationId": "getAccount",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Account"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/films": {
   "post": {
    "tags": [
     "Films"
    ],
    "summary": "Create a film from a script",
    "description": "Checks the whole script first (every problem comes back in `errors`), then creates the film with its scenes, shots, characters and places. 5 credits, charged only if it is created. 30 / 10 min.",
    "operationId": "createFilm",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "film": {
           "$ref": "#/components/schemas/Film"
          },
          "notes": {
           "type": "array",
           "items": {
            "type": "string"
           }
          },
          "credits": {
           "$ref": "#/components/schemas/Credits"
          }
         },
         "additionalProperties": false,
         "required": [
          "film",
          "notes",
          "credits"
         ]
        }
       }
      }
     },
     "400": {
      "description": "Invalid request.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "Not enough credits.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "413": {
      "description": "Body too large.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/Script"
       }
      }
     }
    }
   },
   "get": {
    "tags": [
     "Films"
    ],
    "summary": "List your films",
    "description": "Free. 300 / 10 min.",
    "operationId": "listFilms",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "items": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/FilmSummary"
           }
          }
         },
         "additionalProperties": false,
         "required": [
          "items"
         ]
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/v1/films/{film_id}": {
   "get": {
    "tags": [
     "Films"
    ],
    "summary": "Get a film",
    "description": "Its settings and scenes. Free. 300 / 10 min.",
    "operationId": "getFilm",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Film"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "film_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   },
   "delete": {
    "tags": [
     "Films"
    ],
    "summary": "Delete a film",
    "description": "Cancels its renders and deletes its files. Free. 60 / 10 min.",
    "operationId": "deleteFilm",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Ok"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "film_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  },
  "/v1/films/{film_id}/script": {
   "get": {
    "tags": [
     "Films"
    ],
    "summary": "Export a film as a script",
    "description": "The film in the import format, with every picture as a data URI — re-importable on any account. Free. 30 / 10 min.",
    "operationId": "exportFilm",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Script"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "film_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  },
  "/v1/films/{film_id}/plan": {
   "post": {
    "tags": [
     "Films"
    ],
    "summary": "Dry run",
    "description": "How the film splits into clips, warnings, missing provider keys, the provider-cost estimate on your own keys and the credits a render would cost. Nothing is rendered. Free. 120 / 10 min.",
    "operationId": "planFilm",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Plan"
        }
       }
      }
     },
     "400": {
      "description": "Invalid request.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/Scope"
       }
      }
     }
    },
    "parameters": [
     {
      "name": "film_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  },
  "/v1/films/{film_id}/renders": {
   "post": {
    "tags": [
     "Renders"
    ],
    "summary": "Start a render",
    "description": "Renders on your own provider keys. Reuses each shot's newest stored take while it still matches (free) unless `rerender`. 2 credits per new second, min 10; seconds it doesn't make are refunded if it fails or is cancelled. Refused above your account's `max_render_usd`. 30 / 10 min.",
    "operationId": "startRender",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Render"
        }
       }
      }
     },
     "400": {
      "description": "Invalid request.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "Not enough credits.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "409": {
      "description": "Estimate above `confirm_usd`, or a render already running.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RenderRequest"
       }
      }
     }
    },
    "parameters": [
     {
      "name": "film_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  },
  "/v1/renders/{render_id}": {
   "get": {
    "tags": [
     "Renders"
    ],
    "summary": "Render status",
    "description": "Poll every few seconds: `queued` → `running` → `done` | `failed` | `cancelled`. Free. 600 / 10 min.",
    "operationId": "getRender",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Render"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "render_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  },
  "/v1/renders/{render_id}/cancel": {
   "post": {
    "tags": [
     "Renders"
    ],
    "summary": "Cancel a render",
    "description": "Unmade clips are refunded. 60 / 10 min.",
    "operationId": "cancelRender",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Render"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "render_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  },
  "/v1/renders/{render_id}/video": {
   "get": {
    "tags": [
     "Renders"
    ],
    "summary": "Download the film",
    "description": "The finished MP4. Free. 120 / 10 min.",
    "operationId": "downloadVideo",
    "responses": {
     "200": {
      "description": "The film.",
      "content": {
       "video/mp4": {
        "schema": {
         "type": "string",
         "format": "binary"
        }
       }
      }
     },
     "401": {
      "description": "No, invalid or revoked API key.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Not found or not yours.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limit (see the operation's description).",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "The key's owner isn't on the Studio plan — the API is a Studio feature.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "parameters": [
     {
      "name": "render_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ]
   }
  }
 },
 "components": {
  "schemas": {
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "const": true
     },
     "message": {
      "type": "string"
     },
     "errors": {
      "type": "array",
      "description": "Script imports: every problem found, with its path.",
      "items": {
       "type": "object",
       "properties": {
        "path": {
         "type": "string"
        },
        "message": {
         "type": "string"
        }
       },
       "additionalProperties": false,
       "required": [
        "path",
        "message"
       ]
      }
     }
    },
    "additionalProperties": false,
    "required": [
     "error",
     "message"
    ]
   },
   "Prices": {
    "type": "object",
    "properties": {
     "film": {
      "type": "integer",
      "description": "Credits per film created from a script."
     },
     "render_second": {
      "type": "integer",
      "description": "Credits per newly rendered second."
     },
     "render_minimum": {
      "type": "integer",
      "description": "Minimum credits per render that makes anything new."
     }
    },
    "additionalProperties": false,
    "required": [
     "film",
     "render_second",
     "render_minimum"
    ],
    "description": "Usage-credit prices (1 credit = €0.01, VAT included)."
   },
   "Account": {
    "type": "object",
    "properties": {
     "email": {
      "type": "string"
     },
     "credits": {
      "type": "integer",
      "description": "Balance in credits."
     },
     "prices": {
      "$ref": "#/components/schemas/Prices"
     }
    },
    "additionalProperties": false,
    "required": [
     "email",
     "credits",
     "prices"
    ]
   },
   "Credits": {
    "type": "object",
    "properties": {
     "charged": {
      "type": "integer"
     },
     "balance": {
      "type": "integer"
     }
    },
    "additionalProperties": false,
    "required": [
     "charged",
     "balance"
    ]
   },
   "FilmSummary": {
    "type": "object",
    "properties": {
     "film_id": {
      "type": "string",
      "format": "uuid"
     },
     "name": {
      "type": "string"
     },
     "created_at": {
      "type": "integer",
      "description": "Unix time, seconds."
     },
     "updated_at": {
      "type": "integer",
      "description": "Unix time, seconds."
     }
    },
    "additionalProperties": false,
    "required": [
     "film_id",
     "name",
     "created_at",
     "updated_at"
    ]
   },
   "Film": {
    "type": "object",
    "properties": {
     "film_id": {
      "type": "string",
      "format": "uuid"
     },
     "name": {
      "type": "string"
     },
     "logline": {
      "type": "string"
     },
     "aspect_ratio": {
      "enum": [
       "16:9",
       "9:16",
       "1:1",
       "21:9",
       "4:3"
      ]
     },
     "default_model": {
      "type": "string",
      "description": "Video model id (`GET /api/catalog` → `models[].id`)."
     },
     "created_at": {
      "type": "integer",
      "description": "Unix time, seconds."
     },
     "scenes": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "scene_id": {
         "type": "string",
         "format": "uuid"
        },
        "title": {
         "type": "string"
        },
        "duration": {
         "type": "integer",
         "description": "Seconds."
        },
        "shots": {
         "type": "integer",
         "description": "Number of shots."
        },
        "model": {
         "type": "string",
         "description": "This scene's video model, if it overrides the film's."
        }
       },
       "additionalProperties": false,
       "required": [
        "scene_id",
        "title",
        "duration",
        "shots"
       ]
      }
     }
    },
    "additionalProperties": false,
    "required": [
     "film_id",
     "name",
     "logline",
     "aspect_ratio",
     "default_model",
     "created_at",
     "scenes"
    ]
   },
   "Shot": {
    "type": "object",
    "properties": {
     "text": {
      "type": "string",
      "description": "The shot script (docs/script-format.md): action lines, `@name:` dialogue, `SFX:`/`MUSIC:`/`VO:` sound, `CAM:`/`LIGHT:` camera lines; `&` = same time as the line above."
     },
     "sound": {
      "type": "string"
     },
     "seconds": {
      "type": [
       "integer",
       "null"
      ]
     },
     "direction": {
      "type": "object"
     },
     "continuous": {
      "type": "boolean"
     }
    },
    "additionalProperties": true,
    "description": "One shot. More fields (frames, pictures, model) are in docs/script-format.md."
   },
   "Scene": {
    "type": "object",
    "properties": {
     "title": {
      "type": "string"
     },
     "duration": {
      "type": "integer"
     },
     "scene_prompt": {
      "type": "string"
     },
     "sound": {
      "type": "string"
     },
     "model": {
      "type": [
       "string",
       "null"
      ]
     },
     "direction": {
      "type": "object"
     },
     "max_clip": {
      "type": [
       "integer",
       "null"
      ]
     },
     "chain_from_previous": {
      "type": "boolean"
     },
     "shots": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Shot"
      }
     }
    },
    "additionalProperties": true,
    "description": "One scene (one place and time)."
   },
   "Script": {
    "type": "object",
    "properties": {
     "version": {
      "const": 1
     },
     "film": {
      "type": "object",
      "properties": {
       "name": {
        "type": "string",
        "description": "Required, ≤ 120."
       },
       "logline": {
        "type": "string"
       },
       "global_prompt": {
        "type": "string"
       },
       "negative_prompt": {
        "type": "string"
       },
       "aspect_ratio": {
        "enum": [
         "16:9",
         "9:16",
         "1:1",
         "21:9",
         "4:3"
        ]
       },
       "default_model": {
        "type": "string"
       },
       "video_quality": {
        "enum": [
         "",
         "480p",
         "720p",
         "1080p",
         "4k"
        ],
        "description": "Output quality; `\"\"` = each model's default. Models make the nearest they have at or below it."
       },
       "direction": {
        "type": "object",
        "description": "Look picks per category (`GET /api/catalog` → `direction`)."
       },
       "preset": {
        "type": [
         "string",
         "null"
        ]
       },
       "use_director": {
        "type": "boolean"
       },
       "director_provider": {
        "enum": [
         "anthropic",
         "openai",
         null
        ]
       }
      },
      "additionalProperties": false,
      "required": [
       "name"
      ]
     },
     "scenes": {
      "type": "array",
      "minItems": 1,
      "items": {
       "$ref": "#/components/schemas/Scene"
      }
     },
     "characters": {
      "type": "array",
      "items": {
       "type": "object"
      }
     },
     "environments": {
      "type": "array",
      "items": {
       "type": "object"
      }
     }
    },
    "additionalProperties": false,
    "required": [
     "film",
     "scenes"
    ],
    "description": "A film script — the format `GET /v1/films/{film_id}/script` exports. Unknown fields are rejected; every field and limit is in docs/script-format.md (≤ 25 MB, pictures as data URIs)."
   },
   "Scope": {
    "type": "object",
    "properties": {
     "scene_id": {
      "type": "string",
      "format": "uuid",
      "description": "Only this scene."
     },
     "model": {
      "type": "string",
      "description": "Preview another video model for every scene (or `scene_id`'s); nothing is saved."
     },
     "rerender": {
      "type": "boolean",
      "description": "Make new takes of everything instead of reusing matching stored takes."
     }
    },
    "additionalProperties": false
   },
   "Warning": {
    "type": "object",
    "properties": {
     "level": {
      "enum": [
       "error",
       "warn",
       "info"
      ]
     },
     "scene": {
      "type": "string"
     },
     "text": {
      "type": "string"
     },
     "scene_id": {
      "type": "string",
      "format": "uuid"
     },
     "item_id": {
      "type": "string",
      "format": "uuid"
     }
    },
    "additionalProperties": false,
    "required": [
     "level",
     "scene",
     "text"
    ]
   },
   "Clip": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string"
     },
     "scene_id": {
      "type": "string",
      "format": "uuid"
     },
     "shot": {
      "type": "integer"
     },
     "model": {
      "type": "string"
     },
     "seconds": {
      "type": "integer"
     },
     "start": {
      "type": "string",
      "description": "`frame` = starts on a picture, `chain` = continues the previous clip."
     },
     "reused": {
      "type": "boolean",
      "description": "A stored take is reused (free)."
     },
     "prompt": {
      "type": "string"
     }
    },
    "additionalProperties": false,
    "required": [
     "id",
     "scene_id",
     "shot",
     "model",
     "seconds",
     "reused",
     "prompt"
    ]
   },
   "Plan": {
    "type": "object",
    "properties": {
     "clips": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Clip"
      }
     },
     "warnings": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Warning"
      }
     },
     "providers": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "missing_keys": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "Providers you still need a key for."
     },
     "total_seconds": {
      "type": "integer"
     },
     "new_seconds": {
      "type": "integer"
     },
     "est_provider_usd": {
      "type": "number",
      "description": "What your provider keys will be billed, at the film's video quality. Pass it as `confirm_usd` to start the render."
     },
     "credits": {
      "type": "integer",
      "description": "Credits the render would cost."
     },
     "balance": {
      "type": "integer"
     },
     "blocking": {
      "type": "boolean",
      "description": "An `error` warning: the render would be refused."
     }
    },
    "additionalProperties": false,
    "required": [
     "clips",
     "warnings",
     "providers",
     "missing_keys",
     "total_seconds",
     "new_seconds",
     "est_provider_usd",
     "credits",
     "balance",
     "blocking"
    ]
   },
   "RenderRequest": {
    "allOf": [
     {
      "$ref": "#/components/schemas/Scope"
     },
     {
      "type": "object",
      "properties": {
       "confirm_usd": {
        "type": "number",
        "description": "The provider estimate you accept (from a dry run with the same scope)."
       }
      },
      "additionalProperties": false,
      "required": [
       "confirm_usd"
      ]
     }
    ]
   },
   "Render": {
    "type": "object",
    "properties": {
     "render_id": {
      "type": "string",
      "format": "uuid"
     },
     "film_id": {
      "type": "string",
      "format": "uuid"
     },
     "status": {
      "enum": [
       "queued",
       "running",
       "done",
       "failed",
       "cancelled"
      ]
     },
     "progress": {
      "type": "integer",
      "description": "0–100."
     },
     "error": {
      "type": "string"
     },
     "est_provider_usd": {
      "type": "number"
     },
     "credits_charged": {
      "type": "integer"
     },
     "credits_refunded": {
      "type": "integer"
     },
     "video_url": {
      "type": "string",
      "description": "Present when `done`."
     },
     "clips": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "id": {
         "type": "string"
        },
        "seconds": {
         "type": "integer"
        },
        "status": {
         "type": "string"
        }
       },
       "additionalProperties": false,
       "required": [
        "id",
        "seconds",
        "status"
       ]
      }
     },
     "created_at": {
      "type": "integer",
      "description": "Unix time, seconds."
     },
     "finished_at": {
      "type": "integer",
      "description": "Unix time, seconds."
     }
    },
    "additionalProperties": false,
    "required": [
     "render_id",
     "film_id",
     "status",
     "progress",
     "est_provider_usd",
     "credits_charged",
     "credits_refunded",
     "clips",
     "created_at"
    ]
   },
   "Ok": {
    "type": "object",
    "properties": {
     "result": {
      "const": true
     }
    },
    "additionalProperties": false,
    "required": [
     "result"
    ]
   }
  },
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer",
    "bearerFormat": "rs_live_…"
   }
  }
 }
}
