| # 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 |
|
|