curl --request POST \
--url https://api.mage.space/v1/references \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Red coat",
"handle": "red-coat",
"kind": "outfit",
"image": "https://example.com/red-coat.jpg"
}
'import Mage from '@mage-space/sdk';
const mage = new Mage(); // reads MAGE_API_KEY
await mage.references.create({
name: 'Red coat',
handle: 'red-coat',
kind: 'outfit',
image: 'https://example.com/red-coat.jpg',
});
await mage.run('mango', { prompt: 'a figure wearing @red-coat in the snow' });from mage_space import Mage
mage = Mage() # reads MAGE_API_KEY
mage.references.create(
name="Red coat",
handle="red-coat",
kind="outfit",
image="https://example.com/red-coat.jpg",
)
mage.run("mango", {"prompt": "a figure wearing @red-coat in the snow"})const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Red coat',
handle: 'red-coat',
kind: 'outfit',
image: 'https://example.com/red-coat.jpg'
})
};
fetch('https://api.mage.space/v1/references', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "a81f0c5d-2e6b-4f93-b7c4-0d9e5a3c2f18",
"handle": "red-coat",
"name": "Red coat",
"kind": "outfit",
"description": null,
"image_url": "https://cdn3.mage.space/references/user/image/4c2d.jpg",
"audio_url": null,
"created_at": "2026-09-18T10:05:00.000Z"
}{
"error": {
"code": "invalid_request",
"message": "`name` is required."
}
}{
"error": {
"code": "unauthorized",
"message": "The API key is invalid or has been revoked."
}
}{
"error": {
"code": "payment_required",
"message": "The Mage API and MCP server need a successful payment on this account first: buy any Gem pack or start a plan at https://www.mage.space/gems, then retry. Signup bonus Gems work in the Mage app only."
}
}{
"error": {
"code": "forbidden",
"message": "This account cannot create characters or references."
}
}{
"error": {
"code": "handle_taken",
"message": "The handle `@ana` is taken. Choose another, or omit `handle` to derive one from the name.",
"handle": "ana"
}
}{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side. Retry, and contact support if it persists."
}
}Create reference
POST /v1/references saves a private image or audio reference and returns the handle a prompt mentions it by.
curl --request POST \
--url https://api.mage.space/v1/references \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Red coat",
"handle": "red-coat",
"kind": "outfit",
"image": "https://example.com/red-coat.jpg"
}
'import Mage from '@mage-space/sdk';
const mage = new Mage(); // reads MAGE_API_KEY
await mage.references.create({
name: 'Red coat',
handle: 'red-coat',
kind: 'outfit',
image: 'https://example.com/red-coat.jpg',
});
await mage.run('mango', { prompt: 'a figure wearing @red-coat in the snow' });from mage_space import Mage
mage = Mage() # reads MAGE_API_KEY
mage.references.create(
name="Red coat",
handle="red-coat",
kind="outfit",
image="https://example.com/red-coat.jpg",
)
mage.run("mango", {"prompt": "a figure wearing @red-coat in the snow"})const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Red coat',
handle: 'red-coat',
kind: 'outfit',
image: 'https://example.com/red-coat.jpg'
})
};
fetch('https://api.mage.space/v1/references', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "a81f0c5d-2e6b-4f93-b7c4-0d9e5a3c2f18",
"handle": "red-coat",
"name": "Red coat",
"kind": "outfit",
"description": null,
"image_url": "https://cdn3.mage.space/references/user/image/4c2d.jpg",
"audio_url": null,
"created_at": "2026-09-18T10:05:00.000Z"
}{
"error": {
"code": "invalid_request",
"message": "`name` is required."
}
}{
"error": {
"code": "unauthorized",
"message": "The API key is invalid or has been revoked."
}
}{
"error": {
"code": "payment_required",
"message": "The Mage API and MCP server need a successful payment on this account first: buy any Gem pack or start a plan at https://www.mage.space/gems, then retry. Signup bonus Gems work in the Mage app only."
}
}{
"error": {
"code": "forbidden",
"message": "This account cannot create characters or references."
}
}{
"error": {
"code": "handle_taken",
"message": "The handle `@ana` is taken. Choose another, or omit `handle` to derive one from the name.",
"handle": "ana"
}
}{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side. Retry, and contact support if it persists."
}
}name, a kind, and the media for that kind. An object, location, pose, or outfit takes an image (an https URL, an upload URL, or a data URL of a JPEG or PNG), stored with the reference for as long as it exists. An audio reference takes an audio clip (MP3 or WAV) instead, which goes through the same processing as a clip uploaded in the app: trimmed to 15 seconds and normalized.
The handle follows the same rules as a character’s: 1 to 15 lowercase letters, digits, underscores, or dashes, starting with a letter, unique among live characters and references, and fixed once created. Handles such as image1 and image2 are reserved for uploaded images and return 400 invalid_config. Leave it out to have one derived from the name. A handle already in use is a 409 handle_taken.
References created through the API are private.Authorizations
Create a key in API → API Keys: select Create API key, name it in the popup, then select Create key. Copy the one-time key and send it as Authorization: Bearer mage_sk_…. Keys are for server-side code only.
Body
The display name.
1 - 50What the reference is. The four image kinds take image; audio takes audio.
object, location, pose, outfit, audio The @handle prompts mention it by: 1 to 15 lowercase letters, digits, underscores, or dashes, starting with a letter. Handles such as image1 and image2 are reserved for uploaded images. Derived from the name when omitted. Cannot be changed later.
The image, for the four image kinds: an https URL, an upload URL, or a data URL of a JPEG or PNG. Stored permanently with the reference.
The clip, for kind: "audio": an https URL, an upload URL, or a data URL of an MP3 or WAV. Trimmed to 15 seconds and normalized, like a clip uploaded in the app.
Optional notes, for your own reference.
500Response
The reference.
The reference id, as DELETE /v1/references/{reference_id} takes it.
Mention the reference in a prompt as @handle.
The display name.
What the reference is.
object, location, pose, outfit, audio Your notes, or null.
The image, for the four image kinds; null for an audio reference.
The processed clip, for kind: "audio"; null otherwise.
When it was created.

