# MicroCore Studio API Contract — Advanced CPU Image Gen V2 **Space:** MicroCore-Studio-advanced-cpu-image-gen-v2 **Status:** Active — Plug-and-Play Ready **Last Validated:** 2026-06-10 **Gradio Version:** 5.50.0 **Image Resolution:** 768×768 **Output Format:** PNG (lossless) --- ## 1. Endpoint | Property | Value | |----------|-------| | **Base URL** | `https://{space_id}.hf.space` | | **Submit Endpoint** | `POST /gradio_api/queue/join` | | **Polling Endpoint** | `GET /gradio_api/queue/data?session_hash={HASH}` (SSE stream) | | **Status Endpoint** | `GET /gradio_api/queue/status?event_id={ID}` | | **Auth** | None (public) | | **Content-Type** | `application/json` | > **Note:** Gradio 5.x uses `/gradio_api/queue/join` for submission and SSE streaming via `/gradio_api/queue/data` for results. The legacy `/gradio_api/call/` path also works for submission but returns a simpler response. --- ## 2. Input Payload Order (Deterministic) Inputs map left-to-right, top-to-bottom from Gradio interface: | Index | Parameter | Type | Default | Description | |-------|-----------|------|---------|-------------| | 0 | `data[0]` | string | *(required)* | Prompt text | | 1 | `data[1]` | string | `"blurry, ugly, low quality, deformed"` | Negative prompt | | 2 | `data[2]` | string | `"Photorealistic"` | Style: `None`, `Cinematic`, `Photorealistic`, `Digital Art`, `Cyberpunk`, `Anime` | | 3 | `data[3]` | number | `8` | Inference steps (4–12) | | 4 | `data[4]` | number | `1.5` | Guidance scale (1.0–4.0) | | 5 | `data[5]` | number | `0.3` | Polish intensity / refiner strength (0.0–0.5) | ### Example POST Body (Gradio 5.x — queue/join) ```json { "data": [ "a cat wearing a top hat", "blurry, ugly, low quality", "Photorealistic", 8, 1.5, 0.3 ], "fn_index": 0, "session_hash": "your-session-id" } ``` ### Legacy POST Body (call endpoint) ```json { "data": [ "a cat wearing a top hat", "blurry, ugly, low quality", "Photorealistic", 8, 1.5, 0.3 ] } ``` --- ## 3. Response Format ### Step 1 — Submit Generation (POST) ``` POST /gradio_api/queue/join → Response (within 2s): { "event_id": "ev-abc123..." } ``` **Headers required for polling:** ``` x-grado-user: api ``` ### Step 2 — Poll for Result (SSE Stream) ``` GET /gradio_api/queue/data?session_hash=YOUR_SESSION_HASH → Server-Sent Events stream with messages: { "msg": "estimation", ... } { "msg": "process_starts", "eta": N, ... } { "msg": "process_completed", "output": {...}, "success": true } { "msg": "close_stream" } ``` Poll until `"msg": "process_completed"` is received (timeout: 300s). #### Success Response (`process_completed`) ```json { "msg": "process_completed", "event_id": "...", "output": { "data": [ { "path": "/tmp/gradio/{uuid}/image.jpeg", "url": "https://...hf.space/gradio_api/file=/tmp/gradio/{uuid}/image.png", "size": null, "orig_name": "image.png", "mime_type": "image/png", "is_stream": false, "meta": { "_type": "Image" } }, "Quality Optimized Generation in 98.63s | Cache Key: fb304891dc6a85a5..." ] }, "success": true } ``` #### Image Retrieval The image in `output.data[0]` is returned as a **file reference**, not inline base64: - **URL:** `output.data[0].url` — full HTTPS URL to download the JPEG - **Download:** `GET output.data[0].url` → binary JPEG data - **Size:** >50KB valid PNG (768×768, lossless) - **Format:** `image/png` #### Node.js Integration Example ```javascript const submit = await fetch(SPACE_URL + "/gradio_api/queue/join", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ data: ["prompt text", "negative", "Photorealistic", 8, 1.5, 0.3], fn_index: 0, session_hash: "my-session" }) }); const { event_id } = await submit.json(); // Poll via SSE or use gradio_client library const result = await new Promise((resolve) => { const es = new EventSource(SPACE_URL + "/gradio_api/queue/data?session_hash=my-session"); es.onmessage = (e) => { const msg = JSON.parse(e.data); if (msg.msg === "process_completed") { es.close(); resolve(msg.output.data); } }; }); // result[0].url → download PNG const imgResp = await fetch(result[0].url); const imgBuffer = Buffer.from(await imgResp.arrayBuffer()); console.log(`Image size: ${imgBuffer.length} bytes`); ``` #### Error Response ```json { "msg": "process_completed", "success": false, "output": { "data": ["", "{\"error\": \"...\", \"code\": 400}"] } } ``` --- ## 4. Caching Contract | Property | Value | |----------|-------| | **Cache Key** | `SHA-256(JSON.stringify(payload, sort_keys=True))` | | **Storage Path** | `/tmp/generated_images/{cache_key}.png` | | **TTL** | 24 hours (86400 seconds) | | **Format** | PNG binary (768×768, lossless) | | **Behavior** | Identical payload → instant return from cache, no pipeline invocation | ### Cache Hit Detection - Status string contains prefix `"CACHED (TTL: 24h)"`. - Image returned is byte-identical to previous generation. ### TTL Enforcement - On each cache lookup, file mtime is checked against current time. - Expired entries are deleted on access. - No background cleanup thread needed. --- ## 5. Error Resilience Contract ### 5.1 Circuit Breaker | Trigger | Action | |---------|--------| | 3 consecutive generation failures/timeouts | Circuit opens → all new requests rejected with HTTP-like error for 60s | | After 60s cooldown | Circuit transitions to HALF_OPEN → allows 1 test request | | Test request succeeds | Circuit closes, normal operation resumes | Error message when open: ```json {"error":"Service temporarily unavailable due to high error rate. Please retry in 60s."} ``` ### 5.2 Invalid Payload Handling | Scenario | Response | |----------|----------| | Empty/missing prompt | `{"error": "Invalid payload: 'prompt' is required...", "code": 400}` | | Invalid numeric params | `{"error": "Invalid payload: steps, guidance... must be numeric.", "code": 400}` | | Unknown style | `{"error": "Invalid payload: unknown style 'X'...", "code": 400}` | All invalid payloads return graceful JSON errors. **No crashes.** ### 5.3 OOM / Stress Recovery SLA | Condition | Recovery Time | Behavior | |-----------|--------------|----------| | OOM kill / memory pressure | ≤ 2 minutes | Gradio auto-restarts via Docker restart policy. Model reloads on startup. | | 10+ rapid concurrent requests | Circuit breaker triggers within 3 failures | 60s pause, then auto-recovery | | Pipeline stage 2 (polish) failure | Instant (< 1s) | Falls back to stage 1 result, logs warning, does not increment circuit breaker | --- ## 6. Integration Checklist for MicroCore Studio - [x] Fixed endpoint URL: `/gradio_api/queue/join` (submit) + `/gradio_api/queue/data` (poll) - [x] No authentication required - [x] Deterministic input order documented (6 parameters, indexed 0–5) - [x] POST returns `{event_id}` within 2s - [x] SSE polling returns process_completed with downloadable PNG >50KB - [x] SHA-256 caching with 24h TTL at `/tmp/generated_images/` - [x] Circuit breaker: 3 failures → 60s pause - [x] Graceful error responses (HTTP 400-style JSON) for all invalid inputs - [x] OOM/stress auto-recovery within 2 minutes - [x] Image resolution: 768×768 ensuring >50KB output size