# AI Image Studio API & MCP

Generate images and videos with your AI Image Studio credits from your own code, or from AI apps such as Claude, ChatGPT and Cursor. The models and prices are the same as on the site, and every result also appears in your account's assets.

- **Who can use it:** accounts that have made a purchase on AI Image Studio.
- **Keys and connected apps:** [Account → API & MCP](https://ai-image.studio/app/account/api).
- **What it covers:** text to image, image to image, text to video and image to video, with the models this site offers. The model list can change; read it from `GET /api/v1/models`.

## Quickstart

1. **Create an API key** on [your account page](https://ai-image.studio/app/account/api). It is shown once, so store it like a password.
2. **Start a generation:**

```bash
export API_KEY="bnt_your_key"

curl -X POST https://ai-image.studio/api/v1/generations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","capability_type":"t2i","prompt":"a paper fox in fresh snow"}'
```

3. **Fetch the result** with the `id` from the answer. When `status` is `succeeded`, `outputs[0].url` is your image; it is also in your assets on AI Image Studio.

```bash
curl https://ai-image.studio/api/v1/generations/GENERATION_ID -H "Authorization: Bearer $API_KEY"
```

The examples use GPT Image 2 (`gpt-image-2`). Any model from `GET /api/v1/models` works the same way.

Using an AI app instead? You do not need a key: add the MCP server below and sign in.

## Connect an AI app (MCP)

MCP server URL:

```text
https://ai-image.studio/mcp
```

It is a remote MCP server (Streamable HTTP) with OAuth sign-in. Add the URL to your AI app; the app opens AI Image Studio so you can sign in and approve it. Only accounts that have made a purchase can approve. You can disconnect an app, or change its daily credit limit, on your account page.

### Claude (web and desktop)

1. In Claude, open **Customize → Connectors**, choose **+ Add**, then **Add custom connector**.
2. Name it AI Image Studio, paste `https://ai-image.studio/mcp` as the URL and choose **Add**.
3. Choose **Connect**, sign in to AI Image Studio and approve.

The connector then works in Claude on the web, the desktop app and mobile. Then ask, for example: *"Make a 16:9 image of a paper fox in fresh snow with AI Image Studio."* On Team and Enterprise plans an owner adds it first under **Organization settings → Connectors**, and each member then chooses **Connect**.

### ChatGPT

1. On chatgpt.com, open **Plugins**, choose **+** and then **Add custom MCP server**.
2. Name it AI Image Studio, paste `https://ai-image.studio/mcp` as the server URL and choose **OAuth** for sign-in.
3. Create and install it, sign in to AI Image Studio and approve. In a chat, type **@** and pick AI Image Studio.

Whether you can add custom MCP servers depends on your ChatGPT plan and, in a workspace, on your admin's settings.

### Claude Code

```bash
claude mcp add --transport http ai-image-studio https://ai-image.studio/mcp
```

Then run `/mcp` in Claude Code, pick ai-image-studio and sign in. Add `--scope user` to use it in every project. To use an API key instead of signing in, add `--header "Authorization: Bearer $API_KEY"`.

### Cursor

[Add to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=ai-image-studio&config=eyJ1cmwiOiJodHRwczovL2FpLWltYWdlLnN0dWRpby9tY3AifQ%3D%3D)

Or add it to `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project):

```json
{
  "mcpServers": {
    "ai-image-studio": { "url": "https://ai-image.studio/mcp" }
  }
}
```

Cursor asks you to sign in to AI Image Studio the first time.

### VS Code

[Install in VS Code](vscode:mcp/install?%7B%22name%22%3A%22ai-image-studio%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fai-image.studio%2Fmcp%22%7D)

Or run **MCP: Add Server** from the Command Palette and choose HTTP, or add it to `.vscode/mcp.json` in your project:

```json
{
  "servers": {
    "ai-image-studio": { "type": "http", "url": "https://ai-image.studio/mcp" }
  }
}
```

Use it from GitHub Copilot Chat in agent mode; VS Code asks you to sign in to AI Image Studio the first time.

### Codex

Add it to `~/.codex/config.toml`:

```toml
[mcp_servers.ai-image-studio]
url = "https://ai-image.studio/mcp"
```

Then sign in:

```bash
codex mcp login ai-image-studio
```

The Codex CLI, its IDE extension and the ChatGPT desktop app share this file.

### Other apps

Any MCP client that supports remote servers works: give it `https://ai-image.studio/mcp` with the Streamable HTTP transport and it will offer to sign in with OAuth. In Devin Desktop (formerly Windsurf), open the MCP config file from the Cascade panel's **…** menu and add the server with `"serverUrl": "https://ai-image.studio/mcp"`.

Apps that cannot sign in can send an API key instead:

```json
{
  "mcpServers": {
    "ai-image-studio": {
      "url": "https://ai-image.studio/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
```

### Tools

| Tool | What it does |
| --- | --- |
| `list_models` | Models this site offers |
| `get_model_params` | One model and its parameters |
| `estimate_cost` | Price of a generation, without running it |
| `generate` | Start an image or video generation |
| `get_generation` | One generation and its results |
| `list_generations` | Your generations, newest first |
| `get_credit_balance` | Credits and today's cap |

`generate` waits up to about 25 seconds. If the result is ready it returns the output URLs; otherwise it returns the generation id, and `get_generation` returns the result once it is done.

Things to ask your AI app:

- *"What image models does AI Image Studio have, and what do they cost?"*
- *"Make four square product shots of a ceramic mug on a wooden table."*
- *"Turn this photo into a short video"* (with an `https://` link to the photo)
- *"How many credits do I have left today?"*

## REST API

Base URL: `https://ai-image.studio/api/v1`

Send your API key in the `Authorization` header. Keys only work on AI Image Studio.

```bash
curl https://ai-image.studio/api/v1/balance \
  -H "Authorization: Bearer $API_KEY"
```

### Endpoints

| Method | Path | What it does | MCP tool |
| --- | --- | --- | --- |
| GET | `/api/v1/models` | Models this site offers | `list_models` |
| GET | `/api/v1/models/{slug}` | One model and its parameters | `get_model_params` |
| POST | `/api/v1/quote` | Price of a generation, without running it | `estimate_cost` |
| POST | `/api/v1/generations` | Start an image or video generation | `generate` |
| GET | `/api/v1/generations/{id}` | One generation and its results | `get_generation` |
| GET | `/api/v1/generations` | Your generations, newest first | `list_generations` |
| GET | `/api/v1/balance` | Credits and today's cap | `get_credit_balance` |

### Generate an image, step by step

1. Pick a model and read its parameters:

```bash
curl https://ai-image.studio/api/v1/models -H "Authorization: Bearer $API_KEY"
curl https://ai-image.studio/api/v1/models/gpt-image-2 -H "Authorization: Bearer $API_KEY"
```

2. Optionally check the price first with `POST /api/v1/quote` (same body, nothing is charged).

3. Start the generation. It answers `202` right away:

```bash
curl -X POST https://ai-image.studio/api/v1/generations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-first-image" \
  -d '{"model":"gpt-image-2","capability_type":"t2i","prompt":"a paper fox in fresh snow"}'
```

```json
{
  "success": true,
  "data": {
    "id": "3f9a1c2b7d4e8f60",
    "status": "queued",
    "model": "gpt-image-2",
    "capability_type": "t2i",
    "type": "image",
    "prompt": "a paper fox in fresh snow",
    "params": {
      "prompt": "a paper fox in fresh snow"
    },
    "outputs": [],
    "credits_quoted": 10,
    "error": null,
    "created_at": "2026-10-20T08:00:00.000Z"
  }
}
```

4. Poll `GET /api/v1/generations/{id}` every few seconds until `status` is `succeeded` or `failed`. Statuses go `queued` → `running` → `succeeded` | `failed`; images take seconds, videos a few minutes.

```json
{
  "success": true,
  "data": {
    "id": "3f9a1c2b7d4e8f60",
    "status": "succeeded",
    "model": "gpt-image-2",
    "capability_type": "t2i",
    "type": "image",
    "prompt": "a paper fox in fresh snow",
    "params": {
      "prompt": "a paper fox in fresh snow"
    },
    "outputs": [
      {
        "type": "image",
        "url": "https://ai-image.studio/api/cdn/file/generated/example.webp",
        "mime": "image/webp",
        "width": 1024,
        "height": 1024,
        "duration_s": null
      }
    ],
    "credits_quoted": 10,
    "error": null,
    "created_at": "2026-10-20T08:00:00.000Z"
  }
}
```

The ids, credits and file address above are examples. For image to image or image to video, put public `https://` URLs of your images in `reference_urls`. To refuse a price higher than you expect, send `max_credits`: the call fails with `PRICE_CHANGED` instead of charging more.

### Code examples

**Python** (with `requests`)

```python
import os, time, requests

API = "https://ai-image.studio/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}

res = requests.post(
    f"{API}/generations",
    headers={**HEADERS, "Idempotency-Key": "paper-fox-1"},
    json={"model": "gpt-image-2", "capability_type": "t2i", "prompt": "a paper fox in fresh snow"},
).json()
if not res["success"]:
    raise SystemExit(res["error"]["code"])

gen = res["data"]
while gen["status"] in ("queued", "running"):
    time.sleep(3)
    gen = requests.get(f"{API}/generations/{gen['id']}", headers=HEADERS).json()["data"]

print(gen["status"], [out["url"] for out in gen["outputs"]])
```

**JavaScript** (Node 18+ or any runtime with `fetch`)

```js
const API = "https://ai-image.studio/api/v1";
const headers = { Authorization: `Bearer ${process.env.API_KEY}` };

let res = await fetch(`${API}/generations`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": "paper-fox-1" },
  body: JSON.stringify({ model: "gpt-image-2", capability_type: "t2i", prompt: "a paper fox in fresh snow" }),
}).then((r) => r.json());
if (!res.success) throw new Error(res.error.code);

let gen = res.data;
while (gen.status === "queued" || gen.status === "running") {
  await new Promise((done) => setTimeout(done, 3000));
  gen = (await fetch(`${API}/generations/${gen.id}`, { headers }).then((r) => r.json())).data;
}

console.log(gen.status, gen.outputs.map((out) => out.url));
```

### Responses and errors

Every response is JSON and carries an `X-Request-Id` header.

```json
{ "success": true, "data": { "...": "..." } }
{ "success": false, "error": { "code": "INSUFFICIENT_CREDITS", "message": "...", "request_id": "..." } }
```

Branch on `error.code`, never on the message. The ones you are most likely to meet:

| Code | What to do |
| --- | --- |
| `UNAUTHORIZED` | No key or token, or it was revoked. Check the `Authorization` header. |
| `PAYMENT_REQUIRED` | The account has not made a purchase yet. The API opens after the first one. |
| `INSUFFICIENT_CREDITS` | Not enough credits for this generation. Top up on the pricing page. |
| `DAILY_CAP_REACHED` | This key or app hit its daily credit limit. Raise it on the account page, or wait until 00:00 UTC. |
| `INVALID_PARAMS` | A parameter is missing or out of range. Compare with `GET /models/{slug}`. |
| `MODERATION_BLOCKED` | The prompt or a reference image was refused by moderation. Nothing is charged. |
| `PRICE_CHANGED` | The price is higher than your `max_credits`. Quote again and decide. |
| `RATE_LIMITED` | Too many requests in a minute. Wait a few seconds and retry. |
| `SERVICE_UNAVAILABLE` | A temporary problem on our side. Retry after the `Retry-After` header. |

All codes: `VALIDATION_ERROR`, `INVALID_PARAMS`, `INVALID_MODEL`, `MODERATION_BLOCKED`, `UNAUTHORIZED`, `INVALID_TOKEN`, `TOKEN_EXPIRED`, `PAYMENT_REQUIRED`, `USER_BANNED`, `INSUFFICIENT_CREDITS`, `PREMIUM_CREDITS_REQUIRED`, `DAILY_CAP_REACHED`, `MODEL_NOT_AVAILABLE`, `NOT_FOUND`, `BATCH_NOT_FOUND`, `PRICE_CHANGED`, `IDEMPOTENCY_MISMATCH`, `RATE_LIMITED`, `INTERNAL_ERROR`, `SERVICE_OVERLOADED`, `SERVICE_UNAVAILABLE`.

## Credits and limits

- A generation costs the same credits as on the site. Credits are taken when the generation starts; failed outputs are refunded automatically.
- **Daily credit limit:** each API key and each connected app may spend up to 1,000 credits per UTC day by default. Change it or turn it off on your account page. Past the limit, new generations fail with `DAILY_CAP_REACHED` until 00:00 UTC.
- **Rate limits:** about 10 new generations and 120 other requests per minute per account; past that you get `429 RATE_LIMITED`.
- **Retries:** send an `Idempotency-Key` header with `POST /api/v1/generations`. Repeating a request with the same key returns the first generation instead of starting (and charging for) a new one; reusing a key with a different body fails with `IDEMPOTENCY_MISMATCH`.

## Machine-readable

- OpenAPI 3.1: [https://ai-image.studio/developers/openapi.json](https://ai-image.studio/developers/openapi.json)
- This page as Markdown: [https://ai-image.studio/developers.md](https://ai-image.studio/developers.md)
