# Beautiful.ai API

> Every Beautiful.ai endpoint on Cotlet: inputs, JSON Schema, cURL, Python and Node.js examples and an example response for each call.

Source: https://cotlet.dev/docs/api/beautiful-ai

Docs sections: [Get started](https://cotlet.dev/docs.md) · [REST API](https://cotlet.dev/docs/api.md) · [MCP](https://cotlet.dev/docs/mcp.md) · [SDKs & CLI](https://cotlet.dev/docs/sdks.md) · [Integrations](https://cotlet.dev/docs/integrations.md)

14 endpoints for Beautiful.ai. Each one is a POST with a JSON body, called with your API key.

- Base URL: `https://cotlet.dev/api/v1/beautiful-ai`
- Connects with: Your own Beautiful.ai account (email and password, or Google or Microsoft sign-in)
- Integration page: https://cotlet.dev/integrations/beautiful-ai-api-mcp-server

## Endpoints

| Endpoint | Access | Description |
|---|---|---|
| `list_presentations` | read | Presentations in your library and shared folders, newest first, with folder, slide count and owner. |
| `list_folders` | read | Your folders, including shared workspace folders, with the number of decks in each. |
| `get_slides` | read | Every slide in order: layout, text, speaker notes and whether it is skipped. |
| `get_presentation_analytics` | read | Viewer and slide analytics for a deck, as the app shows them. |
| `list_collaborators` | read | People with access to a presentation and whether they can edit or view. |
| `update_slide_text` | write | Replace text on one slide, keeping its Smart Slide layout. |
| `set_speaker_notes` | write | Write or replace the speaker notes of a slide. |
| `skip_slide` | write | Skip or unskip a slide when presenting. |
| `duplicate_presentation` | write | Copy any presentation in your library, as the Duplicate menu item does. |
| `move_to_folder` | write | Put a presentation in one of your folders. |
| `export_presentation` | write | Export the deck and return a download link. |
| `invite_collaborator` | write | Invite someone by email to edit or view a presentation. They get an email. |
| `remove_collaborator` | write | Revoke a collaborator's access to a presentation. |
| `create_share_link` | write | Share the presentation and return a link to it. |

## List presentations

`POST https://cotlet.dev/api/v1/beautiful-ai/list_presentations`

Access: read.

Returns decks you can open, newest first. Filter by title keyword or folder. Pass presentation_id from each item to the other tools. Pages hold up to 100 decks.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `query` | string | no | Search titles. |
| `folder` | string | no | Only presentations in this folder. |
| `limit` | integer | no | 1 to 100. Default: 25. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/list_presentations \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("beautiful-ai", "list_presentations")
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'list_presentations');
```

**CLI**

```bash
cotlet call beautiful-ai list_presentations
```

### Example response

```json
{
  "presentations": [
    {
      "presentation_id": "pres_8f3k2m9q",
      "title": "Q3 QBR",
      "folder": "Sales",
      "slides": 18,
      "owner": "You",
      "updated_at": "2026-10-08T14:20:00Z"
    },
    {
      "presentation_id": "pres_2q7w1x5c",
      "title": "Investor update",
      "folder": null,
      "slides": 12,
      "owner": "You",
      "updated_at": "2026-10-05T09:02:00Z"
    }
  ]
}
```

## List folders

`POST https://cotlet.dev/api/v1/beautiful-ai/list_folders`

Access: read.

Returns folders by name with deck counts. Use the name as the folder parameter of list_presentations and move_to_folder.

### Parameters

No parameters.

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/list_folders \
  -H "Authorization: Bearer $COTLET_API_KEY"
```

**Python**

```python
result = client.call("beautiful-ai", "list_folders")
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'list_folders');
```

**CLI**

```bash
cotlet call beautiful-ai list_folders
```

### Example response

```json
{
  "folders": [
    {
      "name": "Sales",
      "presentations": 14,
      "shared": true
    },
    {
      "name": "Board",
      "presentations": 6,
      "shared": false
    }
  ]
}
```

## Get slides

`POST https://cotlet.dev/api/v1/beautiful-ai/get_slides`

Access: read.

Returns the slides of one deck in order, starting at 1. Text is listed in reading order per slide. Use it before update_slide_text so your agent sees what is on each slide.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/get_slides \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2"}'
```

**Python**

```python
result = client.call("beautiful-ai", "get_slides", {"presentation_id":"presentation_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'get_slides', {"presentation_id":"presentation_8c41d2"});
```

**CLI**

```bash
cotlet call beautiful-ai get_slides --data '{"presentation_id":"presentation_8c41d2"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "slides": [
    {
      "slide_number": 1,
      "layout": "Title",
      "text": [
        "Q3 QBR",
        "Sales team"
      ],
      "speaker_notes": "",
      "skipped": false
    },
    {
      "slide_number": 4,
      "layout": "Bullets",
      "text": [
        "FY25 targets",
        "Grow ARR 40%",
        "Launch in two new regions"
      ],
      "speaker_notes": "Mention the EU launch date.",
      "skipped": false
    }
  ]
}
```

## Get presentation analytics

`POST https://cotlet.dev/api/v1/beautiful-ai/get_presentation_analytics`

Access: read.

Returns the viewer and slide analytics Beautiful.ai shows for one deck. Availability depends on your plan; without it the call fails with an error that names the plan.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/get_presentation_analytics \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"pres_8f3k2m9q"}'
```

**Python**

```python
result = client.call("beautiful-ai", "get_presentation_analytics", {"presentation_id":"pres_8f3k2m9q"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'get_presentation_analytics', {"presentation_id":"pres_8f3k2m9q"});
```

**CLI**

```bash
cotlet call beautiful-ai get_presentation_analytics --data '{"presentation_id":"pres_8f3k2m9q"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "views": 14,
  "unique_viewers": 9,
  "slides": [
    {
      "slide_number": 1,
      "views": 14
    },
    {
      "slide_number": 4,
      "views": 11
    }
  ]
}
```

## List collaborators

`POST https://cotlet.dev/api/v1/beautiful-ai/list_collaborators`

Access: read.

Returns each person with access to the deck, with email and permission. Use the email in remove_collaborator.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/list_collaborators \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2"}'
```

**Python**

```python
result = client.call("beautiful-ai", "list_collaborators", {"presentation_id":"presentation_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'list_collaborators', {"presentation_id":"presentation_8c41d2"});
```

**CLI**

```bash
cotlet call beautiful-ai list_collaborators --data '{"presentation_id":"presentation_8c41d2"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "collaborators": [
    {
      "email": "anna@example.com",
      "permission": "can_edit"
    },
    {
      "email": "tom@example.com",
      "permission": "can_view"
    }
  ]
}
```

## Update slide text

`POST https://cotlet.dev/api/v1/beautiful-ai/update_slide_text`

Access: write.

Replaces exact text on one slide and keeps its layout. Returns the number of matches replaced and the slide text after the change. It reaches no one and one call undoes it, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `slide_number` | integer | yes | Slide position in the deck, starting at 1. |
| `find` | string | yes | Exact text to replace. |
| `replace` | string | yes | New text. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/update_slide_text \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"pres_8f3k2m9q","slide_number":4,"find":"FY25 targets","replace":"FY26 targets"}'
```

**Python**

```python
result = client.call("beautiful-ai", "update_slide_text", {"presentation_id":"pres_8f3k2m9q","slide_number":4,"find":"FY25 targets","replace":"FY26 targets"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'update_slide_text', {"presentation_id":"pres_8f3k2m9q","slide_number":4,"find":"FY25 targets","replace":"FY26 targets"});
```

**CLI**

```bash
cotlet call beautiful-ai update_slide_text --data '{"presentation_id":"pres_8f3k2m9q","slide_number":4,"find":"FY25 targets","replace":"FY26 targets"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "slide_number": 4,
  "replaced": 1,
  "slide_text": [
    "FY26 targets",
    "Grow ARR 40%",
    "Launch in two new regions"
  ]
}
```

## Set speaker notes

`POST https://cotlet.dev/api/v1/beautiful-ai/set_speaker_notes`

Access: write.

Replaces the speaker notes of one slide with the text you send. An empty string clears them. It reaches no one and one call undoes it, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `slide_number` | integer | yes | Slide position in the deck, starting at 1. |
| `notes` | string | yes | Notes text. Empty string clears them. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/set_speaker_notes \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"pres_2q7w1x5c","slide_number":2,"notes":"Open with the churn drop. Pause for questions before the pricing slide."}'
```

**Python**

```python
result = client.call("beautiful-ai", "set_speaker_notes", {"presentation_id":"pres_2q7w1x5c","slide_number":2,"notes":"Open with the churn drop. Pause for questions before the pricing slide."})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'set_speaker_notes', {"presentation_id":"pres_2q7w1x5c","slide_number":2,"notes":"Open with the churn drop. Pause for questions before the pricing slide."});
```

**CLI**

```bash
cotlet call beautiful-ai set_speaker_notes --data '{"presentation_id":"pres_2q7w1x5c","slide_number":2,"notes":"Open with the churn drop. Pause for questions before the pricing slide."}'
```

### Example response

```json
{
  "presentation_id": "pres_2q7w1x5c",
  "slide_number": 2,
  "speaker_notes": "Open with the churn drop. Pause for questions before the pricing slide."
}
```

## Skip slide

`POST https://cotlet.dev/api/v1/beautiful-ai/skip_slide`

Access: write.

Marks one slide as skipped, so it is left out when presenting, or shows it again. It reaches no one and one call undoes it, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `slide_number` | integer | yes | Slide position in the deck, starting at 1. |
| `skipped` | boolean | yes | true to skip, false to show it again. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/skip_slide \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":true}'
```

**Python**

```python
result = client.call("beautiful-ai", "skip_slide", {"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":True})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'skip_slide', {"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":true});
```

**CLI**

```bash
cotlet call beautiful-ai skip_slide --data '{"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":true}'
```

### Example response

```json
{
  "presentation_id": "pres_2q7w1x5c",
  "slide_number": 7,
  "skipped": true
}
```

## Duplicate presentation

`POST https://cotlet.dev/api/v1/beautiful-ai/duplicate_presentation`

Access: write.

Creates a copy of the deck in your library and returns its ID. The copy is private to you until you share it, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `title` | string | no | Title of the copy. Default: same as the original. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/duplicate_presentation \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2"}'
```

**Python**

```python
result = client.call("beautiful-ai", "duplicate_presentation", {"presentation_id":"presentation_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'duplicate_presentation', {"presentation_id":"presentation_8c41d2"});
```

**CLI**

```bash
cotlet call beautiful-ai duplicate_presentation --data '{"presentation_id":"presentation_8c41d2"}'
```

### Example response

```json
{
  "presentation_id": "pres_9k4m6b2v",
  "source_id": "pres_5d9a4r1t",
  "title": "Sales review, November",
  "slides": 16
}
```

## Move to folder

`POST https://cotlet.dev/api/v1/beautiful-ai/move_to_folder`

Access: write.

Moves a deck into a folder from list_folders. People with access to that folder can then see it. One call moves it back, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `folder` | string | yes | Folder name from list_folders. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/move_to_folder \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2","folder":"folder"}'
```

**Python**

```python
result = client.call("beautiful-ai", "move_to_folder", {"presentation_id":"presentation_8c41d2","folder":"folder"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'move_to_folder', {"presentation_id":"presentation_8c41d2","folder":"folder"});
```

**CLI**

```bash
cotlet call beautiful-ai move_to_folder --data '{"presentation_id":"presentation_8c41d2","folder":"folder"}'
```

### Example response

```json
{
  "presentation_id": "pres_9k4m6b2v",
  "folder": "Sales"
}
```

## Export presentation

`POST https://cotlet.dev/api/v1/beautiful-ai/export_presentation`

Access: write.

Exports one deck and returns a download link. Formats follow your Beautiful.ai plan. The export changes nothing in the deck and reaches no one, so it runs without asking.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `format` | enum | yes | pdf or pptx. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/export_presentation \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2","format":"pdf"}'
```

**Python**

```python
result = client.call("beautiful-ai", "export_presentation", {"presentation_id":"presentation_8c41d2","format":"pdf"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'export_presentation', {"presentation_id":"presentation_8c41d2","format":"pdf"});
```

**CLI**

```bash
cotlet call beautiful-ai export_presentation --data '{"presentation_id":"presentation_8c41d2","format":"pdf"}'
```

### Example response

```json
{
  "presentation_id": "pres_2q7w1x5c",
  "format": "pdf",
  "download_url": "https://www.beautiful.ai/export/exp_71c0aa.pdf"
}
```

## Invite collaborator

`POST https://cotlet.dev/api/v1/beautiful-ai/invite_collaborator`

Access: write. Confirm: waits for the user's OK before it runs.

Gives one person access to the deck and emails them. Permission is can_edit or can_view. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `email` | string | yes | Email of the person to invite. |
| `permission` | enum | yes | can_edit or can_view. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/invite_collaborator \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"}'
```

**Python**

```python
result = client.call("beautiful-ai", "invite_collaborator", {"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'invite_collaborator', {"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"});
```

**CLI**

```bash
cotlet call beautiful-ai invite_collaborator --data '{"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "email": "anna@example.com",
  "permission": "can_edit",
  "status": "invited"
}
```

## Remove collaborator

`POST https://cotlet.dev/api/v1/beautiful-ai/remove_collaborator`

Access: write. Confirm: waits for the user's OK before it runs.

Removes one person from the deck. They lose access at once. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `email` | string | yes | Email from list_collaborators. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/remove_collaborator \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2","email":"jane@example.com"}'
```

**Python**

```python
result = client.call("beautiful-ai", "remove_collaborator", {"presentation_id":"presentation_8c41d2","email":"jane@example.com"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'remove_collaborator', {"presentation_id":"presentation_8c41d2","email":"jane@example.com"});
```

**CLI**

```bash
cotlet call beautiful-ai remove_collaborator --data '{"presentation_id":"presentation_8c41d2","email":"jane@example.com"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "email": "tom@example.com",
  "status": "removed"
}
```

## Create share link

`POST https://cotlet.dev/api/v1/beautiful-ai/create_share_link`

Access: write. Confirm: waits for the user's OK before it runs.

Makes the deck viewable through a link and returns the link. Anyone who gets the link can open the deck. By default you confirm each call; you can switch that off for this tool.

### Parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `presentation_id` | string | yes | Presentation ID from list_presentations. |
| `name` | string | no | Link name, to tell links apart. |

### Request

**cURL**

```bash
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/create_share_link \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"presentation_id":"presentation_8c41d2"}'
```

**Python**

```python
result = client.call("beautiful-ai", "create_share_link", {"presentation_id":"presentation_8c41d2"})
```

**Node.js**

```js
const result = await cotlet.call('beautiful-ai', 'create_share_link', {"presentation_id":"presentation_8c41d2"});
```

**CLI**

```bash
cotlet call beautiful-ai create_share_link --data '{"presentation_id":"presentation_8c41d2"}'
```

### Example response

```json
{
  "presentation_id": "pres_8f3k2m9q",
  "name": "Investors",
  "url": "https://www.beautiful.ai/player/pres_8f3k2m9q",
  "status": "shared"
}
```
