# Generating content

Generation endpoints divide by how long they take. An image comes back in one call, while
a presentation is a pipeline you drive across several. Knowing which you are dealing with
is most of the integration work.

Everything on this page runs a model, so everything [costs
credits](/usage-and-credits) and counts against the `expensive` [rate-limit
tier](/rate-limits).

## Queue and poll

This is the pattern for anything slow, and it is worth learning once:

1. **POST** the request. It answers **202 Accepted** with an identifier: the work
   has been queued, not done.
2. **Poll** the resource until its status says it finished.
3. **Read** the result off the same resource.

A 202 is neither a failure nor a completion. If your client treats any 2xx as "done" and
reads the body for output, this is where it breaks.

<CodeTabs syncKey="lang">

```js title="JavaScript"
async function pollUntilReady(url, isDone, { intervalMs = 3000, timeoutMs = 300000 } = {}) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const resource = await fetch(url, { headers }).then(r => r.json());
    if (isDone(resource)) return resource;
    await new Promise(r => setTimeout(r, intervalMs));
  }
  throw new Error(`Timed out: ${url}`);
}
```

```python title="Python"
def poll_until_ready(url, is_done, interval=3, timeout=300):
    deadline = time.time() + timeout
    while time.time() < deadline:
        resource = requests.get(url, headers=headers).json()
        if is_done(resource):
            return resource
        time.sleep(interval)
    raise TimeoutError(url)
```

</CodeTabs>

## Images

```bash
curl -X POST https://api.genuineai.app/api/v1/studio/generate-image \
  -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "A harbor at golden hour, wide", "aspect_ratio": "16:9"}'
```

Ten aspect ratios are available, from `1:1` through `21:9`, and they are listed in the
[reference](/reference).

The generated image **is stored like any other file, with the prompt kept alongside it**,
so generated images stay findable later rather than only being downloadable at the moment
of creation.

They live in the `generated` repository (everything the platform produced, as against the
`media` library of what people uploaded), so this lists them:

```
GET /media-files?repo_type=generated
```

The free-text `search` covers their prompts, and `contentType` narrows to `image` or
`infographic`. An image generated inside a conversation also belongs to that conversation
and is returned by `GET /threads/{id}/files`.

One consequence: generated images never get analysis embeddings, so [similar-image
search](/ai-enrichment#similar-images) returns an empty list for them. That is expected
rather than a fault.

## Edit images

Three operations work on images already in the library. All are under designs and all are
gated on **module-design**:

| | |
|---|---|
| `POST /designs/remove-background` | Knocks out the background of `file_id`. |
| `POST /designs/edit-image` | Inpainting. Send `mode` (`erase` or `fill`), a PNG `mask` marking the region, and a `prompt` for what to put there. Only what the mask covers is regenerated. |
| `POST /designs/generate-image` | Generates for a design. With `transparent: true` the subject is generated against a knocked-out backdrop, so it sits over the design rather than in a box. |

`POST /designs/generate-from-background` goes the other way: hand it a background
image and it builds a design around it, given a `platform` and optional
`instructions` and `caption`.

### A design's files

```
GET /designs/{id}/files
```

Returns what belongs to one design: the assets placed on it and the previews rendered
from it. The design's own access rules apply on top of each file's, so a caller who cannot
open the design does not receive its assets either.

### Design categories

Designs are filed into the workspace's own taxonomy. `GET /design-categories` lists it
(every workspace starts with a small set it can rename or remove), `PUT
/design-categories` replaces it, and `PUT /designs/{id}/categories` files one design.
Category ids appear on the design as `de_categories`.

## Infographics

Two generators produce genuinely different results from the same brief:

```bash
# a picture
curl -X POST https://api.genuineai.app/api/v1/studio/generate-infographic \
  -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "brief": "Q3 signups by region",
    "size": "wide",
    "style": "editorial",
    "data": {"kind": "ds"}
  }'
```

| | |
|---|---|
| `POST /studio/generate-infographic` | Produces HTML and a PNG of it, linked as one file. |
| `POST /studio/generate-infographic-native` | Produces a **design**: real text layers and real chart objects, editable in the design editor. Requires **module-design**. |

The native form's charts stay bound to the data they were built from, so refreshing one
re-reads the source instead of redrawing a picture. Use the first for a one-off, and the
second when someone will edit the result or it must stay current.

`data.kind` is `none`, `text`, `file` or `ds`, the last pointing at a [knowledge
base](/knowledge-bases). `GET /studio/infographic-options` lists the sizes and styles the
composer accepts; read it rather than hard-coding the list.

### Schedule a refresh

```bash
curl -X PUT https://api.genuineai.app/api/v1/infographics/<id>/schedule \
  -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "cadence": "weekly"}'
```

Re-reads the data source on a daily, weekly or monthly cadence and posts a new revision
each time. `POST /infographics/{id}/refresh` runs one immediately. Only the figures
change; the design does not drift.

**Only an infographic with a stored brief can be scheduled**, since without one there is
nothing to regenerate from.

`GET /infographics/{id}/versions` lists revisions, so a figure that changed can be traced.
`download-png` and `download-html` fetch the output, `snapshot-png` renders an edited
version, and `to-design` converts a picture into an editable design.

## Presentations

The only true pipeline here, marked `beta` and gated on **module-ppt**.

```
POST /presentations/plan   →  an outline you can review and edit
POST /presentations        →  202, generation queued
GET  /presentations/{id}   →  poll until status is ready
```

**Plan first.** `POST /presentations/plan` turns a brief and a template into a proposed
outline and saves it onto the draft:

```bash
curl -X POST https://api.genuineai.app/api/v1/presentations/plan \
  -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "3f2a9c1e-…",
    "brief": {
      "topic": "Q3 results",
      "audience": "Board",
      "slideCount": 12,
      "instructions": "Lead with the revenue story"
    }
  }'
```

Nothing is generated yet: this is the step where the structure is reviewed. Then
generate, passing the plan back:

```bash
curl -X POST https://api.genuineai.app/api/v1/presentations \
  -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \
  -H "Content-Type: application/json" \
  -d '{"templateId": "3f2a9c1e-…", "brief": {…}, "plan": {"slides": [ … ]}}'
```

That answers **202**. Poll `GET /presentations/{id}`, which carries `ppt_job_status` and,
once finished, `ppt_job_output_file_id`: the deck, downloadable like any other file.

### Fix a single slide

Regenerating a whole deck because one image is wrong is rarely what you want:

| | |
|---|---|
| `POST /presentations/{id}/images/regenerate` | Takes `slideIndex` and `slotName`. Finds the best library photo for that slide and generates a fresh image seeded by it. |
| `POST /presentations/{id}/images/select` | Choose a different image by hand. |
| `POST /presentations/{id}/rebuild` | Rebuilds the file from current content, including every image override. |

Both image operations are recorded as overrides on the same terms, so a rebuild preserves
them. The loop is: generate, fix the slides that need it, then rebuild.

`POST /presentations/draft` saves work in progress, and `duplicate` and `rename` do what
their names suggest.

## Which endpoint for which job

| You want | Use |
|---|---|
| A new image, now | `POST /studio/generate-image` |
| An image without its background | `POST /designs/remove-background` |
| To change part of an image | `POST /designs/edit-image` |
| A chart-style graphic, one-off | `POST /studio/generate-infographic` |
| A chart-style graphic someone will edit or that must stay current | `POST /studio/generate-infographic-native` + a schedule |
| A deck | `plan` → `POST /presentations` → poll |

## Next steps

- [Usage and credits](/usage-and-credits) explains what all of this costs and how to watch it.
- [AI enrichment](/ai-enrichment) covers the analysis that makes generated files findable.
- [Organizing and finding assets](/organizing-assets) shows where generated output lands.
