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.
| Label | Account ID | Status | Expiry | Quota | Enabled | Cookies | Last used | Note | Actions |
|---|---|---|---|---|---|---|---|---|---|
| Loading… | |||||||||
Option 1: Browser extension Recommended, no CLI, all platforms
Use a small browser extension to sync the muse.ai session you are already logged into on your own machine.
No Python, no terminal, no commands.
Why an extension is required: all 4 core muse.ai cookies carry the
Why an extension is required: all 4 core muse.ai cookies carry the
httpOnly flag, so page scripts (document.cookie in F12,
bookmarklets) cannot read them; only a browser extension's cookies API can.
1
Download and unzip the extension
Unzip it to a folder you will not delete, e.g.
⬇ Download muse2api-extension.zip
D:\muse2api-extension.
2
Load the extension in your browser
Using Chrome as an example (Edge, Brave and other Chromium browsers are similar):
- Type
chrome://extensionsin the address bar and press Enter - Turn on Developer mode (top right)
- Click Load unpacked (top left)
- Select the folder you unzipped in step 1 (not an individual file inside it)
3
Log in to muse.ai, then import via the extension icon
First open
https://muse.ai/ in your own browser and log in
(until you can see the chat UI), then click the extension icon in the toolbar,
fill in the two values below, and click Read and import.
Option 2: Copy manually No install, fallback
If you would rather not install the extension, you can grab the cookie string by hand. The key is to use
the request headers in the Network panel, not the Console — the
cookie: line includes the httpOnly cookies that the Console cannot see.
- Open and log in to
https://muse.ai/in your own browser; stay on the chat page - Press F12 to open DevTools and switch to the Network panel
- Press F5 to reload so requests appear
- Click any muse.ai request in the list (the first one works)
- On the right, find Headers, then scroll to Request Headers
- Find the line starting with
cookie:and copy everything after the colon (fromhatch_sess=to the end of the line) - Paste it into the Option 3 box below and import
Note: use the
cookie: in the request headers, not the response headers.
The set-cookie in response headers only carries some cookies — you will be missing pieces.
Option 3: Paste import / local script Advanced
If you already have a cookie string, paste it here to import (including strings copied manually in Option 2).
If you prefer the command line, or want to log in with a separate browser (leaving your daily browser untouched), use this script.
It only uses the Python standard library — nothing to pip-install.
CopyGenerating command…
3. Log in to muse.ai in the popup browser window, the script captures and uploads automatically, then the window closes.
Cookie lifetime notes Measured
Measured lifetimes of each muse.ai cookie (may vary slightly per account):
| Cookie | httpOnly | Measured lifetime | Role |
|---|---|---|---|
| hatch_sess | Yes | ~30 days | Main session; decides whether login works |
| hatch_gw | Yes | ~1 year | Gateway token |
| hatch_vml | Yes | ~2 days | Short-lived verification token; sets account lifetime |
| hatch_native_auth_device | Yes | ~30 days | Device ID (anonymous visitors have one too; not a login credential) |
How long does an account actually last? It depends on the earliest-expiring core cookie, i.e.
Note: heavy usage does NOT extend this 2-day window. After each generation this service does read back the freshly issued muse.ai cookies into the pool (so you will see the Expiry column change), but the core cookie expiry is not extended (confirmed by before/after generation experiments).
So: re-import roughly every 2 days. Luckily it is quick — one click on the extension icon.
Import several accounts at once: the pool rotates least-recently-used, so more accounts means more stability and spreads out re-imports (one a day instead of everything expiring at once).
When to re-import? When Expiry in the account list turns Expired and status turns Unhealthy, or a Missing core badge appears.
hatch_vml — about 2 days.Note: heavy usage does NOT extend this 2-day window. After each generation this service does read back the freshly issued muse.ai cookies into the pool (so you will see the Expiry column change), but the core cookie expiry is not extended (confirmed by before/after generation experiments).
So: re-import roughly every 2 days. Luckily it is quick — one click on the extension icon.
Import several accounts at once: the pool rotates least-recently-used, so more accounts means more stability and spreads out re-imports (one a day instead of everything expiring at once).
When to re-import? When Expiry in the account list turns Expired and status turns Unhealthy, or a Missing core badge appears.
Generation tasks 0
Video generation is async; status goes queued → processing → succeeded / failed.
| Task ID | Type | Prompt | Status | Elapsed | Created | Result / 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:
base_url and api_key.
BASE URL:
—
1. Available models
| Model ID | Purpose | Endpoint |
|---|---|---|
| muse-spark | Text / code chat (streaming supported) | POST /v1/chat/completions POST /v1/responses |
| claude-3-5-sonnet | Anthropic Messages format (Claude Code / Agent SDK) | POST /v1/messages |
| muse-image | Text-to-image / image editing | POST /v1/images/generations |
| muse-video | Text-to-video / image-to-video | POST /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
| Method | Path | Description |
|---|---|---|
| GET | /admin/status | Service overview + account pool + recent tasks |
| GET | /admin/accounts | Account list |
| POST | /admin/accounts | Add accounts (single / batch text) |
| PATCH | /admin/accounts/{id} | Rename label / enable-disable |
| DELETE | /admin/accounts/{id} | Delete account |
| POST | /admin/accounts/{id}/test | Verify session for real (also refreshes quota) |
| POST | /admin/accounts/{id}/quota | Read this account's remaining quota live |
| POST | /admin/accounts/{id}/cookies | Update this account's cookies |
| POST | /v1/messages | Anthropic Messages endpoint |
| POST | /v1/messages/count_tokens | Token counting endpoint |
| GET | /admin/tasks | Task history |
| GET | /admin/media | Media library listing |
| POST | /admin/media/delete | Bulk 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:
| Setting | Value |
|---|---|
| Base URL | http://<your-server-ip-or-domain>:18610/v1 |
| API Key | m2a_... (the one in Connection info at the top of this page) |
| Model name | muse-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 type | Required capability | Status |
|---|---|---|
| Chat clients (desktop, Web UI, browser extensions) | POST /v1/chat/completions | ✅ Supported |
| Streaming output (typewriter effect) | stream:true (standard SSE) | ✅ Supported |
| Code / inline completion plugins | POST /v1/chat/completions | ✅ Supported |
| Translation / summary / explainer tools | POST /v1/chat/completions | ✅ Supported |
| Image clients | POST /v1/images/generations | ✅ Supported |
| Video generation clients | POST /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
Verified working: Claude Code, omp (oh-my-pi), Cline, Cursor, any OpenAI-compatible agent. Streaming tool_calls with SSE keepalive supported.
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.