> ## Documentation Index
> Fetch the complete documentation index at: https://help.descript.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List jobs

> List recent jobs with optional filtering by project or job type.

By default, jobs created within the last 7 days are returned. Use `created_after` and
`created_before` to customize the time range. The maximum lookback is 30 days.

Results are paginated. Use the `cursor` from the response `pagination.next_cursor` to
fetch subsequent pages.

Query parameters allow you to filter the results:
* Filter by `project_id` to see all jobs for a project
* Filter by `type` to see specific job types (import/project_media, agent)




## OpenAPI

````yaml GET /jobs
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
security: []
tags:
  - name: Getting started
    description: "The 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/connect-with-us/hosting-partners)

      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:
    get:
      tags:
        - API Endpoints
      summary: List jobs
      description: >
        List recent jobs with optional filtering by project or job type.


        By default, jobs created within the last 7 days are returned. Use
        `created_after` and

        `created_before` to customize the time range. The maximum lookback is 30
        days.


        Results are paginated. Use the `cursor` from the response
        `pagination.next_cursor` to

        fetch subsequent pages.


        Query parameters allow you to filter the results:

        * Filter by `project_id` to see all jobs for a project

        * Filter by `type` to see specific job types (import/project_media,
        agent)
      operationId: listJobs
      parameters:
        - in: query
          name: project_id
          description: Filter by project ID
          required: false
          schema:
            type: string
            format: uuid
        - in: query
          name: type
          description: Filter by job type
          required: false
          schema:
            type: string
            enum:
              - import/project_media
              - agent
        - in: query
          name: cursor
          description: >-
            Cursor for the next page of results, obtained from
            `pagination.next_cursor` in a previous response
          required: false
          schema:
            type: string
        - in: query
          name: limit
          description: Number of items per page (1-100). Defaults to 20.
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - in: query
          name: created_after
          description: >-
            Filter jobs created after this timestamp (ISO 8601). Default: 7 days
            ago. Oldest allowed: 30 days ago.
          required: false
          schema:
            type: string
            format: date-time
        - in: query
          name: created_before
          description: 'Filter jobs created before this timestamp (ISO 8601). Default: now.'
          required: false
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Jobs list retrieved successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - pagination
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/JobStatus'
                  pagination:
                    type: object
                    properties:
                      next_cursor:
                        type: string
                        description: >-
                          Cursor for the next page of results. Absent if no more
                          results.
              examples:
                mixed_jobs:
                  summary: List of jobs with different types and states
                  value:
                    data:
                      - job_id: 6dc3f30a-58c2-4174-96a6-dc18cf3c7776
                        job_type: import/project_media
                        job_state: stopped
                        created_at: '2025-11-18T10:30:00Z'
                        stopped_at: '2025-11-18T10:35:00Z'
                        drive_id: c9c5c47e-158a-49f7-846b-4f6ee2a229a2
                        project_id: 9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
                        project_url: >-
                          https://web.descript.com/9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
                        result:
                          status: success
                          media_status:
                            Misc/intro.mp4:
                              status: success
                              duration_seconds: 10.5
                          media_seconds_used: 11
                      - job_id: a1b2c3d4-5678-90ab-cdef-1234567890ab
                        job_type: agent
                        job_state: running
                        created_at: '2025-11-18T11:00:00Z'
                        drive_id: c9c5c47e-158a-49f7-846b-4f6ee2a229a2
                        project_id: 9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
                        project_url: >-
                          https://web.descript.com/9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
                        progress:
                          label: Applying Studio Sound to clip 2...
                          last_update_at: '2025-11-18T11:01:00Z'
                    pagination:
                      next_cursor: YTFiMmMzZDQtNTY3OC05MGFiLWNkZWYtMTIzNDU2Nzg5MGFi
        '400':
          description: Bad request - `project_id` is not a valid UUID
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error400'
        '401':
          description: Unauthorized - invalid or missing authentication token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error401'
              examples:
                unauthorized:
                  summary: Missing authentication token
                  value:
                    error: unauthorized
                    message: Missing or invalid authentication token
        '429':
          $ref: '#/components/responses/Error429Response'
      security:
        - bearerAuth: []
components:
  schemas:
    JobStatus:
      oneOf:
        - $ref: '#/components/schemas/ImportJobStatus'
        - $ref: '#/components/schemas/AgentJobStatus'
        - $ref: '#/components/schemas/PublishJobStatus'
      discriminator:
        propertyName: job_type
        mapping:
          import/project_media:
            $ref: '#/components/schemas/ImportJobStatus'
          agent:
            $ref: '#/components/schemas/AgentJobStatus'
          publish:
            $ref: '#/components/schemas/PublishJobStatus'
          export/timeline: '#/components/schemas/TimelineExportJobStatus'
      description: >
        Status of an async job. The response structure varies based on the job
        type.

        Use the `job_type` field to determine which fields will be present.
    Error400:
      type: object
      properties:
        error:
          type: string
          example: invalid_input
        message:
          type: string
          example: Invalid request body
      required:
        - error
        - message
    Error401:
      type: object
      properties:
        error:
          type: string
          example: unauthorized
        message:
          type: string
          example: Missing or invalid authentication token
      required:
        - error
        - message
    ImportJobStatus:
      type: object
      description: Status of an import job
      properties:
        job_id:
          type: string
          format: uuid
          description: Unique identifier for the job
          example: 6dc3f30a-58c2-4174-96a6-dc18cf3c7776
        job_type:
          type: string
          enum:
            - import/project_media
          description: Type of job
        job_state:
          type: string
          enum:
            - queued
            - running
            - stopped
            - cancelled
          description: |
            Current state of the job:
            - queued: Job is waiting to start
            - running: Job is actively processing
            - stopped: Job has finished (check result.status for outcome)
            - cancelled: Job was cancelled by user
          example: stopped
        created_at:
          type: string
          format: date-time
          description: When the job was created
          example: '2025-11-18T10:30:00Z'
        stopped_at:
          type: string
          format: date-time
          description: >-
            When the job stopped (only present when job_state is stopped or
            cancelled)
          example: '2025-11-18T10:35:00Z'
        drive_id:
          type: string
          format: uuid
          description: The drive ID
          example: c9c5c47e-158a-49f7-846b-4f6ee2a229a2
        project_id:
          type: string
          format: uuid
          description: The project ID
          example: 9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
        project_url:
          type: string
          format: uri
          description: >-
            URL to access the project in Descript web app. When a composition ID
            is available in the result, the URL includes a composition short ID
            suffix.
          example: https://web.descript.com/9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
        progress:
          type: object
          description: >-
            Progress information for the workflow (only present when job_state
            is running)
          properties:
            label:
              type: string
              description: Human-readable label describing the current action
              example: Importing media...
            percent:
              type: integer
              description: Percentage of the workflow that has been completed
              example: 50
            last_update_at:
              type: string
              format: date-time
              description: When the progress was last updated
              example: '2025-11-18T10:32:00Z'
          required:
            - label
        result:
          description: Job result (only present when job_state is stopped)
          oneOf:
            - $ref: '#/components/schemas/ImportSuccessResult'
            - $ref: '#/components/schemas/ImportErrorResult'
          discriminator:
            propertyName: status
            mapping:
              success:
                $ref: '#/components/schemas/ImportSuccessResult'
              partial:
                $ref: '#/components/schemas/ImportSuccessResult'
              error:
                $ref: '#/components/schemas/ImportErrorResult'
      required:
        - job_id
        - job_type
        - job_state
        - created_at
        - drive_id
        - project_id
        - project_url
    AgentJobStatus:
      type: object
      description: Status of an Agent edit job
      properties:
        job_id:
          type: string
          format: uuid
          description: Unique identifier for the job
          example: 6dc3f30a-58c2-4174-96a6-dc18cf3c7776
        job_type:
          type: string
          enum:
            - agent
          description: Type of job
          example: agent
        job_state:
          type: string
          enum:
            - queued
            - running
            - stopped
            - cancelled
          description: |
            Current state of the job:
            - queued: Job is waiting to start
            - running: Job is actively processing
            - stopped: Job has finished (check result.status for outcome)
            - cancelled: Job was cancelled by user
          example: stopped
        created_at:
          type: string
          format: date-time
          description: When the job was created
          example: '2025-11-18T10:30:00Z'
        stopped_at:
          type: string
          format: date-time
          description: >-
            When the job stopped (only present when job_state is stopped or
            cancelled)
          example: '2025-11-18T10:35:00Z'
        drive_id:
          type: string
          format: uuid
          description: The drive ID
          example: c9c5c47e-158a-49f7-846b-4f6ee2a229a2
        project_id:
          type: string
          format: uuid
          description: The project ID
          example: 9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
        project_url:
          type: string
          format: uri
          description: >-
            URL to access the project in Descript web app. When a composition ID
            is available in the result, the URL includes a composition short ID
            suffix.
          example: https://web.descript.com/9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
        progress:
          type: object
          description: >-
            Progress information for the workflow (only present when job_state
            is running)
          properties:
            label:
              type: string
              description: Human-readable label describing the current action
              example: Applying Studio Sound to clip 2...
            percent:
              type: integer
              description: Percentage of the workflow that has been completed
              example: 50
            last_update_at:
              type: string
              format: date-time
              description: When the progress was last updated
              example: '2025-11-18T10:32:00Z'
          required:
            - label
        result:
          description: Job result (only present when job_state is stopped)
          oneOf:
            - $ref: '#/components/schemas/AgentSuccessResult'
            - $ref: '#/components/schemas/AgentErrorResult'
          discriminator:
            propertyName: status
            mapping:
              success:
                $ref: '#/components/schemas/AgentSuccessResult'
              error:
                $ref: '#/components/schemas/AgentErrorResult'
      required:
        - job_id
        - job_type
        - job_state
        - created_at
        - drive_id
        - project_id
        - project_url
    PublishJobStatus:
      type: object
      description: Status of a publish job
      properties:
        job_id:
          type: string
          format: uuid
          description: Unique identifier for the job
          example: 6dc3f30a-58c2-4174-96a6-dc18cf3c7776
        job_type:
          type: string
          enum:
            - publish
          description: Type of job
        job_state:
          type: string
          enum:
            - queued
            - running
            - stopped
            - cancelled
          description: |
            Current state of the job:
            - queued: Job is waiting to start
            - running: Job is actively processing
            - stopped: Job has finished (check result.status for outcome)
            - cancelled: Job was cancelled by user
          example: stopped
        created_at:
          type: string
          format: date-time
          description: When the job was created
          example: '2025-11-18T10:30:00Z'
        stopped_at:
          type: string
          format: date-time
          description: >-
            When the job stopped (only present when job_state is stopped or
            cancelled)
          example: '2025-11-18T10:35:00Z'
        drive_id:
          type: string
          format: uuid
          description: The drive ID
          example: c9c5c47e-158a-49f7-846b-4f6ee2a229a2
        project_id:
          type: string
          format: uuid
          description: The project ID
          example: 9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
        project_url:
          type: string
          format: uri
          description: >-
            URL to access the project in Descript web app. When a composition ID
            is available in the result, the URL includes a composition short ID
            suffix.
          example: https://web.descript.com/9f36ee32-5a2c-47e7-b1a3-94991d3e3ddb
        progress:
          type: object
          description: >-
            Progress information for the workflow (only present when job_state
            is running)
          properties:
            label:
              type: string
              description: Human-readable label describing the current action
              example: Exporting composition...
            percent:
              type: integer
              description: Percentage of the workflow that has been completed
              example: 50
            last_update_at:
              type: string
              format: date-time
              description: When the progress was last updated
              example: '2025-11-18T10:32:00Z'
            composition_id:
              type: string
              description: Composition being published (present when known)
              example: 39677a40-1c43-4c36-8449-46cfbc4de2b5
            share_url:
              type: string
              format: uri
              description: Share URL when available before the job completes
              example: https://share.descript.com/view/abc123
          required:
            - label
        result:
          description: Job result (only present when job_state is stopped)
          oneOf:
            - $ref: '#/components/schemas/PublishSuccessResult'
            - $ref: '#/components/schemas/PublishErrorResult'
          discriminator:
            propertyName: status
            mapping:
              success:
                $ref: '#/components/schemas/PublishSuccessResult'
              error:
                $ref: '#/components/schemas/PublishErrorResult'
      required:
        - job_id
        - job_type
        - job_state
        - created_at
        - drive_id
        - project_id
        - project_url
    Error429:
      description: >
        Rate limit exceeded response. When this error is returned, the response
        includes headers

        to help you implement proper retry logic:

        - `Retry-After`: Number of seconds to wait before retrying

        - `X-RateLimit-Remaining`: Requests remaining in current window

        - `X-RateLimit-Consumed`: Requests consumed in current window
      type: object
      properties:
        error:
          type: string
          description: Error code indicating rate limit was exceeded
          example: rate_limit_exceeded
        message:
          type: string
          description: Human-readable error message
          example: Too many requests
      required:
        - error
        - message
    ImportSuccessResult:
      type: object
      title: ImportSuccessResult
      description: Result when media was imported (fully or partially)
      properties:
        status:
          type: string
          enum:
            - success
            - partial
          description: |
            - success: All media imported successfully
            - partial: Some media imported successfully, some failed
          example: success
        media_status:
          type: object
          description: |
            Status of each media item in the import.
            Keys are the media reference IDs from the request.
          additionalProperties:
            type: object
            description: Status information for a single media import
            properties:
              status:
                type: string
                enum:
                  - success
                  - failed
                description: Status of this individual media import
              duration_seconds:
                type: number
                format: float
                description: >-
                  Duration of the imported media in seconds (only present for
                  successful imports)
                example: 125.5
              error_message:
                type: string
                description: >-
                  Error message if the import failed (only present for failed
                  imports)
                example: URL is not accessible or does not support Range requests
            required:
              - status
          example:
            Misc/intro.mp4:
              status: success
              duration_seconds: 10.5
            demo.mp4:
              status: success
              duration_seconds: 125
        media_seconds_used:
          type: integer
          description: Total media seconds consumed by this import
          example: 75
        created_compositions:
          type: array
          description: Compositions created during import
          items:
            type: object
            properties:
              id:
                type: string
                example: 0daabc7a-437a-43eb-b04b-b398d502f393
              name:
                type: string
                example: Rough Cut
      required:
        - status
        - media_status
        - media_seconds_used
    ImportErrorResult:
      type: object
      title: ImportErrorResult
      description: Result when job failed completely
      properties:
        status:
          type: string
          enum:
            - error
          description: Job failed completely
          example: error
        error_message:
          type: string
          description: Human-readable error message
          example: Failed to import media files
        error_code:
          type: string
          description: Machine-readable error code
          example: import_failed
      required:
        - status
        - error_message
    AgentSuccessResult:
      type: object
      title: AgentSuccessResult
      description: Result when Agent edit completed successfully
      properties:
        status:
          type: string
          enum:
            - success
          description: Indicates successful completion
          example: success
        agent_response:
          type: string
          description: AI response describing what was done
          example: I added Studio Sound to all 3 clips in your composition
        project_changed:
          type: boolean
          description: Whether the agent made modifications to the project
          example: true
        media_seconds_used:
          type: integer
          description: Media minutes (in seconds) consumed by this operation
          example: 34
        ai_credits_used:
          type: integer
          description: AI credits consumed by this operation
          example: 5
        resolved_model:
          type: string
          description: >
            Model reported for this job: the canonical id for an explicit model
            or

            alias (e.g. `claude-opus-4.8` for `claude-opus`), `auto` for an
            `auto`

            request, or `inherited` when a resume keeps the conversation's
            model.

            Present on jobs submitted via the public API after the model-aliases

            launch; older jobs may omit it.
          example: claude-opus-4.8
        conversation_id:
          type: string
          format: uuid
          description: >
            Conversation ID for this agent session. Pass this value as
            `conversation_id` in a

            subsequent [POST /jobs/agent](#operation/agentEditJob) request to
            continue the conversation.
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
      required:
        - status
        - agent_response
        - project_changed
    AgentErrorResult:
      type: object
      title: AgentErrorResult
      description: Result when Agent edit failed
      properties:
        status:
          type: string
          enum:
            - error
          description: Indicates the job failed
          example: error
        error_message:
          type: string
          description: Human-readable error message
          example: AI agent failed to process the request
        error_code:
          type: string
          description: Machine-readable error code
          example: agent_execution_failed
        resolved_model:
          type: string
          description: >
            Model reported for this job: the canonical id for an explicit model
            or

            alias, `auto` for an `auto` request, or `inherited` when a resume
            keeps

            the conversation's model. Present on jobs submitted via the public
            API

            after the model-aliases launch; older jobs may omit it.
          example: claude-opus-4.8
        conversation_id:
          type: string
          format: uuid
          description: >
            Conversation ID for this agent session, if one was created before
            the error occurred.
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
      required:
        - status
        - error_message
    PublishSuccessResult:
      type: object
      description: Result when publish completed successfully
      properties:
        status:
          type: string
          enum:
            - success
          description: Indicates successful completion
        composition_id:
          type: string
          description: Identifier of the published composition
          example: 39677a40-1c43-4c36-8449-46cfbc4de2b5
        share_url:
          type: string
          format: uri
          description: Public URL to view the published content
          example: https://share.descript.com/view/abc123
        media_type:
          type: string
          enum:
            - Video
            - Audio
          description: >
            The media type the composition was actually published as. For an
            audio-only composition published with the default Video request,
            this is Audio.
          example: Audio
        download_url:
          type: string
          format: uri
          description: >
            Time-limited signed URL to download the original published media
            file. Present when the job completed successfully and signing
            succeeded.
          example: https://storage.googleapis.com/bucket/object?X-Goog-Signature=...
        download_url_expires_at:
          type: string
          format: date-time
          description: ISO 8601 time when download_url expires (if download_url is set)
      required:
        - status
        - composition_id
        - share_url
    PublishErrorResult:
      type: object
      description: Result when publish failed
      properties:
        status:
          type: string
          enum:
            - error
          description: Indicates the publish job failed
        error_message:
          type: string
          description: Human-readable error message
          example: Export failed during render
      required:
        - status
        - error_message
  responses:
    Error429Response:
      description: |
        Too many requests - rate limit exceeded.
        Use the `Retry-After` header to determine when to retry.
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request
          schema:
            type: integer
          example: 30
        X-RateLimit-Remaining:
          description: Number of requests remaining in the current rate limit window
          schema:
            type: integer
          example: 0
        X-RateLimit-Consumed:
          description: Number of requests consumed in the current rate limit window
          schema:
            type: integer
          example: 100
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error429'
          examples:
            rate_limit:
              summary: Rate limit exceeded
              value:
                error: rate_limit_exceeded
                message: Too many requests. Please try again later.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Personal API token created in Descript Settings → API Tokens. See the
        Authentication section for details.

````

## Related topics

- [Connect Descript to Zapier](/api-and-mcp/zapier.md)
- [Descript API](/api-and-mcp/api.md)
- [Descript on Raycast](/account-and-app-settings/descript-on-raycast.md)
- [Call the API directly](/api-and-mcp/other-endpoints.md)
- [Manage your "do not translate" list](/repurpose/do-not-translate.md)
