REST API reference

Beautiful.ai API

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
Beautiful.ai
Beautiful.ai 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.

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

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

Parameters: list_presentations
NameTypeDescription
query string Search titles.
folder string Only presentations in this folder.
limit integer 1 to 100. Default: 25.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/list_presentations \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("beautiful-ai", "list_presentations")
Node.js
const result = await cotlet.call('beautiful-ai', 'list_presentations');
CLI
cotlet call beautiful-ai list_presentations

Example response

{
  "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"
    }
  ]
}

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

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
curl -X POST https://cotlet.dev/api/v1/beautiful-ai/list_folders \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("beautiful-ai", "list_folders")
Node.js
const result = await cotlet.call('beautiful-ai', 'list_folders');
CLI
cotlet call beautiful-ai list_folders

Example response

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

Get slides

read

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

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

Parameters: get_slides
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.

Request

cURL
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
result = client.call("beautiful-ai", "get_slides", {"presentation_id":"presentation_8c41d2"})
Node.js
const result = await cotlet.call('beautiful-ai', 'get_slides', {"presentation_id":"presentation_8c41d2"});
CLI
cotlet call beautiful-ai get_slides --data '{"presentation_id":"presentation_8c41d2"}'

Example response

{
  "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
    }
  ]
}

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

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

Parameters: get_presentation_analytics
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.

Request

cURL
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
result = client.call("beautiful-ai", "get_presentation_analytics", {"presentation_id":"pres_8f3k2m9q"})
Node.js
const result = await cotlet.call('beautiful-ai', 'get_presentation_analytics', {"presentation_id":"pres_8f3k2m9q"});
CLI
cotlet call beautiful-ai get_presentation_analytics --data '{"presentation_id":"pres_8f3k2m9q"}'

Example response

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

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

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

Parameters

Parameters: list_collaborators
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.

Request

cURL
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
result = client.call("beautiful-ai", "list_collaborators", {"presentation_id":"presentation_8c41d2"})
Node.js
const result = await cotlet.call('beautiful-ai', 'list_collaborators', {"presentation_id":"presentation_8c41d2"});
CLI
cotlet call beautiful-ai list_collaborators --data '{"presentation_id":"presentation_8c41d2"}'

Example response

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

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

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

Parameters: update_slide_text
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
slide_number required integer Slide position in the deck, starting at 1.
find required string Exact text to replace.
replace required string New text.

Request

cURL
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
result = client.call("beautiful-ai", "update_slide_text", {"presentation_id":"pres_8f3k2m9q","slide_number":4,"find":"FY25 targets","replace":"FY26 targets"})
Node.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
cotlet call beautiful-ai update_slide_text --data '{"presentation_id":"pres_8f3k2m9q","slide_number":4,"find":"FY25 targets","replace":"FY26 targets"}'

Example response

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

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

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

Parameters: set_speaker_notes
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
slide_number required integer Slide position in the deck, starting at 1.
notes required string Notes text. Empty string clears them.

Request

cURL
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
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
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
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

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

Skip slide

write

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

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

Parameters: skip_slide
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
slide_number required integer Slide position in the deck, starting at 1.
skipped required boolean true to skip, false to show it again.

Request

cURL
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
result = client.call("beautiful-ai", "skip_slide", {"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":True})
Node.js
const result = await cotlet.call('beautiful-ai', 'skip_slide', {"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":true});
CLI
cotlet call beautiful-ai skip_slide --data '{"presentation_id":"presentation_8c41d2","slide_number":1,"skipped":true}'

Example response

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

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

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

Parameters: duplicate_presentation
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
title string Title of the copy. Default: same as the original.

Request

cURL
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
result = client.call("beautiful-ai", "duplicate_presentation", {"presentation_id":"presentation_8c41d2"})
Node.js
const result = await cotlet.call('beautiful-ai', 'duplicate_presentation', {"presentation_id":"presentation_8c41d2"});
CLI
cotlet call beautiful-ai duplicate_presentation --data '{"presentation_id":"presentation_8c41d2"}'

Example response

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

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

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

Parameters: move_to_folder
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
folder required string Folder name from list_folders.

Request

cURL
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
result = client.call("beautiful-ai", "move_to_folder", {"presentation_id":"presentation_8c41d2","folder":"folder"})
Node.js
const result = await cotlet.call('beautiful-ai', 'move_to_folder', {"presentation_id":"presentation_8c41d2","folder":"folder"});
CLI
cotlet call beautiful-ai move_to_folder --data '{"presentation_id":"presentation_8c41d2","folder":"folder"}'

Example response

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

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

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

Parameters: export_presentation
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
format required enum pdf or pptx.

Request

cURL
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
result = client.call("beautiful-ai", "export_presentation", {"presentation_id":"presentation_8c41d2","format":"pdf"})
Node.js
const result = await cotlet.call('beautiful-ai', 'export_presentation', {"presentation_id":"presentation_8c41d2","format":"pdf"});
CLI
cotlet call beautiful-ai export_presentation --data '{"presentation_id":"presentation_8c41d2","format":"pdf"}'

Example response

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

Invite collaborator

write Confirm

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

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

Parameters: invite_collaborator
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
email required string Email of the person to invite.
permission required enum can_edit or can_view.

Request

cURL
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
result = client.call("beautiful-ai", "invite_collaborator", {"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"})
Node.js
const result = await cotlet.call('beautiful-ai', 'invite_collaborator', {"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"});
CLI
cotlet call beautiful-ai invite_collaborator --data '{"presentation_id":"presentation_8c41d2","email":"jane@example.com","permission":"can_edit"}'

Example response

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

Remove collaborator

write Confirm

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

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

Parameters: remove_collaborator
NameTypeDescription
presentation_id required string Presentation ID from list_presentations.
email required string Email from list_collaborators.

Request

cURL
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
result = client.call("beautiful-ai", "remove_collaborator", {"presentation_id":"presentation_8c41d2","email":"jane@example.com"})
Node.js
const result = await cotlet.call('beautiful-ai', 'remove_collaborator', {"presentation_id":"presentation_8c41d2","email":"jane@example.com"});
CLI
cotlet call beautiful-ai remove_collaborator --data '{"presentation_id":"presentation_8c41d2","email":"jane@example.com"}'

Example response

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