Upload an asset
October 12, 2026
Table of contents
Upload an image, a video or an audio file to one of your Muse accounts and get an assetId for it. The file is sent as the raw request body with its MIME type in the Content-Type header (no multipart, no JSON).
The file is written into the Muse workspace of the account, where the muse.ai app keeps its files too. Nothing is stored at useapi.net. Pass the assetId as image_N, video_N or audio_N to POST /jobs/image or POST /jobs/video. A file Muse made needs no upload: its assetId from the job’s result.assets[] works the same way.
The assetId names your API token, the account and the file, and only jobs on that account can use it. To use several uploads in one job, upload them all to the same account with email. The same file uploaded to the same account again gets the same assetId and is not written twice. An upload takes no maxJobs slot and uses no Muse allowance.
https://api.useapi.net/v1/muse/assets?email=
Request Headers
Authorization: Bearer {API token}
Content-Type: image/jpeg # the file's MIME type, see the list below
Content-Length: 316641 # most HTTP clients set it for you
API tokenis required, see Setup useapi.net for details.Content-Typeis required, the file’s MIME type.
Supported values:image/jpeg,image/png,image/webp,video/mp4,video/quicktime,video/webm,audio/mpeg,audio/wav,audio/x-wav,audio/mp4,audio/x-m4a,audio/ogg.Content-Lengthis required, the file size in bytes. A request without it answers411.
The request body is the file’s raw bytes, from 1 byte to 52,428,800 bytes (50 MB). Muse takes a file in 1 MB pieces, so an upload runs at about 1 MB per second: a 50 MB file takes about a minute.
Query Parameters
emailis optional, the account to upload to. When omitted, a healthy account with allowance left is picked at random. URL-encode it.
Responses
-
{ "assetId": "user:12345-email:6578616d706c6540676d61696c2e636f6d-image:d62d3099acbf50a46bc2155a0d18e79dc371ecdc6e4d28a072aa5bbd070bcfd3.jpg", "email": "[email protected]", "type": "image", "mime": "image/jpeg", "bytes": 316641 } -
400 Bad Request — an unsupported
Content-Type, an empty body, or no Muse account added yet.{ "error": "Content-Type must be one of image/jpeg, image/png, image/webp, video/mp4, video/quicktime, video/webm, audio/mpeg, audio/wav, audio/x-wav, audio/mp4, audio/x-m4a, audio/ogg (raw file bytes in the body)", "code": 400 } -
Invalid API token.
{ "error": "useapi.net ⁝ Unauthorized", "code": 401 } -
404 Not Found — the account named by
emailis not added.{ "error": "Account [email protected] is not configured", "code": 404 } -
411 Length Required — the request has no
Content-Lengthheader, for example a streamed (chunked) body.{ "error": "Content-Length is required (send the file as the raw request body)", "code": 411 } -
412 Precondition Failed — the account’s weekly Muse allowance is used up (or every account’s, without
email).{ "error": "All 2 healthy accounts have used up their Muse allowance. GET /accounts/{email} re-reads it", "code": 412 } -
413 Content Too Large — the file is larger than 52,428,800 bytes (50 MB).
{ "error": "File must be at most 52428800 bytes", "code": 413 } -
502 Bad Gateway — Muse did not store the file. Retry.
{ "error": "Muse did not store the file (…), please retry", "code": 502 } -
503 Service Unavailable — Muse could not be reached, or the same file is being uploaded to the account by another request. Retry shortly.
{ "error": "Could not connect to the Muse workspace of account [email protected] (…), please retry shortly", "code": 503 } -
596 Account Error
The account needs your attention, and it is paused until you add it again. You receive an email when this happens. There are two causes.
Meta asks for a security check on the account. Sign in once at muse.ai in a browser, complete the check, then add the account again with POST /accounts using the same email and password. The API keeps using its session, so no new sign-in is needed.
{ "error": "Account [email protected]: Meta asks for a security check on account [email protected] (\"This account must complete a security checkpoint on the web\"). Sign in once at https://muse.ai in a browser, complete the check, then add the account again with POST /accounts", "code": 596 }Or Muse refused to sign the account in again when its session needed renewing, most often because the password was changed. Add the account again with the current password.
{ "error": "Account [email protected]: Muse refused to sign in account [email protected] (…). Update its password with POST /accounts, or sign in at https://muse.ai to clear the block, then re-add it", "code": 596 }
Model
{ // TypeScript, all fields are optional
assetId: string // user:<id>-email:<hex of the email>-<image|video|audio>:<sha256>.<ext>
email: string // the account the file was uploaded to
type: 'image' | 'video' | 'audio'
mime: string // the Content-Type you sent
bytes: number // the file size
error?: string // errors only
code?: number // errors only
}
Examples
-
curl -X POST "https://api.useapi.net/v1/muse/assets?email=example%40gmail.com" \ -H "Authorization: Bearer …" \ -H "Content-Type: image/jpeg" \ --data-binary @rider.jpg -
import fs from "fs"; const token = "API token"; const email = "Previously added account email"; const apiUrl = `https://api.useapi.net/v1/muse/assets?email=${encodeURIComponent(email)}`; const response = await fetch(apiUrl, { method: "POST", headers: { "Authorization": `Bearer ${token}`, "Content-Type": "image/jpeg", }, body: fs.readFileSync("rider.jpg") }); const result = await response.json(); console.log("response", {response, result}); -
import requests token = "API token" email = "Previously added account email" apiUrl = "https://api.useapi.net/v1/muse/assets" headers = { "Authorization" : f"Bearer {token}", "Content-Type": "image/jpeg" } with open("rider.jpg", "rb") as f: response = requests.post(apiUrl, headers=headers, params={"email": email}, data=f.read()) print(response, response.json())