Descript Platform API

REST API for programmatically creating projects, importing media, running AI edits via the Underlord agent, publishing compositions, exporting transcripts, and managing asynchronous jobs in a Descript Drive. Authenticated with a personal Bearer API token scoped to a single Drive.

OpenAPI Specification

descript-openapi.yml Raw ↑
openapi: 3.0.0
info:
  description: Descript API documentation.
  version: '1.2'
  title: Descript API
  x-logo:
    url: assets/descript-logo.svg
    altText: Descript
  license:
    name: Proprietary
    url: https://www.descript.com/terms
servers:
  - url: https://descriptapi.com/v1
tags:
  - name: Getting started
    description: "> **Early Access:** These APIs are still under active development, and may change and evolve over time. We're thankful for your input, and excited to build with you.\n\nThe Descript API lets you programmatically create projects, import media, and edit your projects — all without opening the app.\n\nTo learn more, visit [descript.com/api](https://descript.com/api).\n\n## Create an API token\n\n1. In Descript, open **Settings** and select **API tokens** from the sidebar. Then click **Create token**.\n\n![Navigate to Settings > API tokens and click Create token](assets/token1.png)\n\n2. Give your token a name and select the Drive it should be associated with. Click **Create token**.\n\n<img src=\"assets/token2.png\" alt=\"Name your token and select a Drive\" width=\"500\" />\n\n3. Copy your token and store it in a safe place. You won't be able to view it again. If you lose it, you'll need to generate a new one.\n\n<img src=\"assets/token3.png\" alt=\"Copy and save your API token\" width=\"500\" />\n\n> **Warning:** Treat your API token like a password. Anyone with your token can make API requests on your behalf using your account permissions. Never share your token publicly or commit it to source control.\n\nInclude the token as a Bearer token in the `Authorization` header of your API requests.\n\n## Import media into a new project\n\nYou can create a new project, import media, and place the media into a composition all in one API request using the [import endpoint](#operation/importProjectMedia). This step also transcribes and processes the media so that it's ready for you or the agent to edit.\n\nTo import files, pass in public or pre-signed URIs. Currently, the API does not support uploading a file directly. To test the API with an example file, use the demo video included in the sample request below.\n\nImporting and processing is an asynchronous job, so the response payload will contain a `job_id` for you to [query the status of the job](#operation/getJob) and information about the newly created project. Note that `project_id` and `project_url` are returned immediately alongside `job_id`, but opening the project in Descript will not always show the API's processing state in real time. To prevent unintended changes, we recommend that you do not make any changes to the project until the job has stopped.\n\n\n\n**Request**\n\n```bash\ncurl -X POST https://descriptapi.com/v1/jobs/import/project_media \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_name\": \"My First Video\",\n    \"add_media\": {\n      \"demo.mp4\": {\n        \"url\": \"https://test-files.descriptapi.com/demo-video.mp4\"\n      }\n    },\n    \"add_compositions\": [\n      {\n        \"name\": \"Demo Video\",\n        \"clips\": [\n          { \"media\": \"demo.mp4\" }\n        ]\n      }\n    ]\n  }'\n```\n\n**Response**\n\n```json\n{\n  \"job_id\": \"project-media-import-9d635d5b\",\n  \"drive_id\": \"c9c5c47e\",\n  \"project_id\": \"e2f89ce6\",\n  \"project_url\": \"https://web.descript.com/e2f89ce6\"\n}\n```\n\n## Check for import completion\n\nPoll the [job status endpoint](#operation/getJob) using the `job_id` from the last step to check whether the import job is finished processing. When it is, you'll see `job_state: \"stopped\"`. You can then check the `results` object to see its full results.\n\nYou can also pass in a `callback_url` as a part of the first import request, and we'll ping you when the job has stopped with the same response payload.\n\n**Request**\n\n```bash\ncurl https://descriptapi.com/v1/jobs/project-media-import-9d635d5b \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\n**Response**\n\n```json\n{\n  \"job_id\": \"project-media-import-9d635d5b\",\n  \"job_type\": \"import/project_media\",\n  \"job_state\": \"stopped\",\n  \"project_id\": \"e2f89ce6\",\n  \"project_url\": \"https://web.descript.com/e2f89ce6\",\n  \"result\": {\n    \"status\": \"success\",\n    \"media_status\": {\n      \"main.mp4\": {\n        \"status\": \"success\",\n        \"duration_seconds\": 69.477006\n      }\n    },\n    \"created_compositions\": [\n      { \"id\": \"f8e5088a-4d53-4aab-9d4f-c6624b7d7622\", \"name\": \"Demo Video\" }\n    ]\n  }\n}\n```\n\n## Prompt for edits with Agent Underlord\n\nOnce your media is imported, you can use the [agent edit endpoint](#operation/agentEditJob) to prompt Underlord for edits, just as you would in the app. Because it's an API, conversation and follow up questions aren't practical. So we recommend framing your edits as a one-shot prompt with all the information the agent needs.\n\nEditing can take some time, so the response also returns a `job_id` that you can use to [check the status of the job](#operation/getJob). You can also pass in a `callback_url` as a part of an agent request, and we'll ping you when the job has stopped.\n\n**Request**\n\n```bash\ncurl -X POST https://descriptapi.com/v1/jobs/agent \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"project_id\": \"e2f89ce6\",\n    \"prompt\": \"Add studio sound and captions\"\n  }'\n```\n\n**Response**\n\n```json\n{\n  \"job_id\": \"project-agent-edit-e2f89ce6\",\n  \"drive_id\": \"c9c5c47e\",\n  \"project_id\": \"e2f89ce6\",\n  \"project_url\": \"https://web.descript.com/e2f89ce6\"\n}\n```\n\n## Wait for the agent to complete its job\n\nPoll the [job status endpoint](#operation/getJob) using the `job_id`. When the agent job completes successfully, the response includes a summary of what it accomplished (see the `result.agent_response` field). Use the project URL to open the project in Descript and review Underlord's changes.\n\n**Request**\n\n```bash\ncurl https://descriptapi.com/v1/jobs/project-agent-edit-e2f89ce6 \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nOnce the agent job is successfully complete, you’ll see a response from the agent with a brief summary of what it accomplished. You can then use the project url to review its changes directly in Descript.\n\n**Response**\n\n```json\n{\n\t\"job_id\":\"project-agent-edit-e2f89ce6\",\n\t\"job_type\":\"agent\",\n  \"project_id\":\"YOUR_PROJECT_ID\",\n\t\"project_url\":\"https://web.descript.com/e2f89ce6\",\n\t\"job_state\":\"stopped\",\n\t\"created_at\":\"2026-02-09T05:42:27.554Z\",\n\t\"stopped_at\":\"2026-02-09T05:43:15.296Z\",\n\t\"drive_id\":\"1df135a5-dc4a-4dc3-8f7d-681cfbe961e4\",\n\t\"result\":{\n\t\t\"status\":\"success\",\n    \"agent_response\":\"Done! I've applied Studio Sound to enhance your audio quality and added classic karaoke-style captions to your video.\",\n\t\t\"project_changed\":true,\n\t\t\"media_seconds_used\":0,\n\t\t\"ai_credits_used\":32\n  }\n}\n```\n"
  - name: Using the CLI
    description: |
      The CLI wraps the API into a simple to use command line tool with interactive flows for setting up authentication, importing, and prompting the agent. It also has built-in polling for job completion.

      ## Requirements

      Before installing the CLI, you'll need **Node.js 24 or higher**. Visit [nodejs.org](https://nodejs.org/) to download and install the latest LTS version for your operating system.

      ## Install and set up

      First, install the latest version of the CLI using npm.

      ```bash
      npm install -g @descript/platform-cli@latest
      ```

      Next, configure the CLI with your API key.

      ```bash
      descript-api config set api-key
      ```

      ![Setting up the CLI](assets/cli-set-up.gif)


      ## Import media

      Use the `import` command to create a project by passing a project name and the link to any media you want to upload, or run `descript-api import` for interactive mode. The CLI shows live progress and outputs the project ID when done.

      ```bash
      descript-api import \
        --name "My First Project" \
        --media "https://test-files.descriptapi.com/demo-video.mp4"
      ```

      ![Interactive CLI import](assets/cli-import.gif)

      ## Use the agent

      Use the `agent` command to edit a project by passing in the project id and an Underlord prompt.

      ```bash
      descript-api agent \
        --project-id YOUR_PROJECT_ID \
        --prompt "Remove filler words and add Studio Sound to all clips"
      ```

      You can also ask Underlord create a new project from a prompt alone by writing the script for you!

      ```bash
      descript-api edit --new \
        --prompt "Write a script about how to make great coffee"
      ```

      ## All commands

      Run `descript-api help` to see the full list of available commands and options.
  - name: API Endpoints
    description: Import media, edit projects with AI, and query jobs and projects.
  - name: Direct file upload
    description: |
      Instead of providing a public URL, you can upload files directly from your local machine using the [import endpoint](#operation/importProjectMedia). The flow has three steps: request signed upload URLs, PUT your file bytes, then poll for completion.

      ## Step 1 — Request upload URLs

      Call the import endpoint with `content_type` and `file_size` instead of `url` for each media item you want to upload directly.

      **Request**

      ```bash
      curl -X POST https://descriptapi.com/v1/jobs/import/project_media \
        -H "Authorization: Bearer YOUR_API_TOKEN" \
        -H "Content-Type: application/json" \
        -d '{
          "project_name": "My Upload Project",
          "add_media": {
            "recording.mp4": {
              "content_type": "video/mp4",
              "file_size": 52428800
            }
          },
          "add_compositions": [
            {
              "name": "Main",
              "clips": [
                { "media": "recording.mp4" }
              ]
            }
          ]
        }'
      ```

      The response includes an `upload_urls` object keyed by media reference ID. Each entry contains a signed `upload_url` (valid for 3 hours), plus `asset_id` and `artifact_id` for the created asset.

      **Response**

      ```json
      {
        "job_id": "project-media-import-a1b2c3d4",
        "drive_id": "c9c5c47e",
        "project_id": "e2f89ce6",
        "project_url": "https://web.descript.com/e2f89ce6",
        "upload_urls": {
          "recording.mp4": {
            "upload_url": "https://storage.googleapis.com/bucket/...",
            "asset_id": "d4e5f6a7-1234-5678-9abc-def012345678",
            "artifact_id": "a1b2c3d4-5678-9abc-def0-123456789abc"
          }
        }
      }
      ```

      ## Step 2 — Upload the file

      PUT the raw file bytes to the signed URL. Use `Content-Type: application/octet-stream`.

      ```bash
      curl -X PUT \
        -H "Content-Type: application/octet-stream" \
        --data-binary @recording.mp4 \
        "https://storage.googleapis.com/bucket/..."
      ```

      The import job detects the upload automatically and begins processing.

      ## Step 3 — Poll for completion

      Check the job status the same way as a URL-based import — poll the [job status endpoint](#operation/getJob) with the `job_id`, or provide a `callback_url` in the original request.

      ```bash
      curl https://descriptapi.com/v1/jobs/project-media-import-a1b2c3d4 \
        -H "Authorization: Bearer YOUR_API_TOKEN"
      ```

      When the job reaches `job_state: "stopped"`, check `result.status` for success or failure.

      ## Mixing URL imports and direct uploads

      You can combine URL-based and direct upload media items in a single request. Items with `url` are fetched server-side; items with `content_type` and `file_size` return signed upload URLs.

      ```bash
      curl -X POST https://descriptapi.com/v1/jobs/import/project_media \
        -H "Authorization: Bearer YOUR_API_TOKEN" \
        -H "Content-Type: application/json" \
        -d '{
          "project_name": "Mixed Import",
          "add_media": {
            "intro.mp4": {
              "url": "https://example.com/intro.mp4"
            },
            "recording.mp4": {
              "content_type": "video/mp4",
              "file_size": 52428800
            }
          }
        }'
      ```

      The response will include `upload_urls` only for the direct upload items.

      ## Required fields

      | Field | Type | Description |
      |-------|------|-------------|
      | `content_type` | string | MIME type of the file (e.g., `video/mp4`, `audio/wav`) |
      | `file_size` | integer | File size in bytes |
      | `language` | string | *(optional)* ISO 639-1 language code for transcription. Auto-detected if omitted. |
  - name: Authentication
    description: |
      The Descript API uses personal API tokens to authenticate requests. Tokens are scoped to a specific Drive and inherit your permissions on that Drive.

      To create a token, see the [Getting Started](#section/Getting-started/Create-an-API-token) guide.

      > **Warning:** Treat your API token like a password. Anyone with your token can make API requests on your behalf using your account permissions. Never share your token publicly or commit it to source control.

      ## Using your token

      Include the token as a Bearer token in the `Authorization` header of your API requests.

      **Example**

      ```bash
      curl -H "Authorization: Bearer YOUR_API_TOKEN" https://descriptapi.com/v1/status
      ```
  - name: Rate Limiting
    description: |
      The Descript API implements rate limiting to ensure fair usage and protect service availability.
      When you exceed the rate limit, the API returns a `429 Too Many Requests` response.

      ## Rate Limit Headers

      When a rate limit is exceeded, the response includes the following headers:

      | Header | Description |
      |--------|-------------|
      | `Retry-After` | Number of seconds to wait before retrying the request |
      | `X-RateLimit-Remaining` | Number of requests remaining in the current window |
      | `X-RateLimit-Consumed` | Number of requests consumed in the current window |

      ## Handling Rate Limits

      When you receive a `429` response, use the `Retry-After` header to determine how long to wait before retrying.
      This approach is more efficient than using fixed delays or exponential backoff alone.
  - name: Edit in Descript
    description: |
      > **Note:** The Edit in Descript integration requires contacting Descript for access. [Reach out to us](https://descript.com/api) to get started.

      Edit in Descript API enables partners to give their users the ability to transfer audio or video content to Descript for editing.

      Edit in Descript buttons work by generating one-time use, public Import URLs to the Descript import UI that users
      can be automatically sent to. On that page, they can make a few simple selections before kicking off a Partner cloud
      storage to Descript cloud storage transfer. This will redirect them to a Descript Project ready for editing.

      Partners can initiate the request by securely sending an information schema backend-to-backend to the Descript API
      using a token, in exchange for the Import URL to redirect the user. Partners do not need to store this schema, as
      Descript will do so and use it to start fetching the files when the user confirms the action

      1. When a user clicks `Edit in Descript`, partner's backend service makes POST request to:
          `https://descriptapi.com/v1/edit_in_descript/schema` with an authorization bearer token header and JSON schema body
      2. Descript responds with either an Import URL or an error
      3. Partner redirects the user's browser to the URL returned in step 2 or display an error message and link to help documentation

      ### Partner User Experience
      Some guidelines for partners as you consider this integration:
      * We recommend placing the `Edit in Descript` option next to your download options
        * If you offer multiple download options, such as combined vs. split audio/video files, we recommend placing
      this integration clearly in context with each option, or only the supported option, to help users understand
      what will be exported.
        * Each time you request an import link, a new one is generated. Import links expire after 3 hours. After using an
      import link, the only way to find an imported Project again is in Descript.
        * If an import link has expired or the contents of the schema has changed, please request a new import link with
      the updated schema. This will create a new Descript Project when used.
      * We will provide Descript-branded assets to fit your proposed placement of the `Edit in Descript` CTA and ask
      that you don't edit the assets beyond what we provide. We are happy to work with you on getting you the right
      assets for your placement.
      * Partners should provide error-handling for the POST request, at minimum displaying a generic error message and
      linking to a help article (we can provide a link for this if you prefer).
      * Progress will be conveyed to the user in the Descript side of the user experience.

      ### Descript User Experience
      When users are directed to a Descript Import URL, they'll be asked to either create an account or login in order
      to proceed.

      Next, they will be presented with a few options about how they'd like to import the data, such as where the new
      Descript Project should be created.

      They'll then be redirected to the Project, where they can monitor the progress of the import and start editing.
  - name: Export from Descript
    description: |
      Users of Descript currently have three options to export their edited content. They can export files in various
      formats, share a Descript link, or use our [one-click cloud export](https://help.descript.com/hc/en-us/articles/360043869551-Becoming-a-Supported-Content-Hosting-Partner)
      to publish directly to a partner.

      ### Roundtrip Metadata
      If Project data previously came from a partner via an Edit in Descript schema then any Descript Export pages
      will include `<meta/>` tags which contains the `partner_drive_id` and `source_id` provided when originally
      importing into Descript. This allows partners to deduplicate data returning back to partner systems after
      editing in Descript. Both partner and source properties are included on all public Descript Export pages.

      ```
      <meta property="descript:partner" content="9121bf3a-60fe-4a31-ad59-ed32df610cc3" />
      <meta property="descript:source" content="409148bd-81aa-4af6-a9c3-29b761506f3a" />
      ```
paths:
  /jobs/import/project_media:
    post:
      tags:
        - API Endpoints
      summary: Import media and sequences
      security:
        - bearerAuth: []
      description: "Import media files into a new or existing project and create compositions.\n\nThis endpoint can:\n- Create a new project if `project_id` is not provided\n- Import media files from URLs\n- Create multitrack sequences\n- Create compositions (timelines) from existing or new media in the project\n- Trigger transcription and other background processing tasks\n\n### Media URL requirements\n- URLs must be accessible by Descript servers\n- URLs must support HTTP Range requests\n- Recommended to sign URLs for 12-48 hours to reduce chance of failure\n- [Supported file types](https://help.descript.com/hc/en-us/articles/10164098416909-Supported-file-types)\n\n### Direct file upload\n\nInstead of providing a URL, you can upload files directly by specifying `content_type` and `file_size` for a media item. The response will include a signed `upload_url` for each direct upload item. PUT the file bytes to that URL, and the import job will process it automatically. See the [Direct file upload](#tag/Direct-file-upload) guide for a full walkthrough.\n\n### Async Operations\n\nImports\_run in the background and return a `job_id`. Monitor progress via the [GET /jobs/{job_id}](#operation/getJob) endpoint.\n\n### Dynamic webhook\n\nIf `callback_url` is provided, Descript will POST the job status to that URL when the job finishes (successfully or not).\n\nThe payload will match the format returned by [GET /jobs/{job_id}](#operation/getJob).\n"
      operationId: importProjectMedia
      requestBody:
        content:
          application/json:
            schema:
              type: object
              description: |
                Request to import media into a project and optionally create compositions.
                This operation will:
                - Create a new project if project_id is not provided (using the drive associated with the personal token)
                - Import media files from URLs or create multitrack sequences
                - Optionally create one or more compositions
                - Trigger transcription and other background processing
              properties:
                project_id:
                  type: string
                  format: uuid
                  description: |
                    Existing project ID to import media into. If not provided, a new project will be created.
                    When importing into an existing project, media filenames must not conflict with existing files.
                  example: 9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
                project_name:
                  type: string
                  description: Name for the new project. Only used when project_id is not provided.
                  example: Marketing Video
                team_access:
                  type: string
                  description: |
                    Access level for drive members. Only applicable when creating a new project
                    (when project_id is not provided). Defaults to `none` if not specified.
                    - edit: Users can edit the project
                    - comment: Users can view and comment but not edit
                    - view: Users can view but not comment or edit
                    - none: No shared access (private to owner)
                  enum:
                    - edit
                    - comment
                    - view
                    - none
                  default: none
                  example: edit
                folder_name:
                  type: string
                  description: |
                    Folder path to place the new project in (e.g. "Clients/Acme/Videos").
                    Supports nested paths using "/" as separator. Only applicable when creating a new project
                    (when project_id is not provided). Existing folders along the path are reused; missing
                    segments are created automatically.
                  example: Clients/Acme
                add_media:
                  type: object
                  description: |
                    Map of media reference IDs (display names with optional folder paths) to media import items.
                    Keys are the display names that will appear in the project (e.g., "Misc/intro.mp4" or "demo.mp4").
                    Values define how to import each media item (URL import or multitrack sequence).
                  additionalProperties:
                    type: object
                    description: |
                      Defines how to import a single media item. Can be either a URL import or a multitrack sequence.
                    oneOf:
                      - type: object
                        title: URL Import
                        description: Import media from a URL
                        required:
                          - url
                        properties:
                          url:
                            type: string
                            format: uri
                            description: |
                              URL to import media from. Must be accessible by Descript servers and support Range requests.
                              Recommended to sign URLs for 12-48 hours to reduce chance of failure.
                            example: https://example.com/intro.mp4
                          language:
                            type: string
                            description: |
                              ISO 639-1 language code for transcription (e.g., "en", "es", "fr").
                              If not specified, language is auto-detected from the audio.
                            example: en
                        additionalProperties: false
                      - type: object
                        title: Direct Upload
                        description: |
                          Upload a file directly to Descript. The API returns a signed upload URL
                          in the response. PUT your file to that URL, then the import job will
                          process it automatically.
                        required:
                          - content_type
                          - file_size
                        properties:
                          content_type:
                            type: string
                            description: MIME type of the file (e.g., "video/mp4", "audio/wav")
                            example: video/mp4
                          file_size:
                            type: integer
                            description: File size in bytes
                            example: 52428800
                          language:
                            type: string
                            description: |
                              ISO 639-1 language code for transcription (e.g., "en", "es", "fr").
                              If not specified, language is auto-detected from the audio.
                            example: en
                        additionalProperties: false
                      - type: object
                        title: Multitrack Sequence
                        description: Create a multitrack sequence from multiple media files
                        required:
                          - tracks
                        properties:
                          tracks:
                            type: array
                            description: Array of tracks to combine into a multitrack sequence
                            minItems: 1
                            items:
                              type: object
                              required:
                                - media
                              properties:
                                media:
                                  type: string
                                  description: Media reference ID (display name) of the media to include in this track
                                  example: Recordings/camera1.mp4
                                offset:
                                  type: number
                                  format: float
                                  description: Optional time offset in seconds for syncing this track
                                  example: 50
                                  default: 0
                              additionalProperties: false
                        additionalProperties: false
                  example:
                    Misc/intro.mp4:
                      url: https://example.com/intro.mp4
                    demo.mp4:
                      url: https://example.com/demo.mp4
                    Multicam_Track:
                      tracks:
                        - media: Recordings/camera1.mp4
                          offset: 0
                        - media: Recordings/camera2.mp4
                          offset: 50
                add_compositions:
                  type: array
                  description: Optional list of compositions to create in the project
                  items:
                    type: object
                    description: Defines a composition to create in the project
                    properties:
                      name:
                        type: string
                        description: Name of the composition. If not provided, uses default naming.
                        example: Rough Cut
                      width:
                        type: integer
                        description: Width of the composition in pixels
                        example: 1920
                        default: 1920
                      height:
                        type: integer
                        description: Height of the composition in pixels
                        example: 1080
                        default: 1080
                      fps:
                        type: number
                        description: |
                          **[Work in progress]** This property is not yet supported and will be ignored if provided.

                          Frame rate for the composition in frames per second.
                          Common values: 24, 25, 29.97, 30, 60.
                        default: 30
                        example: 30
                      clips:
                        type: array
                        description: Ordered list of clips to include in the composition
                        items:
                          type: object
                          required:
                            - media
                          properties:
                            media:
                              type: string
                              description: Media reference ID (display name) of the media to add as a clip
                              example: Misc/intro.mp4
                          additionalProperties: false
                    required:
                      - clips
                    additionalProperties: false
                callback_url:
                  type: string
                  format: uri
                  description: |
                    Optional webhook URL to call when the job completes or fails.
                    Descript will POST the job status (same format as [GET /jobs/{job_id}](#operation/getJob)) to this URL.
                  example: https://example.com/webhooks/descript/job_callback
              additionalProperties: false
            examples:
              create_with_composition:
                summary: Create project with initial composition
                description: Most common use case for seeding a project with a simple composition
                value:
                  project_name: Marketing Video
                  add_media:
                    Misc/intro.mp4:
                      url: https://example.com/intro.mp4
                    demo.mp4:
                      url: https://example.com/demo.mp4
                    Misc/outro.mp4:
                      url: https://example.com/outro.mp4
                  add_compositions:
                    - name: Rough Cut
                      clips:
                        - media: Misc/intro.mp4
                        - media: demo.mp4
                        - media: Misc/outro.mp4
              import_only:
                summary: Import media without composition
                description: Import files for later composition creation
                value:
                  project_name: Video Project
                  add_media:
                    Assets/intro.mp4:
                      url: https://example.com/intro.mp4
                    Assets/logo.png:
                      url: https://example.com/logo.png
              direct_upload:
                summary: Direct file upload
                description: Upload a local file directly instead of providing a URL
                value:
                  project_name: Upload Project
                  add_media:
                    recording.mp4:
                      content_type: video/mp4
                      file_size: 52428800
                  add_compositions:
                    - name: Main
                      clips:
                        - media: recording.mp4
              multitrack_sequence:
                summary: Create multitrack sequence
                description: Combine multiple tracks with time offsets
                value:
 

# --- truncated at 32 KB (117 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/descript/refs/heads/main/openapi/descript-openapi.yml