URL: /code/apps/media/generate · Id: `page:/code/apps/media/generate`

# File.generate

> Makes an image, a clip, speech or music from a prompt and your reference Files, and records how it was made.

POST https://api.sb/&#123;your-domain&#125;/files/generate

Makes an image, a clip, speech or music from a prompt and your reference [Files](https://startupbuilder.dev/business/nouns/file), and records how it was made.

- **Action class:** None
- **Approval:** Runs on its own
- **Emits:** `File.generated`
- **Price:** 1.2¢ a File

```text title="Run it · Ask"
Make a square image for the renewal-notice post: a calendar page with a notice 60 days out, in our brand colors.
```

```ts title="Run it · SDK"
import { $ } from 'startup-builder'

const result = await $.try.File.generate({ kind: 'image', prompt: 'A calendar page with one notice pinned 60 days before a lease ends; flat, brand colors, no text.' })
```

```json title="Run it · Response"
{
  "api": "https://api.sb/leaseline.app",
  "file": {
    "$id": "https://api.sb/leaseline.app/files/file_Lc7aR2nV5x",
    "$type": "File",
    "name": "renewal-notice-card.png",
    "contentType": "image/png"
  },
  "action": {
    "operation": "File.generate",
    "mode": "try",
    "status": "done"
  }
}
```

Its Inputs, Outputs, Effects and guards quote [the hub’s `File.generate`](https://startupbuilder.dev/business/nouns/file/generate); this page adds what each Venue honors, its limits and a worked call.

## Inputs
| Name | Type | Default | Meaning |
| --- | --- | --- | --- |
| `kind` | `string` | Required | What to make. |
| `prompt` | `text` | Required | What to make, or for `speech` the text to speak. |
| `references` | `File[]` | `[]` | Files the output follows, such as a product photo or a first frame. Unset: none; the output follows the prompt alone. |
| `voice` | `Voice` | `your Brand’s Voice` | The Voice that speaks, for `speech`. Unset: the Brand’s Voice, when it has one. |
| `format` | `json` | `{ aspect: '1:1' }` | Aspect ratio, resolution, duration and file type. Unset: square, at the network’s largest size for an image; 5 seconds for a clip. |

## Outputs
| Field | Type | What `null` means |
| --- | --- | --- |
| `file` | `File` | Never null: the File, its bytes copied into Storage before the Action is done. |
| `file.name` | `string` | Never null: a name made from the prompt, such as `renewal-notice-card.png`. |
| `file.contentType` | `string` | Never null: `image/png`, `video/mp4`, `audio/mpeg`. |

## Effects
**Action class**

None: no approval rule names it, so it runs within its seat’s Permissions and Limits

**Modes**

- `try`: Checks the prompt, the references and the Voice, and returns the File as it would be named and typed; nothing is generated or billed.
- `send`: Returns a pending Action at once; `File.generated` fires when the bytes are in Storage.
- `do`: Waits for the bytes, seconds for an image and up to a few minutes for a clip, and returns the File.

**Idempotency**

Only with a key: the same `Idempotency-Key` and input return the first Action, and the same key with other input returns `409`. A repeat with the same key returns the first File and bills nothing; a new key generates again.

**Saved or shared**

The File in Storage, with its prompt, references, Voice and route recorded as provenance. A failed or declined generation saves nothing and costs nothing.

**Emits**

`File.generated` with `{ file, kind, prompt }`

**Performed by**

[Content lead](https://startupbuilder.dev/agents/marketing/content-lead)

**Price**

About 1.2¢ a File. At most $1.20 a File. Free: a generation that fails or is declined, try mode.

## On each Venue
It acts on your own records and reaches no Venue, so every account answers the same way.

## What try does
Runs every check the call meets and returns the record as it would be; nothing is stored, sent or posted.

## Refuses when
| Check | Error | Fix | Then call |
| --- | --- | --- | --- |
| An invented testimonial, a synthetic person speaking as a customer, or a face or voice with no yes | [`synthetic-media`](/code/refusals#check-synthetic-media) | Use a real customer’s words with their yes, or show the product instead. | [`Content.draft`](/code/apps/sites-and-content/draft) |
| A cut with an attendee's face, voice or full name and no recorded Consent | [`face-voice-consent`](/code/refusals#check-face-voice-consent) | Record the attendee's Consent, or cut them from the piece. | [`Consent.create`](https://startupbuilder.dev/business/nouns/consent/create) |
| A data call whose price for what you asked is above its `maxCost`, checked before anything is spent | [`max-cost`](/code/refusals#max-cost) | Lower `limit`, or raise `maxCost` to the price the refusal’s detail quotes. | [`Organization.find`](/code/data/organizations/find) |

```json
{
  "type": "https://startupbuilder.dev/errors/synthetic-media",
  "title": "Synthetic media",
  "status": 422,
  "detail": "An invented testimonial, a synthetic person speaking as a Customer, or a face or voice with no yes.",
  "fix": "Use a real Customer’s words with their yes, or show the product instead.",
  "next": {
    "verb": "Content.draft",
    "input": {}
  },
  "instance": "https://api.sb/leaseline.app/actions/action_1"
}
```

## When it waits
In `send` mode it returns a pending Action, `reason: 'running'` until the bytes are in Storage; canceling it cancels the generation, and `File.generated` delivers the result.

```ts
await $.Watch.create({ selector: 'File.generated', url: 'https://leaseline.app/hooks/sb' })
```

## Example
A refusal: its reference shows a face with no recorded Consent, so the call refuses before anything is generated.

**Ask**

```text
Make a square image for the renewal-notice post: a calendar page with a
notice 60 days out, in our brand colors, for `references:
['file_test_face']`.
```

**API**

```bash
curl -X POST "https://api.sb/leaseline.app/files/generate?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "video",
  "prompt": "test clip",
  "references": [
    "file_test_face"
  ]
}'
```

**CLI**

```bash
npx startup-builder do File.generate --data '{
  "kind": "video",
  "prompt": "test clip",
  "references": [
    "file_test_face"
  ]
}'
```

The CLI runs in try mode unless you pass `--do`.

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.File.generate({ kind: 'video', prompt: 'test clip', references: ['file_test_face'] })"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const result = await $.try.File.generate({
  kind: 'video',
  prompt: 'test clip',
  references: ['file_test_face'],
})
```


```json title="Response, in try mode"
{
  "type": "https://startupbuilder.dev/errors/face-voice-consent",
  "title": "No Consent for face or voice",
  "status": 422,
  "detail": "A cut with an attendee's face, voice or full name and no recorded Consent.",
  "fix": "Record the attendee's Consent, or cut them from the piece.",
  "next": {
    "verb": "Consent.create",
    "input": {}
  },
  "instance": "https://api.sb/leaseline.app/actions/action_1"
}
```

To retry, send the same `Idempotency-Key`: the retry returns the first answer for $0. A new key reads again.

A `sk_test_` key answers these the same way every time, at $0 ([every test value](/code/checks#test-values)).

| Test value | Always returns | What it is for |
| --- | --- | --- |
| `prompt: 'test image'` | `{"file":{"name":"test-image.png","contentType":"image/png"}}` | Returns the same 1,024-pixel test image every time, free, so the post that uses it can be built. |
| `references: ['file_test_face']` | Refuses with [`face-voice-consent`](/code/refusals#check-face-voice-consent) | Its reference shows a face with no recorded Consent, so the call refuses before anything is generated. |

## Used by
- **Workflows:** [Launch kit](/capabilities/make-content/launch-kit)
- **Agent tasks:** [Launch day](/capabilities/earn-first-links/launch-day) · [Ad kit](/capabilities/make-content/ad-kit) · [Message test](/capabilities/run-ads/message-test)
- **Jobs:** [Make content](/capabilities/make-content)

## Related
[`Video.draft`](/code/apps/media/draft) · [`Video.finalize`](/code/apps/media/finalize) · [`File.edit`](/code/apps/media/edit) · [`Voice.clone`](/code/apps/media/clone) · [`Voice.retire`](/code/apps/media/retire)