Download API_SPEC.md from mando2222/moss-image: direct link, hf CLI and curl.
- Browser
- Download file 7.82 kB
-
https://huggingface.co/mando2222/moss-image/resolve/cccfdf730b310c2d7745840e04e0930bae987f73/API_SPEC.md
- Command line
-
hf download hf://mando2222/moss-image@cccfdf730b310c2d7745840e04e0930bae987f73/API_SPEC.md
-
curl -L -o API_SPEC.md https://huggingface.co/mando2222/moss-image/resolve/cccfdf730b310c2d7745840e04e0930bae987f73/API_SPEC.md
MOSS-Image API spec (node4)
HTTP image-generation API for the MOSS-Image TTNN bundle. Diffusion model β no tokens, no KV cache, no streaming; requests are image jobs.
Base URL
- From node4 itself:
http://127.0.0.1:8000 - From other boxes on the LAN:
http://192.168.50.97:8000(node4), orhttp://node4:8000if your/etc/hosts/DNS resolves it. - The server binds
0.0.0.0:$PORT(default 8000). Open that port in any firewall between boxes. No auth (intended for a trusted LAN); put it behind a proxy if you need auth.
Status note: the API shape below is identical whether it is served by the device bundle (TTNN on the Blackhole card) or the CPU reference β same endpoints, same schemas. Only speed differs.
Endpoints
GET /health
Liveness + which model/mesh is loaded, and the capability contract.
{ "status": "ok", "model": "OpenMOSS-Team/MOSS-Image-Base",
"mesh": "P150", "mesh_shape": "1x1", "vae_device": true,
"pipeline_loaded": true, "kind": "tt-dit-server",
"progress_reporting": true, "job_persistence": true,
"private_ephemeral_jobs": true, "private_result_ttl_s": 900 }
vae_deviceβtruewhen the VAE decodes on the device (purettnn, the default; validated vs host fp32 to PCC β₯0.9999 at all resolutions). Force host withMOSS_VAE_DEVICE=0.mesh_shapeβ DiT topology (MOSS_MESH):1x1single-chip (default),1x2/1x4mesh.private_ephemeral_jobs/private_result_ttl_sβ see Private jobs below.
Private jobs (default for new POST /generate)
Send an X-Moss-Job-Token header on POST /generate (or let the server mint one and return it
as job_token). The job is then token-scoped: not listed in GET /jobs, never written
to disk (result held in memory only), and reaped after a 900 s TTL. The same token is
required on GET /jobs/{id}, GET /images/{id}.png, and DELETE /jobs/{id}; a missing/wrong
token returns 404. Limits: max 8 private jobs, 64 MiB encoded result each. Legacy disk-backed
jobs (created without a token) remain listable and survive restarts.
GET /v1/models
OpenAI-style model list.
{ "object": "list", "data": [
{ "id": "OpenMOSS-Team/MOSS-Image-Base", "object": "model", "owned_by": "openmoss" } ] }
POST /generate β submit an async job (recommended)
Request body (JSON):
| field | type | default | notes |
|---|---|---|---|
prompt |
string | β | required |
height |
int | 1024 | 256β2048, multiple of 16 |
width |
int | 1024 | 256β2048, multiple of 16 |
num_inference_steps |
int | 50 | 1β200; β₯28 for quality |
guidance_scale |
float | 3.0 | 0β20; CFG scale (1.0 disables CFG) |
negative_prompt |
string | "" |
used when guidance_scale != 1 |
seed |
int|null | null | reproducibility (CPU RNG) |
max_sequence_length |
int | 4096 | 1β4096; max prompt tokens |
shift |
float|null | nullβ5.0 | 1β10; flow-match scheduler shift |
uncond_skip_layers |
list[int] | [22] |
DiT layers skipped on the CFG negative branch; [] disables |
slg_layers |
list[int]|null | null | skip-layer-guidance layers; null/[] disables the extra forward |
slg_scale |
float | 0.0 | 0β20; prediction += slg_scale*(cond β cond_skipped) |
slg_start |
float | 0.0 | 0β1; SLG/skip window start (fraction of steps) |
slg_stop |
float | 1.0 | 0β1; SLG/skip window stop (fraction of steps) |
The advanced knobs mirror reference/pipeline_moss_image.py __call__. Call GET /v1/parameters
(alias GET /config) for this schema with ranges at runtime.
Response (every new job is private by default β keep the job_token):
{ "job_id": "ff70ee2b28e4", "status": "queued", "poll": "/jobs/ff70ee2b28e4",
"job_token": "<43β128 url-safe chars>", "storage": "memory", "private": true, "result_ttl_s": 900 }
Jobs are serialized through one worker (one model / one device); submitting many just queues them.
GET /jobs/{job_id} β poll status
{ "job_id": "ff70ee2b28e4", "status": "done",
"request": { ... }, "image_url": "/images/ff70ee2b28e4.png" }
status β queued | running | done | error. On error, an error field carries the message.
GET /images/{job_id}.png β fetch the result
Returns image/png once the job is done (404 until then). Finished images are
saved to disk ($MOSS_OUTPUT_DIR, default ./moss_outputs) and freed from memory, so
this is served from the saved file after the job completes.
GET /jobs β list jobs
{ "jobs": [ { "job_id": "ff70ee2b28e4", "status": "done",
"file_path": "/.../moss_outputs/ff70ee2b28e4.png", "prompt": "a red fox in snow" } ] }
DELETE /jobs/{job_id} β delete a job + its saved image
Drops the job from memory and removes its PNG from disk.
{ "deleted": true, "job_id": "ff70ee2b28e4", "file_removed": true }
POST /generate/sync β blocking, returns PNG directly
Same body as /generate; responds with image/png. Convenient but holds the connection for the
full generation (minutes at 1024Β²/50) β prefer the async flow for anything non-trivial.
POST /v1/images/generations β OpenAI-compatible (blocking)
Request (superset of the OpenAI schema β the full control set is accepted here too):
{ "prompt": "a red fox in snow", "n": 1, "size": "1024x1024", "seed": 42,
"width": 1024, "height": 1024, "num_inference_steps": 50, "guidance_scale": 3.0,
"negative_prompt": "", "shift": 5.0, "slg_layers": [24], "slg_scale": 3.0 }
size is WIDTHxHEIGHT; explicit width+height override it. All /generate advanced knobs
(max_sequence_length, shift, uncond_skip_layers, slg_*) are accepted. Response (base64
PNGs, OpenAI Images shape):
{ "created": 1760000000, "data": [ { "b64_json": "<base64 png>" } ] }
GET /v1/parameters (alias GET /config) β controllable-parameter schema
A UI reads this to render generation controls. Each entry has name, type, default, and
min/max/multiple_of/max_length where applicable.
{ "model": "OpenMOSS-Team/MOSS-Image-Base",
"endpoints": ["/generate", "/v1/images/generations"],
"parameters": [
{ "name": "num_inference_steps", "type": "int", "default": 50, "min": 1, "max": 200 },
{ "name": "guidance_scale", "type": "float", "default": 3.0, "min": 0.0, "max": 20.0 },
{ "name": "shift", "type": "float|null", "default": 5.0, "min": 1.0, "max": 10.0 },
{ "name": "width", "type": "int", "default": 1024, "min": 256, "max": 2048, "multiple_of": 16 }
/* β¦height, seed, negative_prompt, max_sequence_length, uncond_skip_layers, slg_* β¦ */
] }
Example (async)
HOST=http://192.168.50.97:8000
JID=$(curl -s -X POST $HOST/generate -H 'content-type: application/json' \
-d '{"prompt":"a cozy bookshop, warm light, a cat asleep on a chair","height":1024,"width":1024,"num_inference_steps":50,"seed":7}' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["job_id"])')
until curl -s $HOST/jobs/$JID | grep -q '"status":"done"'; do sleep 5; done
curl -s $HOST/images/$JID.png -o out.png
Notes for client/agent builders
- Latency (single p150, device backend): ~12β25 s for 256Β²/4-step warm; ~235 s for
1024Β²/50-step. Set generous client timeouts; prefer
/generate+ poll over/generate/sync. - Concurrency: requests queue (single device). Don't fan out expecting parallelism.
- Resolution:
height/widthmust be multiples of 16. - Determinism: pass
seedfor reproducible images. - Errors: poll
/jobs/{id}and checkstatus == "error"+ theerrorstring; HTTP 4xx for bad input (e.g. malformedsize), 404 for an unknown job or an image not yet ready.