Skip to main content

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.

Product: Visual Search Use case: Stream a stored resource directly from GCS using the bucket and blob pair returned by search / list / metadata endpoints Host: https://api.memories.ai/serve/api/v1 Auth: Authorization: sk-mavi-... (no Bearer prefix)
Download any stored resource by the bucket + blob pair returned in the response of other Visual Search endpoints (search results, list_videos, get_metadata, transcription, etc.). The response body is a binary file stream; errors are returned as JSON. This is functionally equivalent to Download Video but addresses the resource by its storage location directly, so it also works for keyframe images and any other resource whose bucket / blob is exposed by the API — not just the video file behind a video_no.
Pricing: Billed by bytes downloaded ($0.12 / GB), same model as Download Asset.

Prerequisites

Endpoint

GET /serve/api/v1/download?bucket=<bucket>&blob=<blob>

Authentication

Authorization: sk-mavi-...

Query Parameters

bucket
string
required
GCS bucket name carrying the resource (e.g. the bucket / video_bucket / keyframe_bucket from a previous response).
blob
string
required
GCS blob (object) path inside bucket. URL-encode any reserved characters (slashes inside the blob path are allowed and should not be encoded as %2F).

Code Examples

import requests

url = "https://api.memories.ai/serve/api/v1/download"
params = {
    "bucket": "mavi-resource",
    "blob": "VI625239098370850816.mp4",
}
headers = {"Authorization": "sk-mavi-..."}

resp = requests.get(url, params=params, headers=headers, stream=True)
content_type = resp.headers.get("Content-Type", "")

if "application/json" in content_type.lower():
    # Error path — the server returned a JSON error payload
    print(resp.json())
else:
    with open("video.mp4", "wb") as f:
        for chunk in resp.iter_content(chunk_size=8192):
            if chunk:
                f.write(chunk)
    print("Download complete")

Successful Response

On success, the server streams the file as binary content:
  • Status: 200
  • Content-Type: typically application/octet-stream or the original MIME type
  • Content-Disposition: attachment; filename="..." — the original filename
  • Body: binary content of the resource
The download uses HTTP chunked transfer encoding, so Content-Length is often absent. Don’t rely on it for progress bars — iterate over chunks instead.

Error Response (JSON)

Errors are returned as JSON instead of a binary stream. Branch on Content-Type rather than parsing message strings. Missing bucket:
{
    "code": "0001",
    "msg": "Bucket cannot be null or empty",
    "data": null,
    "success": false,
    "failed": true
}
Missing blob:
{
    "code": "0001",
    "msg": "Blob cannot be null or empty",
    "data": null,
    "success": false,
    "failed": true
}
Object not present in the bucket (wrong values, or resource already deleted):
{
    "code": "0001",
    "msg": "Resource does not exist",
    "data": null,
    "success": false,
    "failed": true
}
Out of balance (download is billed by bytes; if your account has insufficient balance the request is rejected before the stream starts):
{
    "code": "0001",
    "msg": "Insufficient balance to download the resource. Please recharge and try again.",
    "data": null,
    "success": false,
    "failed": true
}

Notes & Limits

  • Rate limiting: shares the per-account download rate limit with Download Video. Exceeding the limit returns “Request has exceeded the limit.” — see Rate limits.
  • Billing: charged by bytes downloaded, not by call count. The deduction happens before the stream is written; you will not be charged for Resource does not exist errors.
  • bucket / blob lifetime: the values can become invalid if the underlying video is deleted via Delete Video. Always be ready to handle the Resource does not exist error.
  • Use the right pair: when downloading a clip’s matched keyframe, use keyframe_bucket + keyframe_blob; when downloading the full video, use video_bucket + video_blob (or bucket + blob from get_metadata / list_videos).
  • Download Video — POST-by-video_no equivalent. Use this when you already have a video_no and want to skip resolving its bucket / blob first.
  • Download Asset — Visual Intelligence v2 equivalent, by asset_id.