Descript API

Download OpenAPI specification:

License: Proprietary

Descript API documentation.

Getting started

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.

The Descript API lets you programmatically create projects, import media, and edit your projects — all without opening the app.

To learn more, visit descript.com/api.

Create an API token

  1. In Descript, open Settings and select API tokens from the sidebar. Then click Create token.

Navigate to Settings > API tokens and click Create token

  1. Give your token a name and select the Drive it should be associated with. Click Create token.
Name your token and select a Drive
  1. 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.
Copy and save your API token

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.

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

Import media into a new project

You can create a new project, import media, and place the media into a composition all in one API request using the import endpoint. This step also transcribes and processes the media so that it's ready for you or the agent to edit.

To 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.

Importing and processing is an asynchronous job, so the response payload will contain a job_id for you to query the status of the job 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.

Request

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 First Video",
    "add_media": {
      "demo.mp4": {
        "url": "https://test-files.descriptapi.com/demo_video.mp4"
      }
    },
    "add_compositions": [
      {
        "name": "Demo Video",
        "clips": [
          { "media": "demo.mp4" }
        ]
      }
    ]
  }'

Response

{
  "job_id": "project-media-import-9d635d5b",
  "drive_id": "c9c5c47e",
  "project_id": "e2f89ce6",
  "project_url": "https://web.descript.com/e2f89ce6"
}

Check for import completion

Poll the job status endpoint 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.

You 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.

Request

curl https://descriptapi.com/v1/jobs/project-media-import-9d635d5b \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Response

{
  "job_id": "project-media-import-9d635d5b",
  "job_type": "import/project_media",
  "job_state": "stopped",
  "project_id": "e2f89ce6",
  "project_url": "https://web.descript.com/e2f89ce6",
  "result": {
    "status": "success",
    "media_status": {
      "main.mp4": {
        "status": "success",
        "duration_seconds": 69.477006
      }
    },
    "created_compositions": [
      { "id": "f8e5088a-4d53-4aab-9d4f-c6624b7d7622", "name": "Demo Video" }
    ]
  }
}

Prompt for edits with Agent Underlord

Once your media is imported, you can use the agent edit endpoint 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.

Editing can take some time, so the response also returns a job_id that you can use to check the status of the job. 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.

Request

curl -X POST https://descriptapi.com/v1/jobs/agent \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "project_id": "e2f89ce6",
    "prompt": "Add studio sound and captions"
  }'

Response

{
  "job_id": "project-agent-edit-e2f89ce6",
  "drive_id": "c9c5c47e",
  "project_id": "e2f89ce6",
  "project_url": "https://web.descript.com/e2f89ce6"
}

Wait for the agent to complete its job

Poll the job status endpoint 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.

Request

curl https://descriptapi.com/v1/jobs/project-agent-edit-e2f89ce6 \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Once 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.

Response

{
    "job_id":"project-agent-edit-e2f89ce6",
    "job_type":"agent",
  "project_id":"YOUR_PROJECT_ID",
    "project_url":"https://web.descript.com/e2f89ce6",
    "job_state":"stopped",
    "created_at":"2026-02-09T05:42:27.554Z",
    "stopped_at":"2026-02-09T05:43:15.296Z",
    "drive_id":"1df135a5-dc4a-4dc3-8f7d-681cfbe961e4",
    "result":{
        "status":"success",
    "agent_response":"Done! I've applied Studio Sound to enhance your audio quality and added classic karaoke-style captions to your video.",
        "project_changed":true,
        "media_seconds_used":0,
        "ai_credits_used":32
  }
}

Using the CLI

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 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.

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

Next, configure the CLI with your API key.

descript-api config set api-key

Setting up the CLI

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.

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

Interactive CLI import

Use the agent

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

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!

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.

API Endpoints

Import media, edit projects with AI, and query jobs and projects.

Import media and sequences

Import media files into a new or existing project and create compositions.

This endpoint can:

  • Create a new project if project_id is not provided
  • Import media files from URLs
  • Create multitrack sequences
  • Create compositions (timelines) from existing or new media in the project
  • Trigger transcription and other background processing tasks

Media URL requirements

  • URLs must be accessible by Descript servers
  • URLs must support HTTP Range requests
  • Recommended to sign URLs for 12-48 hours to reduce chance of failure
  • Supported file types

Async Operations

Imports run in the background and return a job_id. Monitor progress via the GET /jobs/{job_id} endpoint.

Dynamic webhook

If callback_url is provided, Descript will POST the job status to that URL when the job finishes (successfully or not).

The payload will match the format returned by GET /jobs/{job_id}.

Authorizations:
bearerAuth
Request Body schema: application/json
required

Media import and project creation request

project_id
string <uuid>

[Work in progress] Importing into an existing project is not yet supported. Currently, a new project is always created.

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.

project_name
string

Name for the new project. Only used when project_id is not provided.

team_access
string
Default: "none"
Enum: "edit" "comment" "view" "none"

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)
object

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).

Array of objects

Optional list of compositions to create in the project

callback_url
string <uri>

Optional webhook URL to call when the job completes or fails. Descript will POST the job status (same format as GET /jobs/{job_id}) to this URL.

Responses

Request samples

Content type
application/json
Example

Most common use case for seeding a project with a simple composition

{}

Response samples

Content type
application/json
{}

Agent edit

Use a background agent to create and edit projects using a natural language prompt.

  • Edit existing project: Provide a project_id to edit an existing project
  • Create new project: Provide a project_name instead of project_id to create a new project

Common use cases

  • Create new content: "create a 30-second video about cooking tips"
  • Apply audio effects: "add studio sound to every clip"
  • Remove filler words: "remove all filler words from the transcript"
  • Create highlights: "create a 30-second highlight reel"
  • Content editing: "remove the section from 1:30 to 2:15"

Async Operations

Agent edits run in the background and return a job_id. Monitor progress via the GET /jobs/{job_id} endpoint.

Dynamic webhook

If callback_url is provided, Descript will POST the job status to that URL when the job completes or fails. The payload will match the format returned by GET /jobs/{job_id}.

Authorizations:
bearerAuth
Request Body schema: application/json
required

AI agent request

project_id
string <uuid>

The ID of an existing project to edit. Mutually exclusive with project_name.

project_name
string

Name for creating a new project. Mutually exclusive with project_id.

composition_id
string <uuid>

[Work in progress] This property is accepted but not yet functional. It will be ignored.

Optional composition ID within the project to edit.

model
string

AI model to use for editing. Defaults to the default model.

prompt
required
string

Natural language instruction for the agent to execute. Examples: "add studio sound to every clip", "remove all filler words", "create a 30-second highlight reel"

team_access
string
Enum: "edit" "comment" "view" "none"

Access level for team members when creating a new project. Only applicable when project_name is provided (not when using project_id). Defaults to none if not specified.

callback_url
string <uri>

Optional webhook URL to call when the job completes or fails. Descript will POST the job status (same format as GET /jobs/{job_id}) to this URL.

Responses

Request samples

Content type
application/json
Example
{
  • "project_name": "Cooking Tips Video",
  • "prompt": "create a 30-second video about cooking tips with background music"
}

Response samples

Content type
application/json
{}

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)
Authorizations:
bearerAuth
query Parameters
project_id
string <uuid>

Filter by project ID

type
string
Enum: "import/project_media" "agent"

Filter by job type

cursor
string

Cursor for the next page of results, obtained from pagination.next_cursor in a previous response

limit
integer [ 1 .. 100 ]
Default: 20

Number of items per page (1-100). Defaults to 20.

created_after
string <date-time>

Filter jobs created after this timestamp (ISO 8601). Default: 7 days ago. Oldest allowed: 30 days ago.

created_before
string <date-time>

Filter jobs created before this timestamp (ISO 8601). Default: now.

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "pagination": {
    }
}

Get job status

Retrieve the status of any job.

The response format varies based on job type and includes type-specific fields.

Authorizations:
bearerAuth
path Parameters
job_id
required
string <uuid>

The job ID

Responses

Response samples

Content type
application/json
Example
{
  • "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",
  • "result": {
    }
}

Cancel job

Cancel a running job.

Authorizations:
bearerAuth
path Parameters
job_id
required
string <uuid>

The job ID

Responses

Response samples

Content type
application/json
{
  • "error": "unauthorized",
  • "message": "Missing or invalid authentication token"
}

Check API status

Work in progress — This endpoint is not yet available and will return an error if called.

Check API availability and validate authentication token.

This endpoint can be used to:

  • Verify that your authentication token is valid
  • Check API connectivity without performing any heavy operations

Returns a success response if the token is valid, or a 401 error if the token is invalid or missing.

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "status": "ok"
}

Authentication

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 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

curl -H "Authorization: Bearer YOUR_API_TOKEN" https://descriptapi.com/v1/status

Rate Limiting

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.

Edit in Descript

Note: The Edit in Descript integration requires contacting Descript for access. Reach out to us 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.

Create Import URL

Create an Import URL by sending a Project schema to Descript API from your service's backend.

Import Schema

Our import schemas are specified as a minimal JSON list of files which is detailed in full at the bottom of this section. At it's smallest, the request body looks like:

{
  "partner_drive_id": "162c61d1-6ced-4b25-a622-7dba922983ee",
  "project_schema": {
    "schema_version": "1.0.0",
    "files": [{"uri": "https://descriptusercontent.com/jane.wav?signature=d182bca64bf94a1483d2fd16b579f955"}]
  }
}

File Access

The file paths provided in the schema need to either be public or pre-signed URIs with enough time before expiration for failures and retries, we suggest URIs that won't expire for 48 hours. We ask that the files have already been saved when the import link is generated to minimize cases where we're waiting for eventually consistent storage of files that will never be written. We will, however, wait for eventual consistency of the storage layer and retry fetching files before eventually timing out.

Files must be hosted on preapproved hosts as our import process has an allow list which it checks URIs against. Files will be requested with User-Agent: Descriptbot/1.0 (version may change) for tracking purposes.

Import links are no longer valid after a user imports their data once. Viewing an already used import link will not allow for importing again and will not provide access to a previously created Descript Project. Partners are able to generate a new import link at any time, regardless of if a previous import link has been used.

The API does not currently provide partners with a link to the Descript Project, though users will be redirected to it from Descript's web interface the first time they import files, and can always find the Project in Descript.

Import links expire after 3 hours and attempting to use an import link after the pre-signed links in the schema file have expired will result in an error, so we recommend generating the import link after the user has clicked the Edit in Descript button.

Supported media specification

We recommend sending the highest quality, uncompressed versions of files available to you. If you have multiple tracks, we recommend prioritizing sending us the full multi-track sequence over a combined file.

  • Audio: WAV, FLAC, AAC, MP3
  • Video: h264, HEVC (container: MOV, MP4)
Authorizations:
bearerAuth
Request Body schema: application/json
required

Edit in Descript schema POST body.

partner_drive_id
required
string <uuid>

The drive id associated with the auth token.

required
object

The Project schema

Responses

Request samples

Content type
application/json
{}

Response samples

Export from Descript

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 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" />

Get Published Project Metadata

Retrieve metadata for a published Descript project by its URL slug. This endpoint provides information about the published project including title, duration, publisher details, privacy settings, and subtitles.

This endpoint requires authentication using a personal token and is subject to rate limiting of 1000 requests per hour per user.

Authorizations:
bearerAuth
path Parameters
publishedProjectSlug
required
string

The unique URL slug identifying the published project

Responses

Response samples

Content type
application/json
{
  • "project_id": "12345678-1234-5678-1234-567812345678",
  • "publish_type": "video",
  • "privacy": "unlisted",
  • "metadata": {
    },
  • "subtitles": "WEBVTT\\n\\n00:00:00.000 --> 00:00:02.000\\nWelcome to my video"
}