API Server · Mac

# Your Mac Is Now an Image Generation API

Start the API Server in Private Diffusion and your Mac answers image requests from Claude, from scripts, and from any app that speaks the OpenAI image API. Every image is made on your Mac, with no cloud relay in between.

-   Mac only
-   Beta

[![Pre-order on the App Store](/app-store/pre-order-badge/en/pre-order.svg)![Pre-order on the App Store](/app-store/pre-order-badge/en/pre-order-dark.svg)](https://testflight.apple.com/join/DQwfQsEg)[Discord](https://discord.com/invite/g2vMMbtHRt)

On this page

1.  [Overview](#overview)
2.  [Setup](#setup)
3.  [Before you connect](#before-you-connect)
4.  [Examples](#examples)
5.  [Claude and MCP](#mcp)
6.  [Authentication](#authentication)
7.  [Endpoints](#endpoints)
8.  [Models](#models)
9.  [Errors and limits](#errors)
10.  [FAQ](#faq)

## OpenAI-Compatible Image Generation API, Served From Your Mac

Code reaches it through the OpenAI image API, and Claude reaches it through MCP. Either way, the API Server runs the models you have already downloaded and hands back finished images.

### OpenAI-Compatible

Point an OpenAI SDK at your Mac and call `images.generate`. Most image code written for OpenAI changes in two places: the base URL and the key.

### Claude Connects Over MCP

Add Private Diffusion to Claude Code or Claude Desktop, then ask Claude for a picture. It calls the `generate_image` tool, and your Mac makes the image and hands it back.

### Made on Your Mac

Prompts and images travel between your client and your Mac, with no cloud relay. Any device that can reach your Mac can send it requests, and it answers only those that carry your key.

## Set It Up in Three Steps

1.  1
    
    ### Download a Model
    
    Open Private Diffusion on your Mac and download at least one model. The server generates with the models you have, and the one active in Studio is its default.
    
2.  2
    
    ### Start the API Server
    
    Click Start API Server in the API Server tab, or use the Server menu (⇧⌘A). To serve every time the app opens, turn on "Start the API server at launch" in Settings › API Server.
    
3.  3
    
    ### Copy Your Address and Key
    
    Click Details in the API Server tab. It lists your Mac's addresses, your key, and ready-made commands for `curl`, Claude Code, and Claude Desktop with both filled in.
    

## Know Before You Connect

-   The server speaks plain HTTP. Your key, prompts, and images cross the network unencrypted, so run it on networks you trust and stop it on public Wi-Fi.
-   Any device that can reach your Mac and holds the key can generate images.
-   Treat the key like a password. If it leaks, regenerate it in Settings › API Server. Clients using the old key stop working until you give them the new one.
-   Any web page you give the key to can call the server from your browser. Paste it only into tools you trust.
-   With "Start the API server at launch" turned on, your Mac serves on every network it joins. Turn it off on a laptop that travels.
-   While the server runs, Studio pauses, your Mac stays awake, and switching or deleting models waits until you stop it.
-   Images made over the API land in your gallery. Turn on Incognito Mode, or turn off Save API images to gallery, to keep them out.
-   Your Mac makes one image at a time. Up to 8 requests wait their turn, and the next one gets a `queue_full` error.

## Generate Images From `curl`, Python, and JavaScript

Each example makes one picture and saves it as a file. Put your key in an environment variable named `PD_API_KEY`, and replace `your-mac.local` with your Mac's address from Details in the API Server tab.

8963 is the default port. If you changed it in Settings › API Server, use yours.

### curl

Sends the prompt and decodes the returned image with `jq`.

curlCopy

```
curl -sS http://your-mac.local:8963/v1/images/generations \
  -H "Authorization: Bearer $PD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "a lighthouse at dusk, oil painting", "size": "1024x1024"}' \
  | jq -r '.data[0].b64_json // error(.error.message)' | base64 --decode > lighthouse.png
```

### Python (OpenAI SDK)

Uses the official `openai` package. Fields the OpenAI API does not define, such as `seed`, go in `extra_body`. The SDK retries a full queue twice by default, then raises the error.

PythonCopy

```
import base64
import os

from openai import OpenAI

client = OpenAI(
    base_url="http://your-mac.local:8963/v1",
    api_key=os.environ["PD_API_KEY"],
)

result = client.images.generate(
    prompt="a lighthouse at dusk, oil painting",
    size="1024x1024",
    extra_body={"seed": 42},
)

with open("lighthouse.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))
```

### JavaScript (OpenAI SDK, Node.js)

Runs in Node.js with the `openai` package, which sends extra fields such as `seed` as they are. Never run it in a web page, where anyone could read the key.

JavaScriptCopy

```
import { writeFileSync } from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "http://your-mac.local:8963/v1",
  apiKey: process.env.PD_API_KEY,
});

const result = await client.images.generate({
  prompt: "a lighthouse at dusk, oil painting",
  size: "1024x1024",
  seed: 42,
});

writeFileSync("lighthouse.png", Buffer.from(result.data[0].b64_json, "base64"));
```

## Claude Image Generation Over MCP: Claude Code and Claude Desktop

Private Diffusion speaks the Model Context Protocol at `/mcp`. Connect Claude once, then ask for images in plain language.

### Claude Code

With `PD_API_KEY` set as above, run this once in your terminal to add the server to Claude Code.

TerminalCopy

```
claude mcp add --transport http private-diffusion http://your-mac.local:8963/mcp \
  --header "Authorization: Bearer $PD_API_KEY"
```

Do not add `--scope project`. It writes your key into a `.mcp.json` file meant to be shared.

### Claude Desktop

Claude Desktop reaches the server through `mcp-remote`, a small bridge that runs on Node.js. In Claude Desktop, open Settings › Developer › Edit Config, add this entry, replace `pd-your-key` with your key, and restart Claude.

claude\_desktop\_config.jsonCopy

```
{
  "mcpServers": {
    "private-diffusion": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote@0.14.3",
        "http://your-mac.local:8963/mcp",
        "--allow-http",
        "--transport",
        "http-only",
        "--header",
        "Authorization:${PRIVATE_DIFFUSION_AUTH}"
      ],
      "env": {
        "PRIVATE_DIFFUSION_AUTH": "Bearer pd-your-key"
      }
    }
  }
}
```

Needs Node.js. The bridge version is pinned.

### MCP Tools

MCP Tools
| Tool | What it does |
| --- | --- |
| `generate_image` | Makes one to 4 images from a prompt. Takes the HTTP fields except `quality` and streaming, and returns `jpeg` with compression set to 85 unless you ask for PNG. An explicit model that is not ready is an error, not a fallback. |
| `list_models` | Lists the models ready on this Mac with the sizes, steps, and upscale factors each accepts here. |
| `get_image_chunk` | Used by MCP clients that display full-size images. You never call it yourself. |

## Authentication

Every request to `/v1/*` and `/mcp` carries your key in the `Authorization: Bearer pd-…` header. The app creates the key the first time the server starts. Reveal or regenerate it in Settings › API Server.

A missing or wrong key returns 401 with the code `invalid_api_key`.

## Endpoints: `/v1/images/generations`, `/v1/models`, and `/mcp`

### `POST /v1/images/generations`

Generates images from a text prompt. Requests and responses follow the OpenAI image API, with a few fields of its own.

Request parameters
| Parameter | Values | Default | Notes |
| --- | --- | --- | --- |
| `prompt` | string | Required | What to draw. Must not be empty. |
| `model` | string | Active model | A model id from the table below. An id that is unknown, not downloaded, or not supported on this Mac falls back to the active model, and the response's `model` names the one that ran. |
| `n` | 1–4 | `1` | How many images. Each uses the next seed. |
| `size` | "auto" | "WxH" | `"auto"` | Snaps to the nearest size the model supports, by shape first and then area. `"auto"` picks 1024×1024 when the model allows it. Extra large sizes need a Mac with more memory. |
| `quality` | "auto" | "low" | "medium" | "high" | `"auto"` | Only `"high"` changes the result, trading speed for detail. |
| `output_format` | "png" | "jpeg" | `"png"` | The image file format. |
| `output_compression` | 0–100 | `100` | Compression for JPEG output. 100 compresses least. |
| `seed` | integer | Random | Set it to repeat a result. |
| `negative_prompt` | string | None | What to keep out of the image. Some models only; the rest return 400. |
| `steps` | integer | Model default | Must sit inside the model's range. Fixed-step models accept only their own value. |
| `upscale` | 1.5 | 2 | 4 | None | Enlarges the image after it is made. The model must offer the factor and its upscaler must be downloaded, or the request returns 400. On Macs with less memory, 4 becomes 2. |
| `stream` | boolean | `false` | Sends the result as server-sent events, with optional previews. |
| `partial_images` | 0–3 | `0` | How many previews to stream before the final image. Used only with `stream`. |

#### Response

Images come back as base64 in `b64_json`, never as a URL, each with its `seed` and whether it carries a watermark. `model` names the model that ran.

JSONCopy

```
{
  "created": 1767225600,
  "model": "zit",
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAA…",
      "seed": 42,
      "watermarked": false,
      "sensitive": false
    }
  ]
}
```

### Streaming Partial Images

Set `stream` to true and the server replies with server-sent events. Each frame names its event and carries a JSON object.

Streaming Partial Images
| Event | Data |
| --- | --- |
| `image_generation.partial_image` | `type, b64_json, partial_image_index, created_at, watermarked`
A preview while the image forms. The index restarts at 0 for each image.

 |
| `image_generation.completed` | `type, b64_json, seed, watermarked, sensitive, created_at`

The finished image with its seed. One per image when you ask for more than one.

 |
| `error` | `error`

Something failed after the stream opened. Errors before that arrive as a normal JSON response.

 |

The stream closes after the last image. There is no separate done event.

### `GET /v1/models`

Lists the models that are downloaded, ready, and supported on this Mac. Send one of their ids as `model`.

## Which Models Work Over the API

Every Private Diffusion model works over the API once it is downloaded and your Mac supports it. Send the id from the second column as `model`.

Which Models Work Over the API
| Model | Id | Negative prompt | Steps | Upscale |
| --- | --- | --- | --- | --- |
| Anima | `anima` | No | 8-12, default 8 | 2× |
| Flux.2 Klein 4B | `klein` | Yes | 4 | 1.5×, 2× |
| Mage Flow Turbo | `mage-flow-turbo` | No | 4 | 1.5×, 2× |
| Krea 2 Turbo | `krea2-turbo` | No | 8 | 2× |
| Kroma Turbo | `kroma` | Yes | 8-12, default 10 | 2× |
| Z-Image-Turbo | `zit` | Yes | 9 | 2×, 4× |
| Juggernaut Z Fast | `juggernaut-z` | Yes | 8 | 2×, 4× |
| ERNIE Image Turbo | `ernie-turbo` | No | 8 | 1.5×, 2× |
| Chroma1-Flash | `chroma` | Yes | 12 | 2×, 4× |
| Boogu Image Turbo | `boogu` | No | 4 | 2×, 4× |

Krea 2 Turbo always runs 8 steps over the API, even when Studio is set to its faster 4-step mode.

Sizes and upscale factors depend on your Mac's memory. The `list_models` MCP tool reports what your Mac accepts.

## Errors and Limits

Errors follow the OpenAI shape: a JSON object with a message, a type, the parameter at fault, and a code.

JSONCopy

```
{
  "error": {
    "message": "steps must be between 8 and 12 for Kroma Turbo.",
    "type": "invalid_request_error",
    "param": "steps",
    "code": null
  }
}
```

Errors and Limits
| Status | Type and code | When |
| --- | --- | --- |
| 400 | invalid\_request\_error | A field is missing or out of range, or the body is not valid JSON. When one field is at fault, `param` names it. |
| 401 | invalid\_request\_error · invalid\_api\_key | The key is missing or wrong. |
| 404 | invalid\_request\_error · not\_found | The path or method does not exist. |
| 405 | — | A request other than `POST` was sent to `/mcp`. |
| 413 | invalid\_request\_error · request\_too\_large | The body is larger than 2 MiB. |
| 429 | rate\_limit\_error · queue\_full | The queue already holds 8 requests. Try again shortly. |
| 500 | server\_error · generation\_failed · internal\_error | Generation failed on the Mac. |
| 503 | server\_error · server\_stopping · runtime\_unavailable · model\_unavailable | The server is stopping, the engine needs a moment, or no model is active. Retry after the seconds in `Retry-After`. |

-   Request bodies up to 2 MiB.
-   One to 4 images per request.
-   One image at a time, with up to 8 waiting.
-   Every 503 carries `Retry-After` of 10 seconds.

## FAQ

-   ### How do I generate images with Claude?
    
    Connect Claude Code or Claude Desktop to Private Diffusion over MCP with the address and key from Details in the app's API Server tab. Then ask Claude for a picture. Claude calls Private Diffusion, which makes the image on your Mac and hands it back.
    
-   ### Is it compatible with the OpenAI image API?
    
    Yes, for generating images. Point an OpenAI SDK at your Mac's address with your key, and the image generation call works as it does with OpenAI. The differences: images come back as base64, there is no editing or image input, and you get extra fields such as a seed and a negative prompt.
    
-   ### Can other devices on my network use it?
    
    Yes. Any device that can reach your Mac can use it with your key. Use the address from Details in the app's API Server tab.
    
-   ### Is the connection encrypted?
    
    No. The server uses plain HTTP, so use it on networks you trust, keep the key private, and regenerate it if it leaks.
    
-   ### Which models work over the API?
    
    Every model you have downloaded on your Mac. Each keeps its own rules for steps, negative prompts, and upscaling, listed in the table on this page.
    
-   ### What happens when several requests arrive at once?
    
    Your Mac makes one image at a time. Up to 8 requests wait in line, and the next one gets a 429 error until the line moves. The OpenAI SDKs retry that error twice by default before giving up.
    
-   ### Does it work on iPhone or iPad?
    
    No. The API Server is part of Private Diffusion for Mac. On iPhone and iPad, you generate images in the app itself.
    

On this page

1.  [Overview](#overview)
2.  [Setup](#setup)
3.  [Before you connect](#before-you-connect)
4.  [Examples](#examples)
5.  [Claude and MCP](#mcp)
6.  [Authentication](#authentication)
7.  [Endpoints](#endpoints)
8.  [Models](#models)
9.  [Errors and limits](#errors)
10.  [FAQ](#faq)