{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/hermoso-ai/json-schema/hermoso-ai-recast-schema.json",
  "title": "Recast",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/app_hermoso_ai_rest.json#/components/schemas/Recast",
  "type": "object",
  "properties": {
    "object": {
      "type": "string",
      "enum": [
        "recast"
      ]
    },
    "dry_run": {
      "type": "boolean"
    },
    "status": {
      "type": "string",
      "description": "`quoted` (a dry run), `refused` (a dry run that would not start), or the job's own status once queued: `queued`, `running`, `done`, `error`. This enum MAY GROW."
    },
    "quote": {
      "$ref": "#/$defs/RecastQuote"
    },
    "engine": {
      "type": [
        "string",
        "null"
      ],
      "description": "The model that will render it."
    },
    "window": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "start": {
          "type": "number"
        },
        "end": {
          "type": "number"
        },
        "seconds": {
          "type": "number"
        }
      },
      "description": "The part of the video that is recast, in seconds."
    },
    "source_seconds": {
      "type": [
        "number",
        "null"
      ],
      "description": "The whole video's length."
    },
    "subject": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "kind": {
          "type": "string",
          "description": "`person`, or `object` when the picture shows no person (it then replaces the video's subject as an object)."
        },
        "name": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "voice": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "voice": {
          "type": "string"
        },
        "language": {
          "type": [
            "string",
            "null"
          ]
        },
        "lip_synced": {
          "type": "boolean"
        }
      }
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Plain sentences worth showing: a window that was cut, a recast done in passes and the cut second to watch, a face that is small in a shot."
    },
    "person_url": {
      "type": [
        "string",
        "null"
      ],
      "description": "With `person.describe` on a real call: the AI person that was made. It is in your Library; send it as `person.image_url` to reuse them."
    },
    "job_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "job": {
      "allOf": [
        {
          "$ref": "#/$defs/Job"
        }
      ],
      "nullable": true,
      "description": "The queued job, as `GET /v1/jobs/{id}` answers it. Poll that until `done`; `url` is the video."
    }
  },
  "$defs": {
    "Job": {
      "type": "object",
      "properties": {
        "object": {
          "type": "string",
          "enum": [
            "job"
          ]
        },
        "id": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "description": "What kind of work it is: video, stitch, avatar, templatead, upscale, and so on. This set MAY GROW."
        },
        "status": {
          "type": "string",
          "description": "queued, running, done or error. `done` and `error` are final. This enum MAY GROW: keep polling on a value you have not seen."
        },
        "progress": {
          "type": "number",
          "description": "0 to 1, when the worker reports it."
        },
        "label": {
          "type": [
            "string",
            "null"
          ]
        },
        "brand_id": {
          "type": "string",
          "description": "The profile that started the job."
        },
        "created_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "ISO-8601."
        },
        "updated_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "ISO-8601. For a finished job, when it finished."
        },
        "run_at": {
          "type": [
            "string",
            "null"
          ],
          "description": "ISO-8601, for work scheduled to start later; null for work that starts immediately."
        },
        "url": {
          "type": [
            "string",
            "null"
          ],
          "description": "The finished file, once `status` is `done` and the job produced one. Always an absolute, publicly reachable URL."
        },
        "poster_url": {
          "type": [
            "string",
            "null"
          ],
          "description": "A still for a finished video, when there is one."
        },
        "model": {
          "type": [
            "string",
            "null"
          ],
          "description": "The model that rendered it."
        },
        "credits_used": {
          "type": [
            "number",
            "null"
          ]
        },
        "error_message": {
          "type": [
            "string",
            "null"
          ],
          "description": "Why it failed, when `status` is `error`. Named `error_message` so it can never be mistaken for this API’s error envelope."
        },
        "cancelled": {
          "type": "boolean",
          "description": "True when the job was stopped by `POST /v1/jobs/{id}/cancel` before it reached a model. Its `status` is `error` and nothing was charged."
        },
        "result": {
          "type": [
            "object",
            "null"
          ],
          "description": "The worker’s full result. PASSTHROUGH TIER: its shape is the job type’s own and improves with it, like a tool’s `data`. Build on the fields above; read this for detail."
        },
        "poll": {
          "type": "string",
          "description": "This job’s own path."
        }
      }
    },
    "RecastQuote": {
      "type": "object",
      "properties": {
        "object": {
          "type": "string",
          "enum": [
            "quote"
          ]
        },
        "credits": {
          "type": [
            "number",
            "null"
          ],
          "description": "The whole price: the sum of `steps`. An estimate: a real call reserves it and is charged its actual cost, usually within a few percent. null when it would not start (see `refused`)."
        },
        "likely_credits": {
          "type": [
            "number",
            "null"
          ]
        },
        "refused": {
          "type": [
            "string",
            "null"
          ],
          "description": "Why it would not start. Nothing was charged."
        },
        "steps": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/RecastStep"
          }
        }
      }
    },
    "RecastStep": {
      "type": "object",
      "properties": {
        "step": {
          "type": "string",
          "description": "`person` (making a described AI person) or `recast`. This set MAY GROW."
        },
        "label": {
          "type": "string",
          "description": "The step in plain words."
        },
        "credits": {
          "type": [
            "number",
            "null"
          ],
          "description": "Its price: what the step reserves when it starts (`basis: hold`) or, once it has run, what it was charged (`basis: charged`)."
        },
        "likely_credits": {
          "type": [
            "number",
            "null"
          ],
          "description": "When the hold covers an optional leg that usually does not run: the likely charge."
        },
        "basis": {
          "type": "string",
          "description": "`hold` or `charged`. This set MAY GROW."
        }
      }
    }
  }
}