# Generative AI (ai)

> Generate images, videos, sound and assets directly within framefields compositions using the AI gateway.

`framefields` includes built-in generative AI capabilities via the `ai` module. One API key unlocks every supported generative model with unified credit billing, zero retention, and direct WebGPU composition integration.

```ts
import { ai, Composition, Layer } from "framefields";

// Subscribe to a queue-based generation
const { data } = await ai.subscribe("flux/schnell", {
  input: {
    prompt: "An atmospheric 35mm film still of a cinematic neon street",
    image_size: "landscape_16_9",
  },
});

console.log("Image URL:", data.images[0].url);
```

## Setup & API Keys

You don't need separate provider accounts or keys.

1. Sign in at [framefields.dev/dashboard](https://framefields.dev/dashboard).
2. Top up credits on the [Billing page](https://framefields.dev/dashboard/billing) with Dodo Payments.
3. Create an API key on the [API Keys page](https://framefields.dev/dashboard/keys).
4. Add the key to your project `.env`:

```bash
FRAMEFIELDS_API_KEY=ff_live_...
```

Or configure it in code:

```ts
import { ai } from "framefields";

ai.config({
  apiKey: process.env.FRAMEFIELDS_API_KEY,
});
```

## Model Catalog

Explore available models in the [Model Catalog](https://framefields.dev/models), including text-to-image, image-to-video, voice synthesis, and upscaling models.

You can also fetch the catalog programmatically for agentic workflows:

```bash
curl https://api.framefields.dev/v1/models
```

## API Methods

### `ai.subscribe` (Recommended)

Submits a request to the async processing queue, waits for completion, and returns the final output. Ideal for video and high-resolution rendering models.

```ts
const { data } = await ai.subscribe("flux/schnell", {
  input: {
    prompt: "A neon geometric sculpture rotating in void, raytraced",
  },
  pollInterval: 500, // poll status every 500ms
});
```

### `ai.run`

Executes synchronously over a single HTTP connection. Best for fast operations like prompt enhancements or micro-latencies.

```ts
const { data } = await ai.run("flux/schnell", {
  input: { prompt: "Retro minimal typography background" },
});
```

### `ai.stream`

Streams generation events (tokens or partial image steps) over Server-Sent Events (SSE).

```ts
const stream = await ai.stream("flux/dev", {
  input: { prompt: "Cyberpunk cityscape" },
});

for await (const event of stream) {
  console.log("Progress:", event);
}
```

### `ai.storage.upload`

Uploads local buffers or files to ephemeral CDN storage via presigned URLs so models can reference them as input parameters (e.g. image-to-video or style transfer).

```ts
import fs from "node:fs";

const file = fs.readFileSync("input.png");
const fileUrl = await ai.storage.upload(new Blob([file], { type: "image/png" }));

const { data } = await ai.subscribe("wan/video", {
  input: {
    image_url: fileUrl,
    prompt: "Slow cinematic camera pan forward",
  },
});
```

## Using Generated Assets in Compositions

Download or stream generated assets directly into your `framefields` layer hierarchy:

```ts
import { ai, Composition, Layer } from "framefields";
import fs from "node:fs/promises";

// 1. Generate an image asset
const { data } = await ai.subscribe("flux/schnell", {
  input: { prompt: "Abstract glowing glass caustics, dark mode" },
});

// 2. Fetch image buffer
const res = await fetch(data.images[0].url);
const imageBuffer = Buffer.from(await res.arrayBuffer());
await fs.writeFile("assets/generated-bg.png", imageBuffer);

// 3. Compose in WebGPU layer
export default Composition.create({
  width: 1920,
  height: 1080,
  fps: 60,
  durationInFrames: 300,
  children: [
    Layer.image({
      source: "assets/generated-bg.png",
      width: 1920,
      height: 1080,
    }),
  ],
});
```

## Credits & Error Handling

Credits are charged in micro-USD ($0.000001 resolution) based on model usage plus margin.

When credits are depleted, requests will return HTTP `402 Payment Required`:

```ts
try {
  await ai.subscribe("flux/schnell", { input: { prompt: "..." } });
} catch (err: any) {
  if (err.status === 402) {
    console.error("Credits depleted. Top up at https://framefields.dev/dashboard/billing");
  }
}
```

| HTTP Status | Error Type | Solution |
| --- | --- | --- |
| `401` | `invalid_api_key` | Verify `FRAMEFIELDS_API_KEY` in `.env` |
| `402` | `insufficient_credits` | Add credits in [Billing](https://framefields.dev/dashboard/billing) |
| `402` | `key_limit_reached` | Increase key monthly limit in [API Keys](https://framefields.dev/dashboard/keys) |
| `429` | `rate_limited` | Respect retry-after backoff (60 submits/min, 600 status/min) |

## Zero-Retention Privacy

- **No storage:** We do not save or log your prompts, parameters, inputs, or generated outputs.
- **Ephemeral storage:** Files uploaded to storage expire automatically within 7 days.
- **Financial audit only:** We record only billing metadata (request ID, model ID, timestamp, status, and charge).
