curl "https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90" \
-H "x-api-key: your_api_key_here"
async function waitForMedia(mediaId) {
for (;;) {
const response = await fetch(`https://api.hooked.so/v1/media/${mediaId}`, {
headers: { "x-api-key": process.env.HOOKED_API_KEY },
});
const { data } = await response.json();
if (data.status === "COMPLETED") return data;
if (data.status === "FAILED") throw new Error(`Media ${mediaId} failed: ${data.error}`);
await new Promise((resolve) => setTimeout(resolve, 3000));
}
}
import os
import time
import requests
def wait_for_media(media_id):
while True:
response = requests.get(
f"https://api.hooked.so/v1/media/{media_id}",
headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
)
data = response.json()["data"]
if data["status"] == "COMPLETED":
return data
if data["status"] == "FAILED":
raise RuntimeError(f"Media {media_id} failed: {data['error']}")
time.sleep(3)
{
"success": true,
"message": "Media fetched successfully",
"data": {
"id": "cm4x9s8u60009ab12kl56mn90",
"name": "Demo clip",
"type": "video",
"status": "COMPLETED",
"error": null,
"url": "https://files.hooked.so/team/public/demo--fid--9c1d.mp4",
"thumbnail": "https://files.hooked.so/team/public/demo--fid--9c1d.jpg",
"durationSeconds": 12.4,
"size": 8388608,
"aspectRatio": "ratio_9_16",
"isAIGenerated": false,
"createdAt": "2026-10-01T09:30:00.000Z"
}
}
{
"success": false,
"message": "Media not found"
}
Media library
Get Media
One image or video of your media library and its state
GET
/
v1
/
media
/
{mediaId}
curl "https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90" \
-H "x-api-key: your_api_key_here"
async function waitForMedia(mediaId) {
for (;;) {
const response = await fetch(`https://api.hooked.so/v1/media/${mediaId}`, {
headers: { "x-api-key": process.env.HOOKED_API_KEY },
});
const { data } = await response.json();
if (data.status === "COMPLETED") return data;
if (data.status === "FAILED") throw new Error(`Media ${mediaId} failed: ${data.error}`);
await new Promise((resolve) => setTimeout(resolve, 3000));
}
}
import os
import time
import requests
def wait_for_media(media_id):
while True:
response = requests.get(
f"https://api.hooked.so/v1/media/{media_id}",
headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
)
data = response.json()["data"]
if data["status"] == "COMPLETED":
return data
if data["status"] == "FAILED":
raise RuntimeError(f"Media {media_id} failed: {data['error']}")
time.sleep(3)
{
"success": true,
"message": "Media fetched successfully",
"data": {
"id": "cm4x9s8u60009ab12kl56mn90",
"name": "Demo clip",
"type": "video",
"status": "COMPLETED",
"error": null,
"url": "https://files.hooked.so/team/public/demo--fid--9c1d.mp4",
"thumbnail": "https://files.hooked.so/team/public/demo--fid--9c1d.jpg",
"durationSeconds": 12.4,
"size": 8388608,
"aspectRatio": "ratio_9_16",
"isAIGenerated": false,
"createdAt": "2026-10-01T09:30:00.000Z"
}
}
{
"success": false,
"message": "Media not found"
}
Overview
Returns one image or video of your library. After Import Media from URL, poll it untilstatus is COMPLETED (pass the id to any create endpoint) or FAILED. Every few seconds is enough; a large video takes up to a couple of minutes. An import still running after 15 minutes reads as FAILED, so a poll loop always ends.
This call is free and safe to retry. url is an empty string until the media is COMPLETED. A FAILED media says why in error (null otherwise). Rather not poll? Pass a webhook when you import or generate: see media webhooks.
curl "https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90" \
-H "x-api-key: your_api_key_here"
async function waitForMedia(mediaId) {
for (;;) {
const response = await fetch(`https://api.hooked.so/v1/media/${mediaId}`, {
headers: { "x-api-key": process.env.HOOKED_API_KEY },
});
const { data } = await response.json();
if (data.status === "COMPLETED") return data;
if (data.status === "FAILED") throw new Error(`Media ${mediaId} failed: ${data.error}`);
await new Promise((resolve) => setTimeout(resolve, 3000));
}
}
import os
import time
import requests
def wait_for_media(media_id):
while True:
response = requests.get(
f"https://api.hooked.so/v1/media/{media_id}",
headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
)
data = response.json()["data"]
if data["status"] == "COMPLETED":
return data
if data["status"] == "FAILED":
raise RuntimeError(f"Media {media_id} failed: {data['error']}")
time.sleep(3)
{
"success": true,
"message": "Media fetched successfully",
"data": {
"id": "cm4x9s8u60009ab12kl56mn90",
"name": "Demo clip",
"type": "video",
"status": "COMPLETED",
"error": null,
"url": "https://files.hooked.so/team/public/demo--fid--9c1d.mp4",
"thumbnail": "https://files.hooked.so/team/public/demo--fid--9c1d.jpg",
"durationSeconds": 12.4,
"size": 8388608,
"aspectRatio": "ratio_9_16",
"isAIGenerated": false,
"createdAt": "2026-10-01T09:30:00.000Z"
}
}
{
"success": false,
"message": "Media not found"
}
Errors
| Status | When |
|---|---|
| 401 | Missing or invalid API key (code: "not_authenticated") |
| 403 | The team does not have the Hooked app product (code: "entitlement_required") |
| 404 | No such image or video in your library. Another team’s media, or an id that is not one, answers the same Media not found |
Authorizations
Path Parameters
The media id, from List Media, an import or an upload.