> ## Documentation Index
> Fetch the complete documentation index at: https://api-tools.memories.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Download Task Result

> Download completed screenplay extraction results as a zip file

<Info>
  **Product**: Visual Agents
  **Use case**: Managed endpoints powering Memories.ai's open-source video search and editing agents (queries, video clipping/editing, screenplay extraction)
  **Host**: `https://mavi-backend.memories.ai/serve/api/v2`
  **Auth**: `Authorization: sk-mavi-...` (no `Bearer` prefix)
</Info>

This endpoint downloads all output files from a completed screenplay extraction task as a single zip archive. The zip contains storyboard files, transcript JSONs, namelist, and/or merged XLSX based on the configuration used when submitting the task.

<Note>
  **Pricing:**

  * \$0.12/1GB download (based on total original file sizes, not compressed zip size)
</Note>

**Response Behavior:**

* ✅ **Success**: Returns **zip file stream** (binary data) — browser **automatically downloads to local storage**
* ❌ **Error**: Returns **JSON error** — use `json()` to parse error message

**Key Points:**

* Success response is a **file** (binary data), NOT JSON
* The zip filename is `{task_id}.zip`
* Error response is **JSON** with error details
* Task must be in `completed` status, otherwise an error is returned
* Check response status before deciding how to handle the response

### Code Examples

<CodeGroup>
  ```javascript fetch theme={null}
  const BASE_URL = "https://mavi-backend.memories.ai/serve/api/v2";
  const API_KEY = "sk-mavi-...";
  const fs = require('fs');

  const taskId = "ros-sd-20260313-a3f8c2b1";
  const response = await fetch(`${BASE_URL}/screenplay/tasks/${taskId}/download`, {
    method: 'GET',
    headers: {
      'Authorization': API_KEY
    }
  });

  if (response.ok) {
    // Success: save as zip file
    const buffer = await response.arrayBuffer();
    fs.writeFileSync(`${taskId}.zip`, Buffer.from(buffer));
    console.log(`Downloaded ${taskId}.zip`);
  } else {
    // Error: parse JSON
    const error = await response.json();
    console.error('Download failed:', error);
  }
  ```

  ```javascript axios theme={null}
  import axios from 'axios';
  import fs from 'fs';

  const BASE_URL = "https://mavi-backend.memories.ai/serve/api/v2";
  const API_KEY = "sk-mavi-...";

  const taskId = "ros-sd-20260313-a3f8c2b1";
  try {
    const response = await axios.get(`${BASE_URL}/screenplay/tasks/${taskId}/download`, {
      headers: {
        'Authorization': API_KEY
      },
      responseType: 'arraybuffer'
    });

    fs.writeFileSync(`${taskId}.zip`, response.data);
    console.log(`Downloaded ${taskId}.zip`);
  } catch (error) {
    console.error('Download failed:', error.response?.data);
  }
  ```

  ```python Python theme={null}
  import requests

  BASE_URL = "https://mavi-backend.memories.ai/serve/api/v2"
  API_KEY = "sk-mavi-..."
  HEADERS = {
      "Authorization": f"{API_KEY}"
  }

  def download_screenplay_result(task_id):
      url = f"{BASE_URL}/screenplay/tasks/{task_id}/download"
      response = requests.get(url, headers=HEADERS, stream=True)

      if response.status_code == 200:
          filename = f"{task_id}.zip"
          with open(filename, 'wb') as f:
              for chunk in response.iter_content(chunk_size=8192):
                  f.write(chunk)
          print(f"Downloaded {filename}")
      else:
          print(f"Download failed: {response.json()}")

  # Usage example
  download_screenplay_result("ros-sd-20260313-a3f8c2b1")
  ```
</CodeGroup>

### Path Parameters

| Parameter | Type   | Required | Description                                |
| --------- | ------ | -------- | ------------------------------------------ |
| task\_id  | string | Yes      | The screenplay task ID of a completed task |

### Response

On success, returns a binary zip file stream with the following headers:

| Header              | Value                                  |
| ------------------- | -------------------------------------- |
| Content-Type        | `application/zip`                      |
| Content-Disposition | `attachment; filename="{task_id}.zip"` |

### Zip File Contents

The zip archive contains the following files based on your task configuration:

| Config Flag                | Files Included                                            | Description                                                                   |
| -------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `require_json: true`       | `*_transcript.json`, `*_storyboard.json`, `namelist.json` | Per-episode transcript and storyboard JSONs, plus a global character namelist |
| `require_xlsx: true`       | `*.xlsx` (per episode)                                    | Per-episode storyboard spreadsheets                                           |
| `require_merge_xlsx: true` | `merged.xlsx`                                             | Single merged spreadsheet combining all episodes                              |

### Error Responses

| Scenario             | Error Message                                                                     |
| -------------------- | --------------------------------------------------------------------------------- |
| Task not found       | `"Task not found for id: {task_id}"`                                              |
| Task not completed   | `"Task is not completed yet, current status: {status}"`                           |
| No result data       | `"No result data available for this task."`                                       |
| No files found       | `"No downloadable files found for this task."`                                    |
| Insufficient balance | `"Insufficient balance to download the resource. Please recharge and try again."` |

### Notes

* The task must be in `completed` status — check with [Get Task Status](/visual-agents/screenplay/get-task-status) first
* Download cost is calculated based on the **sum of all individual file sizes** (original sizes, not compressed)
* Files with duplicate names are automatically renamed with a numeric suffix (e.g., `file.json`, `file_1.json`)
* The zip is streamed directly — no intermediate storage is used
