curl -X POST "https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete" \
-H "x-api-key: your_api_key_here"
const response = await fetch(
"https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete",
{ method: "POST", headers: { "x-api-key": process.env.HOOKED_API_KEY } }
);
const { data } = await response.json();
console.log(data.status, data.durationSeconds);
import os
import requests
response = requests.post(
"https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete",
headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
)
print(response.json()["data"]["status"])
{
"success": true,
"message": "Upload completed",
"data": {
"id": "cm4x9s8u60009ab12kl56mn90",
"name": "demo.mp4",
"type": "video",
"status": "COMPLETED",
"error": null,
"url": "https://files.hooked.so/team/public/demo--fid--9c1d.mp4",
"thumbnail": null,
"durationSeconds": 12.4,
"size": 8388608,
"aspectRatio": null,
"isAIGenerated": false,
"createdAt": "2026-10-01T09:30:00.000Z"
}
}
{
"success": false,
"message": "The file was not uploaded"
}
{
"success": false,
"message": "The upload failed; start a new one"
}
Media library
Complete Upload
Confirm an upload once the file is PUT, and make the media ready
POST
/
v1
/
media
/
{mediaId}
/
complete
curl -X POST "https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete" \
-H "x-api-key: your_api_key_here"
const response = await fetch(
"https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete",
{ method: "POST", headers: { "x-api-key": process.env.HOOKED_API_KEY } }
);
const { data } = await response.json();
console.log(data.status, data.durationSeconds);
import os
import requests
response = requests.post(
"https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete",
headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
)
print(response.json()["data"]["status"])
{
"success": true,
"message": "Upload completed",
"data": {
"id": "cm4x9s8u60009ab12kl56mn90",
"name": "demo.mp4",
"type": "video",
"status": "COMPLETED",
"error": null,
"url": "https://files.hooked.so/team/public/demo--fid--9c1d.mp4",
"thumbnail": null,
"durationSeconds": 12.4,
"size": 8388608,
"aspectRatio": null,
"isAIGenerated": false,
"createdAt": "2026-10-01T09:30:00.000Z"
}
}
{
"success": false,
"message": "The file was not uploaded"
}
{
"success": false,
"message": "The upload failed; start a new one"
}
Overview
The last step of Upload Media. Call it after the PUT touploadUrl succeeded; it takes no body. Hooked checks that storage really holds the file and reads its real size, counts it against your plan’s storage, reads a video’s length and starts its thumbnail. The media is then COMPLETED and its id works in any create endpoint.
- The file is not there yet:
400 The file was not uploaded. The media staysPENDING; PUT the file and call again. - The file is over 100 MB, or its real size does not fit your storage: the file is deleted and the media becomes
FAILED. Start a new upload. - Calling it again on a
COMPLETEDmedia answers200with the same media; nothing is counted twice.
curl -X POST "https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete" \
-H "x-api-key: your_api_key_here"
const response = await fetch(
"https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete",
{ method: "POST", headers: { "x-api-key": process.env.HOOKED_API_KEY } }
);
const { data } = await response.json();
console.log(data.status, data.durationSeconds);
import os
import requests
response = requests.post(
"https://api.hooked.so/v1/media/cm4x9s8u60009ab12kl56mn90/complete",
headers={"x-api-key": os.environ["HOOKED_API_KEY"]},
)
print(response.json()["data"]["status"])
{
"success": true,
"message": "Upload completed",
"data": {
"id": "cm4x9s8u60009ab12kl56mn90",
"name": "demo.mp4",
"type": "video",
"status": "COMPLETED",
"error": null,
"url": "https://files.hooked.so/team/public/demo--fid--9c1d.mp4",
"thumbnail": null,
"durationSeconds": 12.4,
"size": 8388608,
"aspectRatio": null,
"isAIGenerated": false,
"createdAt": "2026-10-01T09:30:00.000Z"
}
}
{
"success": false,
"message": "The file was not uploaded"
}
{
"success": false,
"message": "The upload failed; start a new one"
}
Errors
| Status | Message | Cause |
|---|---|---|
| 400 | The file was not uploaded | Nothing at the upload URL yet. PUT the file, then call again. |
| 400 | The file is larger than 100 MB | The uploaded file is too large. It was deleted; the media is FAILED. |
| 401 | code: "not_authenticated" | Missing or invalid x-api-key. |
| 403 | Insufficient storage. ... | The real size does not fit your plan’s storage. The file was deleted; the media is FAILED. |
| 404 | Media not found | No such media in your library. |
| 409 | The upload failed; start a new one | The media is FAILED. |
| 409 | Media is not a pending upload (status ...) | The media did not come from Upload Media (an import, a generated file). |
Authorizations
Path Parameters
The mediaId from Upload Media.