Agent-skill-layerproof slide-decks
Public API slide deck operations (X-API-KEY). Generate outlines, update outline, get deck, batch generate slides, generate transcript/image/content, cancel, theme, transcript, duplicate section. Types follow PublicApiSlideDeckController (/api/v2/projects/{projectId}/slide-deck/{slideDeckId}).
git clone https://github.com/compilet-dev/agent-skill-layerproof
T=$(mktemp -d) && git clone --depth=1 https://github.com/compilet-dev/agent-skill-layerproof "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/slide-decks" ~/.claude/skills/compilet-dev-agent-skill-layerproof-slide-decks && rm -rf "$T"
skills/slide-decks/SKILL.mdSkill: Slide Deck Generation
Description
Manage AI-generated slide decks and outlines. This skill documents the public API at
/api/v2/projects/{projectId}/slide-deck/{slideDeckId} (PublicApiSlideDeckController). All endpoints require projectId and slideDeckId in the path. Authenticate with X-API-KEY header. Poll async operations via GET /api/v2/jobs/{activityId}.
TypeScript types (request / response)
Mirrors
PublicApiSlideDeckController data classes.
// --- Outline section (used in UpdateOutlineRequest and responses) --- type PublicApiSlideIconAsset = { query: string; slot?: string | null }; type PublicApiSlideImageAsset = { prompt: string; slot?: string | null }; type PublicApiOutlineSection = { id: string; section_title: string; // 1–500 chars content?: string | null; // max 5000 key_points?: string[] | null; visual_suggestion?: string | null; // max 500 speaker_notes?: string | null; // max 2000 url_references?: string | null; layout?: string | null; icon_assets?: PublicApiSlideIconAsset[]; image_assets?: PublicApiSlideImageAsset[]; reference_image_paths?: string[]; slide_intent?: Record<string, unknown> | null; }; // --- Generate Outline (POST) — async --- type GenerateOutlineRequest = { prompt: string; // 3–2000 chars, required slide_count?: number; // default 5, min 1 language?: string; // 2–10 chars, e.g. "en" file_s3_keys?: string[]; // from POST /api/v2/files/prepare web_search_enabled?: boolean; text_detail_level?: string | null; tone?: string | null; }; type GenerateOutlineResponse = { activity_id: string; status: string; message: string; estimated_completion_seconds?: number; }; // --- Update Outline (PUT) --- type UpdateOutlineRequest = { title: string; // 1–500 chars sections: PublicApiOutlineSection[]; // at least one required }; type PublicApiOutline = { id: string; title: string; sections: PublicApiOutlineSection[]; total_sections: number; suggested_slide_count?: number | null; updated_at?: string; }; type UpdateOutlineResponse = { outline: PublicApiOutline }; // --- Get Deck (GET) --- type PublicApiSlideDeck = { id: string; project_id: string; title: string; description?: string | null; deck_type?: string | null; slide_numbers?: number | null; aspect_ratio: string; theme?: string | null; outline_generation_live_object_id?: string | null; created_at: string; updated_at: string; }; type PublicApiSlide = { id: string; index: number; section_id: string; section_title: string; content?: string | null; key_points?: string[] | null; visual_suggestion?: string | null; speaker_notes?: string | null; transcript?: string | null; image_url?: string | null; image_expires_at?: string | null; generation_status: string; error_message?: string | null; created_at: string; updated_at: string; }; type PublicApiDeckMetadata = { total_slides: number; completed_slides: number; pending_slides: number; overall_progress: number; }; type GetDeckResponse = { slide_deck: PublicApiSlideDeck; outline: PublicApiOutline; slides: PublicApiSlide[]; metadata: PublicApiDeckMetadata; }; // --- Batch Generate Slides (POST) — async --- type BatchGenerateSlidesRequest = { generation_type?: string; // default "BOTH" speaking_style?: string | null; target_duration_minutes?: number | null; // min 1 transcript_tone?: string | null; aspect_ratio?: string | null; output_language?: string | null; // 2–10 chars text_detail_level?: string | null; tone?: string | null; }; type BatchGenerateSlidesResponse = { activity_id: string; total_slides: number; status: string; message: string; estimated_completion_seconds: number; }; // --- Generate Slide Content / Transcript / Image (POST) — async --- type GenerateSlideContentRequest = { slide_section_id: string; speaking_style?: string | null; target_duration_minutes?: number | null; // min 1 transcript_tone?: string | null; generation_type?: string | null; // default "TRANSCRIPT_AND_IMAGE" }; type GenerateSlideContentResponse = { activity_id: string; slide_section_id: string; transcript_gen_live_object_id?: string | null; image_gen_live_object_id?: string | null; status: string; message: string; }; type GenerateSlideTranscriptRequest = { slide_section_id: string; speaking_style?: string | null; target_duration_minutes?: number | null; // min 1 transcript_tone?: string | null; }; type GenerateSlideTranscriptResponse = { activity_id: string; slide_section_id: string; transcript_gen_live_object_id: string; status: string; message: string; estimated_completion_seconds?: number; }; type GenerateSlideImageRequest = { slide_section_id: string; aspect_ratio?: string; // "16:9" | "4:3" | "1:1", default "16:9" }; type GenerateSlideImageResponse = { activity_id: string; slide_section_id: string; image_gen_live_object_id: string; status: string; message: string; estimated_completion_seconds?: number; }; // --- Cancel Generation (POST) --- type CancelGenerationRequest = { live_object_ids?: string[] | null }; type CancelGenerationResponse = { cancelled_live_objects: string[]; failed_to_cancel_live_objects: string[]; total_activities_cancelled: number; message: string; }; // --- Generate Theme (POST) — async --- type GenerateThemeRequest = { prompt: string; // 10–2000 chars reference_image_paths?: string[] | null; }; type GenerateThemeResponse = { activity_id: string; status: string; message: string; estimated_completion_seconds: number; }; // --- Update Transcript (PUT) --- type UpdateTranscriptRequest = { transcript: string }; type UpdateTranscriptResponse = { slide_section_id: string; version_id: string; version_number: number; transcript_gen_live_object_id: string; transcript: string; updated_at: string; }; // --- Duplicate Section (POST) --- type DuplicateSectionRequest = { copy_content?: boolean; insert_after?: boolean; }; type DuplicateSectionResponse = { new_section_id: string; new_section: PublicApiOutlineSection; transcript_gen_live_object_id?: string | null; image_gen_live_object_id?: string | null; message: string; };
Generate Outline (async)
Request body:
GenerateOutlineRequest. Response (202): GenerateOutlineResponse.
Starts outline generation from a prompt. Use
file_s3_keys from files uploaded via /api/v2/files/prepare and confirm. Poll GET /api/v2/jobs/{activityId} for status.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/outline/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Create a product launch deck","slide_count":6}'
With reference files and language:
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/outline/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Q4 strategy","slide_count":5,"language":"en","file_s3_keys":["public-api/.../file.pdf"],"web_search_enabled":true}'
Update Outline
Request body:
UpdateOutlineRequest. Response: UpdateOutlineResponse.
Updates outline title and sections (add, remove, reorder). At least one section required.
curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/outline" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"title":"My Deck","sections":[{"id":"section-uuid","section_title":"Intro","content":"...","speaker_notes":"..."}]}'
Get Full Slide Deck
Query:
include_images (default true), image_expiry_seconds (default 3600). Response: GetDeckResponse.
Returns deck, outline, slides with presigned image URLs, and metadata.
curl "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/?include_images=true&image_expiry_seconds=3600" \ -H "X-API-KEY: $LAYERPROOF_API_KEY"
Batch Generate Slides (async)
Request body:
BatchGenerateSlidesRequest. Response (202): BatchGenerateSlidesResponse.
Generate transcript and/or images for all outline sections. Requires an outline first. Poll jobs with
activity_id.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/slides/batch-generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"generation_type":"BOTH"}'
Generate Slide Content (async)
Request body:
GenerateSlideContentRequest. Response (202): GenerateSlideContentResponse.
Generate transcript and image for one section. Poll
GET /api/v2/jobs/{activityId}.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/slides/generate-content" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_section_id":"<section_uuid>"}'
Generate Slide Transcript (async)
Request body:
GenerateSlideTranscriptRequest. Response (202): GenerateSlideTranscriptResponse.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/slides/generate-transcript" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_section_id":"<section_uuid>"}'
Generate Slide Image (async)
Request body:
GenerateSlideImageRequest. Response (202): GenerateSlideImageResponse.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/slides/generate-image" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_section_id":"<section_uuid>","aspect_ratio":"16:9"}'
Cancel Generation
Request body:
CancelGenerationRequest. Response: CancelGenerationResponse.
Provide
live_object_ids from active generation responses to cancel.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/cancel" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"live_object_ids":["<live_object_uuid>"]}'
Generate Deck Theme (async)
Request body:
GenerateThemeRequest. Response (202): GenerateThemeResponse.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/theme/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Minimal corporate blue"}'
Update Slide Transcript
Request body:
UpdateTranscriptRequest. Response: UpdateTranscriptResponse.
Path includes
slideSectionId: PUT .../slides/{slideSectionId}/transcript.
curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/slides/<slide_section_id>/transcript" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"transcript":"Updated speaker notes."}'
Duplicate Slide Section
Request body:
DuplicateSectionRequest. Response: DuplicateSectionResponse.
Path includes
slideSectionId: POST .../slides/{slideSectionId}/duplicate.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slide-deck/<slide_deck_id>/slides/<slide_section_id>/duplicate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"copy_content":true,"insert_after":true}'
Agent behavior
When the user asks to work with slide decks (outline, deck, slides, theme, transcript), do the following.
1. Choose the right endpoint
Base path:
/api/v2/projects/{projectId}/slide-deck/{slideDeckId}. All require projectId and slideDeckId.
| User intent | Endpoint | Method |
|---|---|---|
| Generate outline from prompt | | POST |
| Update outline structure | | PUT |
| Get full deck (outline + slides + URLs) | (with optional query) | GET |
| Batch generate all slides | | POST |
| Generate one slide content | | POST |
| Generate one slide transcript | | POST |
| Generate one slide image | | POST |
| Cancel generations | | POST |
| Generate deck theme | | POST |
| Update slide transcript | | PUT |
| Duplicate section | | POST |
| Improve section (AI) | | POST |
| Manual slide generation | | POST |
| Patch visual style description | | PATCH |
| List / restore transcript versions | (GET), (POST) | GET / POST |
| Mark transcript / improvement / live object read | , , | PATCH |
| Text-to-speech | (POST), (GET) | POST / GET |
| Update deck settings (aspect ratio, etc.) | (slide-deck root) | PATCH |
| Tone settings | | GET / PUT |
| Batch Konva layout | | POST |
| PPTX import | , | POST |
| Citations | , , | GET |
2. Build and run the request
Step 1 — Check environment variables first. Before running any curl command, verify both
LAYERPROOF_BASE_URL and LAYERPROOF_API_KEY are set on the user's machine:
if [[ -z "${LAYERPROOF_BASE_URL}" ]]; then echo "ERROR: LAYERPROOF_BASE_URL is not set." return 1 fi if [[ -z "${LAYERPROOF_API_KEY}" ]]; then echo "ERROR: LAYERPROOF_API_KEY is not set." return 1 fi
If running from a project directory with a
.env.local file, load it first:
if [[ -f .env.local ]]; then set -a source .env.local set +a fi
Step 2 — Auth: Every request must include
X-API-KEY: $LAYERPROOF_API_KEY. Read LAYERPROOF_BASE_URL and LAYERPROOF_API_KEY from the environment; if missing, tell the user to set them.
Step 3 — Path: Resolve projectId and slideDeckId (and slideSectionId where needed) from context or user input. If missing, ask.
Step 4 — GET: Build curl with path and query params (include_images, image_expiry_seconds for get deck). Run and show result.
Step 5 — POST/PUT: Build JSON body from the types above. Use -X POST or -X PUT, -H "Content-Type: application/json", and -d '...'. Run and show result.
3. After async endpoints
- Responses include
. Tell the user the job was started and suggest pollingactivity_id
untilGET $LAYERPROOF_BASE_URL/api/v2/jobs/{activityId}
isstatus
orDONE
.CANCELED - Typical flow: generate outline → poll until DONE → get deck or update outline → batch generate slides or generate single slide content/transcript/image → poll jobs.
4. Response handling
- Always show the raw JSON response in a JSON code block; do not convert to a table.
- If the response contains image URLs (e.g. in get deck
), show images and the JSON.slides[].image_url - On error (4xx/5xx), show the response body and status code; suggest fixing API key, projectId/slideDeckId/sectionId, or request body.
5. Example workflows
Workflow A — User: "Generate an outline for a product launch deck in project X."
- Resolve projectId and slideDeckId (e.g. from GET projects, then
).project.slide_deck_id - Choose
.POST .../outline/generate - Build body:
.{"prompt":"Product launch deck","slide_count":5} - Run curl; show JSON. Tell user to poll
and then call get deck or update outline as needed.GET /api/v2/jobs/{activityId}
Workflow B — User: "Full deck: outline from a prompt and reference PDF, then tweak the outline, apply a theme, batch generate slides, and fix one slide’s image."
- Resolve projectId and slideDeckId. Get
from public-files (prepare → upload → confirm) or project-files if the API accepts them for outline.file_s3_keys - POST
with.../outline/generate
; capture{"prompt":"Product launch with pricing","slide_count":6,"file_s3_keys":["<s3_key>"],"language":"en"}
.activity_id - Poll
until DONE. On failure, report and stop.GET /api/v2/jobs/{activity_id} - GET deck; from
identify a section to change. PUToutline.sections
with.../outline
and updatedtitle
(e.g. editsections
,section_title
,key_points
for one section).visual_suggestion - If user wants a theme: use themes skill — POST
with/api/v2/themes/apply
andslide_deck_id
(settheme_id
if images should be regenerated); poll job whenregenerate_slides
is returned.activity_id - POST
with optional.../batch-generate
,generation_type
,aspect_ratio
; capturespeaking_style
.activity_id - Poll
until DONE.GET /api/v2/jobs/{activity_id} - GET deck; check
andmetadata.completed_slides
. If one slide’s image is wrong, POSTslides[].generation_status
(or generate-content) with section id; poll that job until DONE; GET deck again to show result..../slides/{sectionId}/generate-image
Workflow C — User: "Duplicate a section in the outline and regenerate slides for the new section only."
- GET deck; from
pick aoutline.sections
(UUID string) to duplicate.section_id - POST
with.../slides/{slide_section_id}/duplicate
; read{"copy_content":true,"insert_after":true}
from the response.new_section_id - PUT
with updated.../outline
andtitle
array (merge/reorder the duplicated section as needed).sections - POST
|.../slides/generate-transcript
|generate-image
with the new section id; pollgenerate-content
; GET deck to confirm.GET /api/v2/jobs/{activity_id}
Response format (required)
- (if response contains url to show image) please show image and show json response instead of table
- Always show the raw JSON response (verbatim) in a JSON code block.
- If the response contains a URL for an image, render/show the image and also show the JSON response (do not convert to a table).