Service — Accounts — Browser — Auto-refresh API Key

Connection info Paste these two values into your project

Paste the two values below into your project and you are ready to call. BASE URL is the API address prefix.
Models: muse-spark (chat/code), muse-image (images), muse-video (video). See the Integration Docs tab for full examples.
Total accounts
0
Healthy
0
Faulty
0
Disabled
0
Media files
0

Add accounts Batch supported

Copy the cookie string for muse.ai from your browser and paste it here. Key cookies: hatch_sess、hatch_gw、hatch_vml。 For batch import, one account per line as label | cookie-string (label optional).

Account list 0

● Auto-keepalive running (15m)
Background silent keepalive runs every 15 minutes with fair multi-account rotation (LRU); Test opens muse.ai for a real session check.
LabelAccount IDStatusExpiryQuotaEnabledCookies Last usedNoteActions
Loading…

Generation tasks 0

Video generation is async; status goes queued → processing → succeeded / failed.
Task IDTypePromptStatus ElapsedCreatedResult / error
Loading…

Media library 0

All generated images/videos saved to disk — download directly or hand the links to downstream projects.
Loading…

Image generation test POST /v1/images/generations

Calls muse.ai for real; images return in about 10–30s.

Video generation test POST /v1/videos

Async task, usually done in 60–120s; this page polls progress automatically.

Integration guide

The API mirrors OpenAI conventions — downstream projects only need to change base_url and api_key.
BASE URL:—

1. Available models

Model IDPurposeEndpoint
muse-sparkText / code chat (streaming supported)POST /v1/chat/completions
POST /v1/responses
claude-3-5-sonnetAnthropic Messages format (Claude Code / Agent SDK)POST /v1/messages
muse-imageText-to-image / image editingPOST /v1/images/generations
muse-videoText-to-video / image-to-videoPOST /v1/videos → GET /v1/videos/{id}
These three are the real Muse capabilities: Muse Spark (language/code), Muse Image (images), Muse Video (video). The muse.ai web app routes via an agent with no model picker, so the model field only exists for downstream compatibility — common names like gpt-4o, claude-sonnet-4 or dall-e-3 are auto-mapped to the matching capability.

2. Chat / code

Copy# Non-streaming
curl -X POST "BASE/v1/chat/completions" \
  -H "Authorization: Bearer $MUSE2API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"muse-spark","messages":[{"role":"user","content":"Write a Python quicksort"}]}'

# Streaming: add "stream":true; returns standard SSE (data: {...} / data: [DONE])

3. Images (curl)

Copycurl -X POST "BASE/v1/images/generations" \
  -H "Authorization: Bearer $MUSE2API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A Shiba Inu wearing an astronaut helmet","size":"1:1","response_format":"url"}'

# Response
{"created":1790148495,"data":[{
  "revised_prompt":"A Shiba Inu wearing an astronaut helmet",
  "url":"http://your-server:18610/v1/media/xxxx.webp",
  "kind":"image","bytes":23860}]}

# url is a full absolute URL, ready for downstream render/download; /v1/media/* needs no auth.
# For base64, pass "response_format":"b64_json".

4. Video (curl, async)

Copy# 1. Create the task
curl -X POST "BASE/v1/videos" \
  -H "Authorization: Bearer $MUSE2API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A kitten walking across a meadow","duration":5,"size":"16:9"}'
# → {"id":"task_xxx","status":"queued"}

# 2. Poll the result
curl "BASE/v1/videos/task_xxx" -H "Authorization: Bearer $MUSE2API_KEY"
# → {"status":"succeeded","result":{"url":"/v1/media/xxx.mp4"}}

5. Python (OpenAI SDK compatible)

Copyfrom openai import OpenAI
import time

client = OpenAI(base_url="BASE/v1", api_key="m2a_...")

# Image
r = client.images.generate(model="muse-image", prompt="A Shiba Inu wearing an astronaut helmet")
print(r.data[0].url)

# Video (native endpoint, since it is async)
import requests
t = requests.post("BASE/v1/videos", json={"prompt":"Kitten walking","duration":5},
                  headers={"Authorization":"Bearer m2a_..."}).json()
while True:
    s = requests.get(f"BASE/v1/videos/{t['id']}",
                     headers={"Authorization":"Bearer m2a_..."}).json()
    if s["status"] in ("succeeded","failed"): break
    time.sleep(5)
print(s)

6. Anthropic Messages API (Claude Code & Agent SDK)

Copy# Claude Code (terminal):
export ANTHROPIC_BASE_URL="http://127.0.0.1:18610"
export ANTHROPIC_API_KEY="$MUSE2API_KEY"
claude

# Python (Anthropic SDK):
import anthropic
client = anthropic.Anthropic(base_url="http://127.0.0.1:18610", api_key="m2a_...")
msg = client.messages.create(
    model="claude-3-5-sonnet", max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)
print(msg.content[0].text)

# curl (POST /v1/messages)
curl -X POST "BASE/v1/messages" \
  -H "x-api-key: $MUSE2API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-3-5-sonnet","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'

7. Admin API

MethodPathDescription
GET/admin/statusService overview + account pool + recent tasks
GET/admin/accountsAccount list
POST/admin/accountsAdd accounts (single / batch text)
PATCH/admin/accounts/{id}Rename label / enable-disable
DELETE/admin/accounts/{id}Delete account
POST/admin/accounts/{id}/testVerify session for real (also refreshes quota)
POST/admin/accounts/{id}/quotaRead this account's remaining quota live
POST/admin/accounts/{id}/cookiesUpdate this account's cookies
POST/v1/messagesAnthropic Messages endpoint
POST/v1/messages/count_tokensToken counting endpoint
GET/admin/tasksTask history
GET/admin/mediaMedia library listing
POST/admin/media/deleteBulk delete media files

8. Auth

All endpoints except /healthz, /readyz, /api/hello, and /v1/media/* require authentication. Both Authorization: Bearer <API Key> and x-api-key: <API Key> are accepted. The API Key is configured in .env as MUSE2API_KEY.

9. Connecting clients / agents

Any client that supports a custom OpenAI-compatible endpoint works with just three values:
SettingValue
Base URLhttp://<your-server-ip-or-domain>:18610/v1
API Keym2a_... (the one in Connection info at the top of this page)
Model namemuse-spark
Any model name works: common names (gpt-4o, gpt-5, claude-sonnet-4, deepseek-chat, gemini-2.5-pro, etc.) are auto-mapped to the matching capability; unknown names pass through untouched, and since muse.ai routes automatically anyway, results are unaffected.

Compatibility by client type

Client typeRequired capabilityStatus
Chat clients (desktop, Web UI, browser extensions)POST /v1/chat/completions✅ Supported
Streaming output (typewriter effect)stream:true (standard SSE)✅ Supported
Code / inline completion pluginsPOST /v1/chat/completions✅ Supported
Translation / summary / explainer toolsPOST /v1/chat/completions✅ Supported
Image clientsPOST /v1/images/generations✅ Supported
Video generation clientsPOST /v1/videos(async polling)✅ Supported
Autonomous agent mode (Claude Code, omp, Cline, Cursor)tool_calls / function calling✅ Supported
Tool calling — now solved in this fork:
The upstream project documented this as unsupported: muse.ai's assistant refuses to emit pseudo-tool-call JSON when asked via prompt injection.
This fork bypasses that entirely using Jev (TypeSafe System One model via OpenCode free endpoint — no key needed). Jev intercepts the request before muse.ai, selects the right tool and fills its arguments from the conversation, then returns a proper tool_calls response. muse.ai only sees round 2, with the tool result injected as natural context — it responds as if it looked the data up itself.
Verified working: Claude Code, omp (oh-my-pi), Cline, Cursor, any OpenAI-compatible agent. Streaming tool_calls with SSE keepalive supported.