slide generation layerproof logo

slide generation layerproof

0

agent-skill-layerproof plugin for Cursor

11 skills

exports

Public API export (X-API-KEY). Export PNG ZIP, PPTX, or video (async), get status, cancel. PublicApiExportController.

# Skill: Export Slides ## Description Export presentations as PNG ZIP, PPTX, or **narrated video** (Pro / credits). This skill documents the **public API** at `/api/v2/projects/{projectId}/exports` (PublicApiExportController). Exports are async: POST returns `export_id` (same id used for job-style polling); poll GET `.../exports/{export_id}` for status; when COMPLETED, use `download_url` (presigned, ~1 hour). Authenticate with `X-API-KEY` header. --- ## TypeScript types (request / response) Mirrors `PublicApiExportController` data classes. ```typescript // --- Export PNG / PPTX / Video (POST) — 202 --- type PublicExportStartedResponse = { export_id: string; // UUID — poll GET .../exports/{export_id} status?: string; // default "PENDING" }; // --- Video export body (POST .../exports/video) — optional --- type PublicVideoExportRequest = { quality?: string | null; // export quality enum as returned by API include_notes?: boolean; // default false voice?: string | null; // default "Puck" language_code?: string | null; // default "en-US" }; // --- Get Export Status (GET) --- type PublicExportProgress = { current: number; total: number }; type PublicExportStatusData = { export_id: string; status: string; format: string; download_url?: string | null; expires_at?: string | null; file_size_bytes?: number | null; progress?: PublicExportProgress | null; error_message?: string | null; }; type PublicExportStatusResponse = { data: PublicExportStatusData }; // --- Cancel Export (POST) --- type PublicCancelExportResponse = { export_id: string; status: string; // "CANCELLED" or "ALREADY_TERMINAL" }; ``` --- ## Export PNG ZIP (async) Response (202): `PublicExportStartedResponse`. Poll GET .../exports/{exportId} for status. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/exports/png" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Export PPTX (async) Response (202): `PublicExportStartedResponse`. Poll GET .../exports/{exportId} for status. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/exports/pptx" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Export Video (async) Narrated video with TTS. May return **402** (quota) or **403** (Pro plan required). Optional JSON body: `PublicVideoExportRequest`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/exports/video" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"include_notes":false,"voice":"Puck","language_code":"en-US"}' ``` --- ## Get Export Status Response: `PublicExportStatusResponse`. When status is COMPLETED, `data.downloadUrl` and `data.expiresAt` are set. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/exports/<export_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Cancel Export Response: `PublicCancelExportResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/exports/<export_id>/cancel" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Agent behavior When the user asks to export a project (PNG ZIP or PPTX) or check/cancel an export, do the following. ### 1. Choose the right endpoint Base path: `/api/v2/projects/{projectId}/exports`. All require `projectId`. | User intent | Endpoint | Method | |-------------|----------|--------| | Export as PNG ZIP | `.../exports/png` | POST | | Export as PPTX | `.../exports/pptx` | POST | | Export as video (TTS) | `.../exports/video` | POST | | Get export status / download URL | `.../exports/{exportId}` | GET | | Cancel in-progress export | `.../exports/{exportId}/cancel` | POST | ### 2. Build and run - **Auth**: Include `X-API-KEY: $LAYERPROOF_API_KEY`. Read env vars; if missing, tell the user. - **Path**: Resolve projectId from context; exportId from the 202 response of export PNG/PPTX. - Run curl and show the result. ### 3. After starting export - Response contains `export_id`. Tell the user to poll GET .../exports/{export_id} until status is COMPLETED (or FAILED). When COMPLETED, use `data.download_url` (valid ~1 hour). ### 4. Response handling - Always show raw JSON in a code block. - If `download_url` is present, show the URL and mention the file can be downloaded. - On 410, download URL expired; suggest triggering a new export. ### 5. Example workflows **Workflow A — User**: "Export my project as PPTX and give me the download link." 1. Resolve projectId. POST `.../projects/{projectId}/exports/pptx`; capture `export_id` from 202 response. 2. Poll GET `.../projects/{projectId}/exports/{export_id}` until `data.status` is COMPLETED or FAILED. If FAILED, show `data.error_message` and suggest retry or checking project/slides. 3. When COMPLETED, show `data.download_url` and `data.expires_at`; remind user the URL is temporary (~1 hour). **Workflow B — User**: "Export the same project as both PNG ZIP and PPTX; if one fails, still get the other." 1. POST `.../exports/png`; get `export_id_png`. POST `.../exports/pptx`; get `export_id_pptx`. 2. Poll both: GET `.../exports/{export_id_png}` and GET `.../exports/{export_id_pptx}` (e.g. in sequence or inform user to poll). For each: when COMPLETED, show `download_url`; when FAILED, show `error_message` and which format failed. 3. Optionally: if user wants to cancel the slower one, POST `.../exports/{export_id}/cancel` for the relevant export id. **Workflow C — User**: "Start a PPTX export; I might cancel it if it takes too long." 1. POST `.../exports/pptx`; get `export_id`. Tell user polling has started. 2. If user says "cancel the export" before COMPLETED: POST `.../exports/{export_id}/cancel`; show response (status CANCELLED or ALREADY_TERMINAL). 3. If not canceled: poll until COMPLETED and show `download_url`, or FAILED and show `error_message`. --- ## 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).

jobs

Public API job status polling (X-API-KEY). Poll async operations (outline, slides, exports, etc.) by activityId. Types follow PublicApiJobController (/api/v2/jobs/{activityId}).

# Skill: Job Monitoring ## Description Poll the status of asynchronous operations. This skill documents the **public API** at `/api/v2/jobs/{activityId}` (PublicApiJobController). The `activityId` is returned when you start async operations (e.g. outline/generate, batch-generate, export PNG/PPTX). Authenticate with `X-API-KEY` header. --- ## TypeScript types (request / response) Mirrors `PublicApiJobController` response. ```typescript // --- Get Job Status (GET) --- type JobStatusResponse = { activity_id: string; status: 'SCHEDULED' | 'RUNNING' | 'PENDING' | 'DONE' | 'CANCELED'; message: string; created_at?: string | null; // ISO 8601 updated_at?: string | null; // ISO 8601 live_object_id?: string | null; // when derivable from activity input output?: Record<string, unknown> | null; // structured map when DONE failure_reason?: string | null; }; ``` --- ## Get Job Status Response: `JobStatusResponse`. Poll until `status` is `DONE` or `CANCELED`. When DONE, use `output` (object map when present) for results; when failed, use `failure_reason`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/jobs/<activity_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Agent behavior When the user asks to check job status or poll an async operation, do the following. ### 1. Endpoint | User intent | Endpoint | Method | |-------------|----------|--------| | Check/poll job status | `/api/v2/jobs/{activityId}` | GET | ### 2. Build and run - **Auth**: Include `X-API-KEY: $LAYERPROOF_API_KEY`. Read env vars; if missing, tell the user. - **Path**: Use the `activity_id` returned from a previous async call (outline generate, batch generate, export, etc.). Run curl and show the result. ### 3. After response - If status is SCHEDULED/RUNNING/PENDING, suggest polling again after a few seconds. - If DONE, use `output` (object) if present and summarize the result. - If CANCELED or DONE with `failure_reason`, report the outcome. ### 4. Response handling - Always show the **raw JSON response** in a JSON code block. - On 404, job not found or user does not own the associated project. ### 5. Example workflows **Workflow A — User**: "Check status of job [activity_id]." 1. GET `/api/v2/jobs/{activityId}`; show JSON. If SCHEDULED/RUNNING/PENDING, suggest re-polling in a few seconds. If DONE, show `output` (and summarize). If CANCELED or failure_reason, report and stop. **Workflow B — User**: "I started an outline generate and a batch generate; poll both and tell me when they’re done or if either failed." 1. User provides two activity IDs (or they are in context from prior slide-deck calls). Poll GET `/api/v2/jobs/{activityId1}` and GET `/api/v2/jobs/{activityId2}`. 2. For each: if DONE, report success and optionally parse `output`; if CANCELED or DONE with `failure_reason`, report which job failed and the reason. 3. If both still in progress, suggest polling again; if one is DONE and the other not, report current state and continue polling the other until terminal. **Workflow C — User**: "Wait for this job and then get the slide deck / campaign / export result." 1. Poll GET `/api/v2/jobs/{activityId}` until status is DONE or CANCELED. If failed, report and stop. 2. When DONE: depending on workflow type (from initial trigger), hand off to the right skill — e.g. slide-decks GET deck, social-campaigns GET campaign, exports GET export status — using IDs from context or from `output` (e.g. project_id, slide_deck_id, campaign_id, export_id) and show the resulting resource or download URL. --- ## 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).

project-files

Public API project file management (X-API-KEY). Prepare upload/update, confirm, AI files, subdirectories, resolve assets/paths, preview URL, get, download, delete. PublicApiProjectFileController.

# Skill: Project Files ## Description Manage files in project directories. This skill documents the **public API** at `/api/v2/projects/{projectId}` (PublicApiProjectFileController). Upload flow: 1) POST prepare with directoryId; 2) PUT file to `upload_url`; 3) POST confirm with `file_id`. All paths require `projectId`; prepare/prepare-update also need `directoryId`. Authenticate with `X-API-KEY` header. --- ## TypeScript types (request / response) Mirrors `PublicApiProjectFileController` data classes. ```typescript // --- Prepare upload (POST) — 201 --- type PrepareFileUploadRequest = { path: string; file_name: string; mime_type: string; size: number; }; type PrepareFileUploadResponse = { upload_url: string; file_id: string; s3_key: string; expires_at: string; }; // --- Prepare update (POST) --- type PrepareUpdateFileRequest = { path: string; mime_type?: string | null; size?: number | null; }; type PrepareUpdateFileResponse = { upload_url: string; file_id: string; s3_key: string; expires_at: string; }; // --- Confirm (POST) --- type ConfirmFileUploadRequest = { metadata?: Record<string, unknown> | null }; type FileResponse = { id: string; name: string; file_type: string; mime_type: string; s3_key: string; size: number; uploaded_at: string; uploaded_by: string; status: string; metadata: Record<string, unknown> | null; }; // --- Download URL (GET), Get file (GET), Delete (DELETE) --- type DownloadUrlResponse = { download_url: string; expires_at: string; }; // --- Preview URL (POST .../preview-url) --- type PreviewUrlResponse = { preview_url: string; expires_at: string; }; // --- Create subdirectory (POST .../subdirectories) --- type CreateDirectoryRequest = { name: string }; type CreateDirectoryResponse = { id: string; name: string }; // --- Resolve assets (POST .../resolve-assets) --- type ResolveAssetsRequest = { paths: string[] }; type ResolvedAsset = { original_path: string; presigned_url: string | null; error: string | null; }; type ResolveAssetsResponse = { assets: ResolvedAsset[] }; // --- Resolve paths to IDs (POST .../resolve-paths-to-ids) --- type ResolvePathsToIdsRequest = { paths: string[] }; type ResolvedPathToId = { original_path: string; file_id: string | null; error: string | null; }; type ResolvePathsToIdsResponse = { resolved: ResolvedPathToId[] }; // --- AI file (POST .../ai-files) — 201 --- type CreateAiFileRequest = { filename: string; path: string; workflow_type: string; project_type_id?: string | null; form_input_data?: Record<string, unknown> | null; }; type CreateAiFileResponse = { file_id: string; filename: string; workflow_type: string; }; // --- Trigger / cancel AI file --- type TriggerAiFileRequest = { form_input_data?: Record<string, unknown> | null }; type TriggerAiFileResponse = { activity_id: string; workflow_type: string; live_object_id: string; }; type CancelAiFileResponse = { live_object_id: string; cancelled_children: number; }; ``` --- ## Prepare Project File Upload Request body: `PrepareFileUploadRequest`. Response (201): `PrepareFileUploadResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/files/prepare" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"path":"/","file_name":"doc.pdf","mime_type":"application/pdf","size":2048}' ``` --- ## Prepare Project File Update Request body: `PrepareUpdateFileRequest`. Response: `PrepareUpdateFileResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/files/prepare-update" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"path":"/doc.pdf","mime_type":"application/pdf","size":2048}' ``` --- ## Confirm Project File Upload Request body: `ConfirmFileUploadRequest`. Response: `FileResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/files/<file_id>/confirm" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"metadata":{}}' ``` --- ## Get File Download URL Response: `DownloadUrlResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/files/<file_id>/download-url" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Get File Details Response: `FileResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/files/<file_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Delete Project File Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/files/<file_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Create Subdirectory Creates a child directory under `directory_id`. Response (201): `CreateDirectoryResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/subdirectories" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"assets"}' ``` --- ## Preview URL (HTML) For HTML files: processes assets and returns a presigned preview URL. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/files/<file_id>/preview-url" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Resolve Asset Paths to URLs Body: `{ "paths": ["./img.png", "..."] }`. Response: `ResolveAssetsResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/resolve-assets" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"paths":["/relative/path.png"]}' ``` --- ## Resolve Paths to Live Object IDs Body: `{ "paths": ["~/file.txt", "/abs/path"] }`. Response: `ResolvePathsToIdsResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/resolve-paths-to-ids" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"paths":["/notes.txt"]}' ``` --- ## Create AI File Creates an `.ai` configuration file in the directory. Response (201): `CreateAiFileResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/directories/<directory_id>/ai-files" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"filename":"workflow.ai","path":"/","workflow_type":"YOUR_WORKFLOW"}' ``` --- ## Trigger AI File Workflow Poll `GET /api/v2/jobs/{activity_id}` after. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/ai-files/<ai_file_id>/trigger" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{}' ``` --- ## Cancel AI File Workflow ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/ai-files/<ai_file_id>/cancel" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Agent behavior When the user asks to manage project files (upload, update, confirm, download, delete), do the following. ### 1. Choose the right endpoint Base path: `/api/v2/projects/{projectId}`. Replace `project_id`, `directory_id`, `file_id` as needed. | User intent | Endpoint | Method | |-------------|----------|--------| | Get upload URL for new file | `.../directories/{directoryId}/files/prepare` | POST | | Get upload URL to update file | `.../directories/{directoryId}/files/prepare-update` | POST | | Confirm upload after PUT | `.../files/{fileId}/confirm` | POST | | Get download URL | `.../files/{fileId}/download-url` | GET | | Get file metadata | `.../files/{fileId}` | GET | | Delete file | `.../files/{fileId}` | DELETE | | Create subdirectory | `.../directories/{directoryId}/subdirectories` | POST | | HTML preview URL | `.../directories/{directoryId}/files/{fileId}/preview-url` | POST | | Resolve paths → presigned URLs | `.../directories/{directoryId}/resolve-assets` | POST | | Resolve paths → file IDs | `.../directories/{directoryId}/resolve-paths-to-ids` | POST | | Create AI file | `.../directories/{directoryId}/ai-files` | POST | | Trigger AI file | `.../ai-files/{aiFileId}/trigger` | POST | | Cancel AI file | `.../ai-files/{aiFileId}/cancel` | POST | ### 2. Build and run the request - **Auth**: Include `X-API-KEY: $LAYERPROOF_API_KEY`. Read env vars; if missing, tell the user. - **Path**: Resolve projectId, directoryId, fileId from context or user input. - **POST**: Build JSON body from types above; run curl and show result. - **GET/DELETE**: Build path only; run curl and show result. ### 3. Upload flow Prepare → PUT file to `upload_url` → confirm with `file_id`. Then use `file_id` for get/download/delete. ### 4. Response handling - Always show raw JSON in a code block; show image + JSON if image URL present. - On error, show body and status code. ### 5. Example workflows **Workflow A — User**: "Upload a PDF to project X in the root directory." 1. Resolve projectId and directoryId (e.g. root directory from project or list directories). POST `.../directories/{directoryId}/files/prepare` with `{"path":"/","file_name":"brief.pdf","mime_type":"application/pdf","size":<bytes>}`; get `upload_url`, `file_id`, `s3_key`. 2. Tell user to PUT the file to `upload_url` with `Content-Type: application/pdf`. Then POST `.../files/{file_id}/confirm` with `{}` (or `{"metadata":{}}`). 3. Show JSON; use `file_id` for later get/download/delete. **Workflow B — User**: "Upload two reference docs to the project, then use them when generating the slide deck outline." 1. For each file: prepare with path (e.g. `/ref1.pdf`, `/ref2.docx`) → user uploads to `upload_url` → confirm. Capture both `file_id` and `s3_key` (if returned) for each. 2. If outline generation accepts project file references: pass the project file identifiers (e.g. s3_keys or file_ids) into the slide-deck outline/generate request (e.g. `file_s3_keys` or equivalent). Otherwise use public-files for outline references and keep project files for project-scoped use only. 3. Hand off to slide-decks: POST outline/generate with the resolved keys; poll job; get deck. **Workflow C — User**: "Update an existing file in the project (new version) and get a download URL after." 1. Resolve projectId, directoryId, and existing file path. POST `.../directories/{directoryId}/files/prepare-update` with `{"path":"/brief.pdf","mime_type":"application/pdf","size":<new_bytes>}`; get `upload_url`, `file_id`. 2. User PUTs new content to `upload_url`; then POST `.../files/{file_id}/confirm`. GET `.../files/{file_id}/download-url` to show the user a temporary download link. 3. On error (e.g. path not found), show response body and suggest verifying path and project/directory IDs. --- ## 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).

projects

Public API project management (X-API-KEY). Create, list, get, update, delete, clone, vote, visibility, recent/deleted/restore. Cursor pagination. Types follow PublicApiProjectController (/api/v2/projects).

# Skill: Projects Management ## Description Manage Layerproof projects (create, list, get, update, delete, clone, vote, public list, visibility, recent, soft-delete restore). This skill documents the **public API** at `/api/v2/projects` (PublicApiProjectController). Authenticate with `X-API-KEY` header. **List** uses cursor pagination (`limit`, `cursor`). **List deleted** uses offset pagination (`page`, `page_size`). --- ## Requirements Environment variables: - `LAYERPROOF_BASE_URL` - `LAYERPROOF_API_KEY` All requests must include: - `X-API-KEY: $LAYERPROOF_API_KEY` --- ## TypeScript types (request / response) Mirrors `PublicApiProjectController` data classes. ```typescript // --- Create (POST) — 201 --- type PublicApiCreateProjectRequest = { name: string; // required, 1–255 chars description?: string | null; // max 10000 chars status?: string | null; // e.g. "DRAFT"; defaults to DRAFT if omitted tags?: string[] | null; metadata?: Record<string, any> | null; project_kind?: "SLIDE_DECK" | "GENERIC" | "MINDMAP" | "THEME" | "BLOG_POST" | "SOCIAL_CAMPAIGN"; // default: SLIDE_DECK workspace_id?: string | null; // UUID theme_id?: string | null; // UUID; optional theme for slide deck aspect_ratio?: string | null; // e.g. "16:9" }; // --- Update (PUT) --- type PublicApiUpdateProjectRequest = { name?: string | null; // 1–255 chars description?: string | null; // max 10000 chars status?: string | null; tags?: string[] | null; metadata?: Record<string, any> | null; workspace_id?: string | null; // UUID is_public?: boolean | null; }; // --- Clone (POST /{projectId}/clone) — 201 --- type CloneProjectRequest = { name?: string | null; // defaults to "Copy of <source name>" workspace_id?: string | null; // UUID; if null, auto-creates hidden workspace }; // --- Project response --- type PublicApiProjectResponse = { id: string; name: string; description: string | null; status: string; // e.g. "ACTIVE", "DRAFT" project_kind: string; // e.g. "SLIDE_DECK" metadata: Record<string, any>; slide_deck_id: string | null; workspace_id?: string | null; // UUID thumbnail_url?: string | null; // optional preview image URL slide_deck_type?: string | null; // e.g. "PRESENTATION", "SOCIAL_POST", "WEBPAGE", "VIDEO" tags: string[]; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 is_public: boolean; vote_count: number; has_voted?: boolean | null; }; // --- List response (cursor-paginated) --- type PublicApiProjectListResponse = { data: PublicApiProjectResponse[]; next_cursor?: string | null; // pass as `cursor` param for next page has_more?: boolean; }; // --- Recent projects (GET /list/recent) --- type PublicApiRecentProjectsResponse = { data: PublicApiProjectResponse[]; }; // --- Update visibility only (PUT /{project_id}/visibility) --- type PublicApiUpdateProjectVisibilityRequest = { is_public: boolean; // required }; ``` --- ## List Projects Query params: `limit` (default 20, max 100), `cursor` (from previous `next_cursor`). ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects?limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` Example JSON response: ```json {"data":[{"id":"2b12d232-eca6-4161-96df-9f954fbbb36f","name":"Exit Strategy Overview","description":"...","status":"ACTIVE","project_kind":"SLIDE_DECK","metadata":{},"slide_deck_id":"ab2c64a5-0b59-45ec-baef-1d5b68dbf5fe","created_at":"2026-03-09T03:15:51.548959Z","updated_at":"2026-03-09T03:16:17.069810Z","is_public":false,"vote_count":0,"has_voted":null}],"next_cursor":null,"has_more":false} ``` --- ## Get Project ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` Example JSON response: ```json {"id":"2b12d232-eca6-4161-96df-9f954fbbb36f","name":"Exit Strategy Overview","description":"...","status":"ACTIVE","project_kind":"SLIDE_DECK","metadata":{"original_prompt":"Create an exit strategy overview"},"slide_deck_id":"ab2c64a5-0b59-45ec-baef-1d5b68dbf5fe","created_at":"2026-03-09T03:15:51.548959Z","updated_at":"2026-03-09T03:16:17.069810Z","is_public":false,"vote_count":0,"has_voted":false} ``` --- ## Create Project Request body: `PublicApiCreateProjectRequest`. Response (201): `PublicApiProjectResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{ "name": "<project_name>", "description": "<description>", "project_kind": "SLIDE_DECK" }' ``` Example JSON response: ```json {"id":"68f8270f-f36a-4817-8d0b-2c05efcd1c9a","name":"tmp-skill-project","description":"tmp","status":"DRAFT","project_kind":"SLIDE_DECK","metadata":{},"slide_deck_id":"a877d0c0-9514-40cc-8d27-cee3a1e73934","created_at":"2026-03-10T07:07:46.211172Z","updated_at":"2026-03-10T07:07:46.211176Z","is_public":false,"vote_count":0,"has_voted":null} ``` --- ## Update Project Request body: `PublicApiUpdateProjectRequest`. Only provided fields are updated. Response: `PublicApiProjectResponse`. ```bash curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"<new_name>","description":"<new_description>","is_public":true}' ``` --- ## Delete Project Soft-deletes the project and all associated resources. Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## List Public Projects Query params: `limit` (default 20, max 100), `cursor`, `slide_deck_type` (one of `PRESENTATION`, `SOCIAL_POST`, `WEBPAGE`, `VIDEO`; optional). ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/public?limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Vote for a Project Records a vote on a public project. Response: 204 No Content. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/vote" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Remove Vote from a Project Removes a vote from a public project. Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/vote" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Clone Project Clones an owned or public project into a new private project. Request body: `CloneProjectRequest`. Response (201): `PublicApiProjectResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/clone" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"<cloned_project_name>","workspace_id":"<workspace_id>"}' ``` --- ## Update Project Visibility Sets public or private without sending a full project update. Request body: `PublicApiUpdateProjectVisibilityRequest`. Response: `PublicApiProjectResponse`. ```bash curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/visibility" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"is_public":true}' ``` --- ## List Recent Projects Query: `limit` (default 4, max 100). Response: `PublicApiRecentProjectsResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/list/recent?limit=8" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## List Deleted Projects Soft-deleted projects for the current user. Query: `page` (default 0), `page_size` (default 20). Response: `PublicApiProjectListResponse` (cursor fields may be absent; use `has_more`). ```bash curl "$LAYERPROOF_BASE_URL/api/v2/projects/deleted?page=0&page_size=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Restore Deleted Project Restores a soft-deleted project. Response (200): `{"restored": true}`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/restore" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Permanently Delete Project Hard-deletes a project that is already soft-deleted. Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/permanently" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Agent behavior When the user asks to manage projects, do the following. ### 1. Choose the right endpoint | User intent | Endpoint | Method | |-------------|----------|--------| | List own projects | `/api/v2/projects?limit=20` | GET | | Get project by ID | `/api/v2/projects/{projectId}` | GET | | Create project | `/api/v2/projects` | POST | | Update project | `/api/v2/projects/{projectId}` | PUT | | Delete project | `/api/v2/projects/{projectId}` | DELETE | | List public projects | `/api/v2/projects/public?limit=20` | GET | | Vote for a project | `/api/v2/projects/{projectId}/vote` | POST | | Remove vote | `/api/v2/projects/{projectId}/vote` | DELETE | | Clone a project | `/api/v2/projects/{projectId}/clone` | POST | | Set visibility only | `/api/v2/projects/{projectId}/visibility` | PUT | | Recent projects | `/api/v2/projects/list/recent?limit=8` | GET | | List deleted projects | `/api/v2/projects/deleted?page=0&page_size=20` | GET | | Restore deleted project | `/api/v2/projects/{projectId}/restore` | POST | | Permanently delete (after soft delete) | `/api/v2/projects/{projectId}/permanently` | DELETE | ### 2. Build and run the request - **Auth**: 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. - **GET list**: Use `limit` (default 20, max 100) and `cursor` for pagination. Pass `next_cursor` from a previous response as `cursor` to fetch the next page. - **POST/PUT**: Build JSON body from the appropriate request type. Run curl and show result. - **DELETE project / vote**: Build path; run curl. Response is 204 with no body. ### 3. Response handling - Always show the **raw JSON response** in a JSON code block. - For 204 responses, indicate success and no body. - On error, show the response body and status code. ### 4. Example workflows **Workflow A — User**: "Create a project called Q3 Roadmap." 1. Choose POST `/api/v2/projects`. 2. Body: `{"name":"Q3 Roadmap","project_kind":"SLIDE_DECK"}`. 3. Run curl; show JSON. The returned `id` is the project ID; `slide_deck_id` is the associated slide deck. **Workflow B — User**: "Create a slide deck project in workspace W, then generate an outline for it." 1. Resolve `workspace_id` (e.g. from GET workspaces or user). POST `/api/v2/projects` with `{"name":"...", "project_kind":"SLIDE_DECK", "workspace_id":"<workspace_id>"}`; capture `id` and `slide_deck_id`. 2. Hand off to slide-decks skill: use `projectId = id` and `slideDeckId = slide_deck_id`; POST `.../projects/{projectId}/slide-deck/{slideDeckId}/outline/generate` with prompt and slide_count; poll jobs; get deck or update outline as needed. **Workflow C — User**: "List my projects, find the one named 'Launch Deck', export it as PPTX, and if there’s a clone or vote option show me how." 1. GET `/api/v2/projects` with `limit` and optional `cursor`; paginate if needed. Locate project where `name` matches "Launch Deck"; capture `id`. 2. Hand off to exports skill: POST `.../projects/{id}/exports/pptx`; poll GET `.../exports/{exportId}` until COMPLETED; show `downloadUrl`. 3. Optionally: POST `.../projects/{id}/clone` to clone, or POST/DELETE `.../projects/{id}/vote` per API; show response and explain usage. --- ## 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).

public-files

Public API reference files (X-API-KEY). Prepare upload, confirm, delete, get download URL. Use s3_key from prepare in outline generation. Types follow PublicApiFileController (/api/v2/files).

# Skill: Public Files ## Description Upload reference files (images, documents) for use in outline generation. This skill documents the **public API** at `/api/v2/files` (PublicApiFileController). Flow: 1) POST /prepare → get `upload_url` and `s3_key`; 2) PUT file to `upload_url`; 3) POST /confirm; use `s3_key` in `file_s3_keys` when calling slide-deck outline/generate. Authenticate with `X-API-KEY` header. Max 20 MB; allowed types: PDF, DOCX, PPTX, TXT, MD, PNG, JPEG, WebP, SVG, BMP, TIFF, HEIC, HEIF, AVIF, ICO. --- ## TypeScript types (request / response) Mirrors `PublicApiFileController` (/api/v2/files) data classes. ```typescript // --- Prepare (POST) --- type PrepareFileUploadRequest = { file_name: string; // max 255 chars mime_type: string; size: number; // 1 to 20*1024*1024 }; type PrepareFileUploadResponse = { upload_url: string; s3_key: string; expires_at: string; // ISO 8601, ~10 min }; // --- Confirm (POST) --- type PublicApiConfirmFileUploadRequest = { s3_key: string }; type PublicApiConfirmFileUploadResponse = { s3_key: string; uploaded: boolean }; // --- Delete (POST) --- type PublicApiDeleteFileRequest = { s3_key: string }; type PublicApiDeleteFileResponse = { success: boolean }; // --- Download URL (POST) --- type PublicApiDownloadUrlRequest = { s3_key: string; expiry_seconds?: number; // 60–604800, default 3600 }; type PublicApiDownloadUrlResponse = { download_url: string; expires_at: string; }; ``` --- ## Prepare Public File Upload Request body: `PrepareFileUploadRequest`. Response: `PrepareFileUploadResponse`. Then PUT file to `upload_url` with matching Content-Type. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/files/prepare" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"file_name":"doc.pdf","mime_type":"application/pdf","size":1024}' ``` --- ## Confirm Public File Upload Request body: `PublicApiConfirmFileUploadRequest`. Response: `PublicApiConfirmFileUploadResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/files/confirm" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"s3_key":"<s3_key_from_prepare>"}' ``` --- ## Delete Public File Request body: `PublicApiDeleteFileRequest`. Response: `PublicApiDeleteFileResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/files/delete" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"s3_key":"<s3_key>"}' ``` --- ## Get Public File Download URL Request body: `PublicApiDownloadUrlRequest`. Response: `PublicApiDownloadUrlResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/files/download-url" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"s3_key":"<s3_key>","expiry_seconds":3600}' ``` --- ## Agent behavior When the user asks to upload or manage reference files (for outlines), do the following. ### 1. Choose the right endpoint | User intent | Endpoint | Method | |-------------|----------|--------| | Get upload URL for a file | `/api/v2/files/prepare` | POST | | Confirm file uploaded to S3 | `/api/v2/files/confirm` | POST | | Delete a file by s3_key | `/api/v2/files/delete` | POST | | Get download URL for a file | `/api/v2/files/download-url` | POST | ### 2. Build and run the request - **Auth**: 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. - **Body**: All endpoints use JSON body (`file_name`, `mime_type`, `size` for prepare; `s3_key` for confirm/delete/download-url). Run curl and show the result. ### 3. Upload flow After prepare: tell the user to PUT the file to `upload_url` with `Content-Type: <mime_type>`, then call confirm with the returned `s3_key`. Use that `s3_key` in `file_s3_keys` when calling slide-deck outline/generate. ### 4. Response handling - Always show the **raw JSON response** in a JSON code block. - If the response contains a URL for an image, show the image and the JSON. - On error, show the response body and status code. ### 5. Example workflows **Workflow A — User**: "Upload a reference PDF for outline generation." 1. POST `/api/v2/files/prepare` with `{"file_name":"brief.pdf","mime_type":"application/pdf","size":<bytes>}`; get `upload_url`, `s3_key`, `expires_at`. 2. User PUTs file to `upload_url` with `Content-Type: application/pdf`. POST `/api/v2/files/confirm` with `{"s3_key":"<s3_key>"}`. 3. Use this `s3_key` in slide-deck POST `.../outline/generate` body as `file_s3_keys: ["<s3_key>"]`. **Workflow B — User**: "Upload two reference files (PDF + DOCX), confirm both, then generate an outline that uses them." 1. For first file: prepare → user uploads → confirm; capture `s3_key_1`. For second: prepare → upload → confirm; capture `s3_key_2`. 2. Hand off to slide-decks: resolve projectId and slideDeckId. POST `.../outline/generate` with `{"prompt":"...", "slide_count":5, "file_s3_keys":["<s3_key_1>","<s3_key_2>"]}`. 3. Poll jobs for `activity_id`; when DONE, GET deck to show outline that was informed by the references. **Workflow C — User**: "Get a download URL for a file I uploaded earlier (I have the s3_key), then delete it when done." 1. POST `/api/v2/files/download-url` with `{"s3_key":"<s3_key>","expiry_seconds":3600}`; show `download_url` and `expires_at`. 2. When user is done: POST `/api/v2/files/delete` with `{"s3_key":"<s3_key>"}`; show success response. Warn that delete is irreversible. --- ## 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).

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}).

# Skill: 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. ```typescript // --- 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. ```bash 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: ```bash 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. ```bash 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. ```bash 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`. ```bash 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}`. ```bash 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`. ```bash 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`. ```bash 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. ```bash 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`. ```bash 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`. ```bash 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`. ```bash 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 | `.../outline/generate` | POST | | Update outline structure | `.../outline` | PUT | | Get full deck (outline + slides + URLs) | `.../` (with optional query) | GET | | Batch generate all slides | `.../slides/batch-generate` | POST | | Generate one slide content | `.../slides/generate-content` | POST | | Generate one slide transcript | `.../slides/generate-transcript` | POST | | Generate one slide image | `.../slides/generate-image` | POST | | Cancel generations | `.../cancel` | POST | | Generate deck theme | `.../theme/generate` | POST | | Update slide transcript | `.../slides/{slideSectionId}/transcript` | PUT | | Duplicate section | `.../slides/{slideSectionId}/duplicate` | POST | | Improve section (AI) | `.../slides/improve` | POST | | Manual slide generation | `.../slides/generate-manual` | POST | | Patch visual style description | `.../theme/visual-style-description` | PATCH | | List / restore transcript versions | `.../slides/{id}/transcript/versions` (GET), `.../versions/{version_id}/restore` (POST) | GET / POST | | Mark transcript / improvement / live object read | `.../mark-transcript-read`, `.../mark-improvement-read`, `.../live-objects/{id}/mark-read` | PATCH | | Text-to-speech | `.../slides/{id}/generate-tts` (POST), `.../slides/{audio_id}/audio/download-url` (GET) | POST / GET | | Update deck settings (aspect ratio, etc.) | `.../` (slide-deck root) | PATCH | | Tone settings | `.../tone-settings` | GET / PUT | | Batch Konva layout | `.../slides/batch-generate-layout` | POST | | PPTX import | `.../import/prepare-upload`, `.../import` | POST | | Citations | `.../citations`, `.../citations/slide/{index}`, `.../citations/{citation_id}` | GET | ### 2. Build and run the request - **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. - **Path**: Resolve `projectId` and `slideDeckId` (and `slideSectionId` where needed) from context or user input. If missing, ask. - **GET**: Build curl with path and query params (`include_images`, `image_expiry_seconds` for get deck). Run and show result. - **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 `activity_id`. Tell the user the job was started and suggest polling `GET $LAYERPROOF_BASE_URL/api/v2/jobs/{activityId}` until `status` is `DONE` or `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 `slides[].image_url`), show images and the JSON. - 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." 1. Resolve projectId and slideDeckId (e.g. from GET projects, then `project.slide_deck_id`). 2. Choose `POST .../outline/generate`. 3. Build body: `{"prompt":"Product launch deck","slide_count":5}`. 4. Run curl; show JSON. Tell user to poll `GET /api/v2/jobs/{activityId}` and then call get deck or update outline as needed. **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." 1. Resolve projectId and slideDeckId. Get `file_s3_keys` from public-files (prepare → upload → confirm) or project-files if the API accepts them for outline. 2. POST `.../outline/generate` with `{"prompt":"Product launch with pricing","slide_count":6,"file_s3_keys":["<s3_key>"],"language":"en"}`; capture `activity_id`. 3. Poll `GET /api/v2/jobs/{activity_id}` until DONE. On failure, report and stop. 4. GET deck; from `outline.sections` identify a section to change. PUT `.../outline` with `title` and updated `sections` (e.g. edit `section_title`, `key_points`, `visual_suggestion` for one section). 5. If user wants a theme: use themes skill — **POST `/api/v2/themes/apply`** with `slide_deck_id` and `theme_id` (set `regenerate_slides` if images should be regenerated); poll job when `activity_id` is returned. 6. POST `.../batch-generate` with optional `generation_type`, `aspect_ratio`, `speaking_style`; capture `activity_id`. 7. Poll `GET /api/v2/jobs/{activity_id}` until DONE. 8. GET deck; check `metadata.completed_slides` and `slides[].generation_status`. If one slide’s image is wrong, POST `.../slides/{sectionId}/generate-image` (or generate-content) with section id; poll that job until DONE; GET deck again to show result. **Workflow C — User**: "Duplicate a section in the outline and regenerate slides for the new section only." 1. GET deck; from `outline.sections` pick a `section_id` (UUID string) to duplicate. 2. POST `.../slides/{slide_section_id}/duplicate` with `{"copy_content":true,"insert_after":true}`; read `new_section_id` from the response. 3. PUT `.../outline` with updated `title` and `sections` array (merge/reorder the duplicated section as needed). 4. POST `.../slides/generate-transcript` | `generate-image` | `generate-content` with the new section id; poll `GET /api/v2/jobs/{activity_id}`; GET deck to confirm. --- ## 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).

slides

Public API slide editing (X-API-KEY). Edit slide images with AI, accept/revert edits, object removal, text extraction, save Konva nodes. Types follow PublicApiSlideController (/api/v2/projects/{projectId}/slides).

# Skill: Slide Editing ## Description Modify slides after generation. This skill documents the **public API** at `/api/v2/projects/{projectId}/slides` (PublicApiSlideController). All slide endpoints require `projectId` and `slideId` in the path. Authenticate with `X-API-KEY` header. --- ## TypeScript types (request / response) Mirrors `PublicApiSlideController` (/api/v2/projects/{projectId}/slides) data classes. ```typescript // Shared: cropped region for region-based editing. Must lie fully within image bounds. // Constraints: x >= 0, y >= 0, width > 0, height > 0; x + width <= image width, y + height <= image height. type CroppedRegion = { x: number; y: number; width: number; height: number; }; // --- Edit Slide Image (POST) — async, poll jobs --- type SlideImageEditRequest = { /** AI instruction for the edit (required, non-blank) */ instruction: string; /** Path to input image in project working dir (required, non-blank) */ input_image_path: string; /** Optional extra reference image paths */ other_reference_image_paths?: string[]; /** Optional region to edit; only this region is modified */ cropped_region?: CroppedRegion; }; // --- Accept Image Edit (POST) --- type AcceptImageEditRequest = { live_object_id: string; // UUID from image-edit or object-removal response (required) target_node_id?: string; override_image_path?: string; // Optional path to use instead of workflow output }; // --- Revert Slide (POST) --- type RevertSlideRequest = { history_entry_id: string; // UUID from slide history (required) node_id?: string; }; // --- Object Removal (POST) — async, poll jobs --- type ObjectRemovalRequest = { input_image_path: string; // required, non-blank mask_path?: string; cropped_region?: CroppedRegion; }; // --- Extract Text (POST) — async, poll jobs --- type ExtractTextRequest = { node_id?: string; node_image_path?: string; }; // --- Save Konva Nodes (PUT) --- type SaveKonvaNodesRequest = { konva_nodes: Record<string, unknown>; // required konva_order: string[]; // required base_snapshot_id?: string; // UUID, optional }; // --- Responses --- type TriggerWorkflowResponse = { activity_id: string; // UUID – poll GET /api/v2/jobs/{activityId} workflow_type: string; live_object_id: string; // UUID – pass to accept-image-edit when done }; type AcceptImageEditResponse = { id: string; // slide UUID slide_section_id: string; image_path: string | null; status: string; }; ``` --- ## Edit Slide Image (async) Request body: `SlideImageEditRequest`. Response: `TriggerWorkflowResponse`. Triggers AI-powered slide image editing. Upload input image first, then call with `instruction` and `input_image_path`. Poll `GET /api/v2/jobs/{activityId}` for status; when DONE, call accept-image-edit with `live_object_id`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/image-edit" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"instruction":"Make the background blue","input_image_path":"/slides/slide-1.png"}' ``` With optional region and reference images: ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/image-edit" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"instruction":"Replace this area","input_image_path":"/slides/slide-1.png","cropped_region":{"x":0,"y":0,"width":200,"height":100},"other_reference_image_paths":["/ref.png"]}' ``` --- ## Accept Image Edit Request body: `AcceptImageEditRequest`. Response: `AcceptImageEditResponse`. Call after the image-edit or object-removal workflow completes successfully. Use `live_object_id` from the trigger response. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/accept-image-edit" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"live_object_id":"<live_object_uuid>"}' ``` --- ## Revert Slide Request body: `RevertSlideRequest`. Response: `AcceptImageEditResponse`. Reverts the slide to a previous version using `history_entry_id` from slide history. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/revert" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"history_entry_id":"<history_entry_uuid>"}' ``` --- ## Remove Objects (async) Request body: `ObjectRemovalRequest`. Response: `TriggerWorkflowResponse`. Triggers AI-powered object removal. Optional `mask_path` for mask-based removal. Poll jobs; when DONE, call accept-image-edit with `live_object_id`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/object-removal" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"input_image_path":"/slides/slide-1.png"}' ``` With mask: ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/object-removal" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"input_image_path":"/slides/slide-1.png","mask_path":"/masks/mask.png"}' ``` --- ## Extract Text (async) Request body: `ExtractTextRequest` (optional). Response: `TriggerWorkflowResponse`. Performs OCR, removes text from image via inpainting, creates editable Konva text nodes. Poll `GET /api/v2/jobs/{activityId}` for status. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/extract-text" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{}' ``` With optional node: ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/extract-text" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"node_id":"node-1","node_image_path":"/nodes/node1.png"}' ``` --- ## Save Konva Nodes Request body: `SaveKonvaNodesRequest`. Response: 200, no body. Persists Konva canvas nodes and order (positions, layer order, flattened image path). ```bash curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/projects/<project_id>/slides/<slide_id>/konva-nodes" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"konva_nodes":{},"konva_order":[]}' ``` --- ## Agent behavior When the user asks to edit slides (image edit, accept edit, revert, remove objects, extract text, save canvas), do the following. ### 1. Choose the right endpoint | User intent | Endpoint | Method | |-------------|----------|--------| | Edit slide image with AI instruction | `/api/v2/projects/{projectId}/slides/{slideId}/image-edit` | POST | | Accept edited image after workflow completes | `/api/v2/projects/{projectId}/slides/{slideId}/accept-image-edit` | POST | | Revert slide to previous version | `/api/v2/projects/{projectId}/slides/{slideId}/revert` | POST | | Remove objects from slide image (AI) | `/api/v2/projects/{projectId}/slides/{slideId}/object-removal` | POST | | Extract text from slide (OCR + inpainting) | `/api/v2/projects/{projectId}/slides/{slideId}/extract-text` | POST | | Save Konva canvas nodes/order | `/api/v2/projects/{projectId}/slides/{slideId}/konva-nodes` | PUT | All paths require `projectId` and `slideId` (replace placeholders with actual UUIDs). ### 2. Build and run the request - **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. - **Path**: Resolve `project_id` and `slide_id` from context (e.g. from project/slide-deck list or user input). If missing, ask the user. - **POST/PUT**: Build JSON body from the types above. Use `-X POST` or `-X PUT`, `-H "Content-Type: application/json"`, and `-d '...'`. Run the curl and show the result. ### 3. After async endpoints (image-edit, object-removal, extract-text) - Response includes `activity_id` and `live_object_id`. Tell the user the workflow was started. - Suggest polling `GET $LAYERPROOF_BASE_URL/api/v2/jobs/<activity_id>` until `status` is `DONE` or `CANCELED`. - For image-edit and object-removal: when DONE, tell the user to call **accept-image-edit** with `live_object_id` to apply the result. ### 4. Response handling - Always show the **raw JSON response** in a JSON code block; do not convert to a table. - If the response contains a URL for an image (e.g. `image_path`), show the image and the JSON. - On error (4xx/5xx), show the response body and status code; suggest fixing API key, projectId/slideId, or request body. ### 5. Example workflows **Workflow A — User**: "Edit slide image in project X, slide Y: make the background darker." 1. Choose `POST /api/v2/projects/{projectId}/slides/{slideId}/image-edit`. 2. Resolve projectId and slideId (from user or ask). 3. Build body: `{"instruction":"Make the background darker","input_image_path":"/path/to/slide/image"}` (user may need to provide image path). 4. Run curl; show JSON. Mention polling jobs with `activity_id` and calling accept-image-edit with `live_object_id` when done. **Workflow B — User**: "Edit two slides: darker background on slide 1, remove the logo from slide 3; then revert slide 1 if I don’t like it." 1. Resolve projectId; get slide ids from slide-deck GET deck (e.g. `slides[0].id`, `slides[2].id`). 2. For slide 1: POST `.../slides/{slideId1}/image-edit` with `{"instruction":"Make the background darker"}`; capture `activity_id_1` and `live_object_id_1`. For slide 3: POST `.../slides/{slideId3}/object-removal` with region/instruction; capture `activity_id_3` and `live_object_id_3`. 3. Poll `GET /api/v2/jobs/{activity_id_1}` and `.../jobs/{activity_id_3}` until both DONE. If either fails, report which slide and reason. 4. POST `.../slides/{slideId1}/accept-image-edit` with `{"live_object_id":"<live_object_id_1>"}`; POST `.../slides/{slideId3}/accept-image-edit` with `{"live_object_id":"<live_object_id_3>"}`. Show updated slide images (GET deck or slide detail). 5. If user says "revert slide 1": GET slide history (if available) for slideId1 to get `history_entry_id`; POST `.../slides/{slideId1}/revert` with `{"history_entry_id":"<id>"}`. Confirm with GET deck. **Workflow C — User**: "Extract text from slide 2 and replace the old text (OCR + inpainting)." 1. Resolve projectId and slideId for slide 2. POST `.../slides/{slideId}/extract-text` (body per API); capture `activity_id`. 2. Poll `GET /api/v2/jobs/{activity_id}` until DONE. When DONE, `output` may contain extracted text or updated asset reference. 3. If a follow-up accept or apply step is required (e.g. accept-image-edit), use the returned `live_object_id`; otherwise show the result (e.g. updated slide or transcript) from GET deck. --- ## 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).

social-campaigns

Public API social campaigns (X-API-KEY). CRUD campaigns, generate, confirm outline, topics, variations, captions, exports, theme, citations. PublicApiSocialCampaignController (/api/v2/social-campaigns).

# Skill: Social Campaigns ## Description **Social campaigns** are projects with `project_kind` **SOCIAL_CAMPAIGN**. This skill documents **PublicApiSocialCampaignController** at `/api/v2/social-campaigns`. Authenticate with `X-API-KEY`. - **Campaign generation** returns `activity_id` — poll **`GET /api/v2/jobs/{activity_id}`** (same as slide workflows). - **ZIP exports** return `export_id` — poll **`GET /api/v2/social-campaigns/{campaign_id}/exports/{export_id}`** (not the jobs endpoint). --- ## TypeScript types (selected) ```typescript // --- Create / list / get --- type PublicApiCreateCampaignRequest = { name: string; description?: string | null; status?: string | null; tags?: string[] | null; metadata?: Record<string, unknown> | null; workspace_id?: string | null; theme_id?: string | null; aspect_ratio?: string | null; }; type PublicApiCampaignResponse = { campaign_id: string; name: string; description?: string | null; campaign_live_object_id: string; created_at: string; updated_at: string; }; type PublicApiCampaignListResponse = { data: PublicApiCampaignResponse[]; next_cursor?: string | null; has_more: boolean; }; // --- Generate campaign --- type PublicApiTrendSnapshot = { key: string; label: string; platform: string; region?: string | null; score?: number | null; // ... additional optional analytics fields }; type PublicApiGenerateCampaignRequest = { prompt: string; theme_id?: string | null; tone_config?: { output_language?: string | null; text_detail_level?: string | null; tone?: string | null; voice?: string | null; audience?: string | null; } | null; reference_file_paths?: string[] | null; web_search_enabled?: boolean; target_topic_count?: number | null; trend_snapshot?: PublicApiTrendSnapshot | null; trend_snapshots?: PublicApiTrendSnapshot[] | null; auto_select?: boolean; // default false — if true, skips outline confirmation }; type PublicApiGenerateCampaignResponse = { campaign_live_object_id: string; activity_id: string; workflow_type: string; }; // --- Confirm outline (after outline step when auto_select is false) --- type PublicApiConfirmOutlineRequest = { selections: { topic_index: number; option_index: number }[]; }; // --- Topics (“posts” in paths) --- type PublicApiCreateTopicRequest = { topic?: string | null; core_message?: string | null; key_points?: string[] | null; visual_suggestion?: string | null; }; type PublicApiTopicResponse = { topic_id: string; live_object_id: string; status: string; topic?: string | null; core_message?: string | null; key_points?: string[] | null; visual_suggestion?: string | null; version: number; created_at: string; updated_at: string; }; // --- Export --- type PublicApiCampaignExportStartedResponse = { export_id: string; status: string; }; type PublicApiCampaignExportStatusResponse = { export_id: string; status: 'IN_PROGRESS' | 'COMPLETED' | 'FAILED'; download_url?: string | null; expires_at?: string | null; file_size_bytes?: number | null; error_message?: string | null; }; ``` --- ## Campaign CRUD | Action | Method | Path | |--------|--------|------| | Create | POST | `/api/v2/social-campaigns` | | List (cursor) | GET | `/api/v2/social-campaigns?limit=20&cursor=` | | Get + posts | GET | `/api/v2/social-campaigns/{campaign_id}` | | Update | PUT | `/api/v2/social-campaigns/{campaign_id}` | | Update settings (theme) | PUT | `/api/v2/social-campaigns/{campaign_id}/settings` | | Delete | DELETE | `/api/v2/social-campaigns/{campaign_id}` | ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/social-campaigns" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"Q1 Launch","workspace_id":"<workspace_uuid>"}' ``` --- ## Generate & confirm | Action | Method | Path | |--------|--------|------| | Generate from prompt | POST | `/api/v2/social-campaigns/{campaign_id}/generate` | | Confirm outline picks | POST | `/api/v2/social-campaigns/{campaign_id}/confirm-outline` | ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/social-campaigns/<campaign_id>/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Holiday campaign","target_topic_count":5,"web_search_enabled":true,"auto_select":false}' ``` Poll **`GET /api/v2/jobs/{activity_id}`**. If `auto_select` is false, user picks outline options, then **POST confirm-outline** with `selections`. --- ## Topics (paths use `/posts`) | Action | Method | Path | |--------|--------|------| | Create topic | POST | `/api/v2/social-campaigns/{campaign_id}/posts` | | Update topic | PUT | `/api/v2/social-campaigns/{campaign_id}/posts/{post_id}` | | Delete topic | DELETE | `/api/v2/social-campaigns/{campaign_id}/posts/{post_id}` | | Reorder | PUT | `/api/v2/social-campaigns/{campaign_id}/reorder` body `{"topic_ids":["uuid",...]}` | --- ## Variations & images | Action | Method | Path | |--------|--------|------| | Generate variations | POST | `.../posts/{post_id}/generate-variations` | | More variations | POST | `.../posts/{post_id}/generate-more-variations` | | Delete variation | DELETE | `.../posts/{post_id}/variations/{variation_id}` | | Retry variation | POST | `.../posts/{post_id}/variations/{variation_id}/retry` | | Aspect ratio variant | POST | `.../posts/{post_id}/variations/{variation_id}/generate-aspect-ratio` | | Edit variation image | POST | `.../posts/{post_id}/variations/{variation_id}/edit-image` | | Accept edit (if needed) | POST | `.../posts/{post_id}/variations/{variation_id}/accept-edit` | Poll **`GET /api/v2/jobs/{activity_id}`** for async variation work. --- ## Captions | Action | Method | Path | |--------|--------|------| | Update caption / hashtags | PUT | `.../posts/{post_id}/caption` | | Generate caption (async) | POST | `.../posts/{post_id}/generate-caption` | --- ## Theme | Action | Method | Path | |--------|--------|------| | Generate campaign theme (async) | POST | `/api/v2/social-campaigns/{campaign_id}/generate-theme` | Poll jobs with returned activity id. --- ## Exports (ZIP) | Action | Method | Path | |--------|--------|------| | Export full campaign ZIP | POST | `/api/v2/social-campaigns/{campaign_id}/exports/zip` | | Export one topic ZIP | POST | `/api/v2/social-campaigns/{campaign_id}/posts/{post_id}/exports/zip` | | Poll export | GET | `/api/v2/social-campaigns/{campaign_id}/exports/{export_id}` | ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/social-campaigns/<campaign_id>/exports/zip" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Citations & history | Action | Method | Path | |--------|--------|------| | Campaign citations | GET | `/api/v2/social-campaigns/{campaign_id}/citations` | | Post citations | GET | `.../posts/{post_id}/citations` | | Platform post citations | GET | `.../posts/{post_id}/platforms/{platform}/citations` | | Platform generation history | GET | `.../posts/{post_id}/platforms/{platform}/history` | | Platform edit history | GET | `.../posts/{post_id}/platforms/{platform}/edits` | --- ## Agent behavior 1. Resolve **`campaign_id`** (create or list). **`campaign_live_object_id`** in responses is the campaign root live object. 2. **Generate** → poll **jobs** until `DONE` / handle `failure_reason`. 3. **Exports** → poll **`.../social-campaigns/{id}/exports/{export_id}`** until `COMPLETED` or `FAILED`. 4. **Topics** are listed under **`posts`** in API paths; treat `post_id` as **topic id**. 5. There is **no** `generate-platform` or per-platform image-edit in this public controller; platform-specific data appears in **get** campaign and **citations/history** endpoints when present. --- ## Response format (required) - When responses include **image URLs** for posts or variations, **render previews** and show raw JSON. - Always show **verbatim JSON** in a code block.

themes

Public API theme management (X-API-KEY). List, get, save, update, delete, generate, regenerate, apply, unapply. PublicThemeController (/api/v2/themes).

# Skill: Theme Management ## Description Themes define visual styling for slides. This skill documents the **public API** at `/api/v2/themes` (PublicThemeController). Authenticate with `X-API-KEY` header. --- ## TypeScript types (request / response) Mirrors `PublicThemeController` (/api/v2/themes) data classes. ```typescript // --- List Themes (GET) --- // Query: offset (default 0), limit (default 20), search (optional) type PublicThemeListResponse = { data: PublicThemeResponse[]; total: number; offset: number; limit: number; }; // --- Get Theme By ID (GET) --- type PublicThemeResponse = { id: string; name: string; description: string | null; visibility: string; // "PRIVATE" | "SYSTEM" | "SHARED" preview_url: string; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 }; // --- Generate Theme (POST) — async --- type PublicGenerateThemeRequest = { prompt: string; // required, max 5000 chars project_id?: string | null; // optional THEME project UUID; if omitted, a project is created automatically }; type PublicGenerateThemeResponse = { activity_id: string; // UUID – poll GET /api/v2/jobs/{activity_id} theme_id: string; // UUID }; // --- Apply Theme (POST) --- type PublicApplyThemeRequest = { slide_deck_id: string; // UUID, required theme_id: string; // UUID, required regenerate_slides?: boolean; // default false; if true, triggers batch image regeneration – poll activity_id }; type PublicApplyThemeResponse = { theme_id: string; theme_name: string; slide_deck_id: string; applied: boolean; // true when applied successfully activity_id: string | null; // set when regenerate_slides is true – poll GET /api/v2/jobs/{activity_id} }; // --- Save theme (POST /api/v2/themes) — 201 --- type PublicSaveThemeRequest = { name: string; // required, max 256 visual_style_description: string; // required, max 5000 preview_s3_key: string; // required — S3 key of preview image description?: string | null; // max 1000 source_prompt?: string | null; source_project_id?: string | null; tags?: string[] | null; }; // --- Update theme (PUT /{theme_id}) --- type PublicUpdateThemeRequest = { name?: string | null; description?: string | null; tags?: string[] | null; visual_style_description?: string | null; }; // --- Regenerate theme (POST /{theme_id}/regenerate) — 202 --- type PublicRegenerateThemeRequest = { project_id: string; // UUID — project whose working dir is used adjustment_prompt: string; reference_image_paths?: string[] | null; preview_only?: boolean; }; type PublicRegenerateThemeResponse = { activity_id: string; theme_id: string; live_object_id: string; }; // --- Unapply (POST /unapply) --- type PublicUnapplyThemeRequest = { project_id: string; slide_deck_id: string; }; ``` --- ## List Themes Query: `offset` (default 0), `limit` (default 20), `search` (optional). Response: `PublicThemeListResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/themes?offset=0&limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Get Theme By ID Response: `PublicThemeResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Generate Theme Request body: `PublicGenerateThemeRequest`. Response (202): `PublicGenerateThemeResponse`. Only `prompt` is required. Optional `project_id` uses an existing THEME project; if omitted, one is created automatically. Poll `GET /api/v2/jobs/{activityId}` for status. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Clean, minimal style with SF Pro"}' ``` With optional `project_id`: ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Clean, minimal style","project_id":"<theme_project_uuid>"}' ``` --- ## Apply Theme Request body: `PublicApplyThemeRequest`. Response: `PublicApplyThemeResponse`. Theme and slide deck are specified in the body. When `regenerate_slides` is true, poll `GET /api/v2/jobs/{activityId}` for batch image regeneration status. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/apply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_deck_id":"<slide_deck_uuid>","theme_id":"<theme_uuid>"}' ``` With slide regeneration: ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/apply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_deck_id":"<slide_deck_uuid>","theme_id":"<theme_uuid>","regenerate_slides":true}' ``` --- ## Save Theme (manual) Creates a saved private theme. Requires `visual_style_description` and `preview_s3_key` (upload preview via project/public files first). Response (201): `PublicThemeResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"My brand","visual_style_description":"Minimal dark UI, rounded cards","preview_s3_key":"<s3_key>"}' ``` --- ## Update Theme Request body: `PublicUpdateThemeRequest`. Response: `PublicThemeResponse`. ```bash curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"Renamed theme"}' ``` --- ## Delete Theme Soft-deletes a user-owned theme. Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Regenerate Theme (async) Request body: `PublicRegenerateThemeRequest`. Response (202): `PublicRegenerateThemeResponse`. Poll `GET /api/v2/jobs/{activity_id}`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>/regenerate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"project_id":"<project_uuid>","adjustment_prompt":"More contrast, warmer palette"}' ``` --- ## Unapply Theme from Slide Deck Removes applied theme from a deck. Request body: `PublicUnapplyThemeRequest`. Response: 204 No Content. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/unapply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"project_id":"<project_uuid>","slide_deck_id":"<slide_deck_uuid>"}' ``` --- ## List My Themes (by user) Query: `offset`, `limit`, optional `visibility` (`PRIVATE` \| `SYSTEM` \| `SHARED`), optional `search`. Response: `PublicThemeListResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/themes/by-user-id?offset=0&limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Agent behavior When the user asks to work with themes (list, get, generate, apply), do the following. ### 1. Choose the right endpoint | User intent | Endpoint | Method | |-------------|----------|--------| | List/browse themes, search themes | `/api/v2/themes` | GET | | Get one theme by ID | `/api/v2/themes/<theme_id>` | GET | | Save a theme manually | `/api/v2/themes` | POST | | Update theme metadata | `/api/v2/themes/<theme_id>` | PUT | | Delete theme | `/api/v2/themes/<theme_id>` | DELETE | | Generate theme from prompt (async) | `/api/v2/themes/generate` | POST | | Regenerate / adjust theme (async) | `/api/v2/themes/<theme_id>/regenerate` | POST | | Apply a theme to a slide deck | `/api/v2/themes/apply` | POST | | Unapply theme from deck | `/api/v2/themes/unapply` | POST | | List current user’s themes | `/api/v2/themes/by-user-id` | GET | ### 2. Build and run the request - **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. - **GET**: Build `curl` with the chosen path and query params (`offset`, `limit`, `search` for list). Run the curl and show the result. - **POST**: Build a JSON body from the user's input (prompt, theme ID, slide deck ID, etc.). Use `-X POST`, `-H "Content-Type: application/json"`, and `-d '...'`. Run the curl and show the result. ### 3. After generate or apply (with regeneration) - **Generate theme**: Response includes `activity_id` and `theme_id`. Tell the user the theme was started and give `theme_id`. Optionally poll `GET $LAYERPROOF_BASE_URL/api/v2/jobs/<activity_id>` until `status` is `DONE` or `CANCELED`, then report outcome. - **Apply theme with `regenerate_slides: true`**: Response may include `activity_id`. If present, tell the user regeneration was started and optionally poll `GET .../api/v2/jobs/<activity_id>` for status. ### 4. Response handling - Always show the **raw JSON response** in a JSON code block; do not convert to a table. - If the response contains a URL for an image (e.g. `preview_url`), show the image and the JSON. - On error (4xx/5xx), show the response body and status code; suggest fixing missing/invalid API key, IDs, or request body. ### 5. Example workflows **Workflow A — User**: "Generate a theme with prompt: minimal dark mode." 1. Choose `POST /api/v2/themes/generate`. 2. Build body: `{"prompt":"minimal dark mode"}`. 3. Run: `curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/generate" -H "Content-Type: application/json" -H "X-API-KEY: $LAYERPROOF_API_KEY" -d '{"prompt":"minimal dark mode"}'`. 4. Show the JSON response; if it contains `activity_id`, mention they can poll `/api/v2/jobs/{activityId}` for status and use `theme_id` once done. **Workflow B — User**: "List themes, generate a new 'corporate blue' theme, wait for it to finish, then apply it to my slide deck and regenerate slides." 1. GET `/api/v2/themes` with optional `limit`, `offset`, `search`; show list. User may pick existing or request new. 2. POST `/api/v2/themes/generate` with `{"prompt":"corporate blue"}`; capture `activity_id` and `theme_id`. 3. Poll `GET /api/v2/jobs/{activity_id}` until status is DONE (or CANCELED). If DONE, theme is ready; if failed, report `failure_reason`. 4. Resolve projectId and slideDeckId (projects + slide-deck). POST or PUT the slide-deck theme/settings endpoint with `theme_id` (e.g. PUT `.../slide-deck/.../settings` with `{"theme_id":"<theme_id>"}`). 5. Use **POST `/api/v2/themes/apply`** with `regenerate_slides: true` if you want slide images regenerated; capture `activity_id` and poll jobs until DONE. Otherwise apply with `regenerate_slides: false` or omit. **Workflow C — User**: "I have a theme ID; apply it to deck X and only update the look (no slide regeneration)." 1. **POST `/api/v2/themes/apply`** with `{"slide_deck_id":"<slide_deck_uuid>","theme_id":"<theme_uuid>"}` (omit `regenerate_slides` or set `false`). 2. Confirm with GET deck; no job polling needed unless `regenerate_slides` was true. --- ## 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).

tones

Public API tone presets (X-API-KEY). List, create, get, update, delete, duplicate, apply to slide deck, save-as-preset. PublicApiToneController (/api/v2/tones).

# Skill: Tone Presets ## Description Manage **tone presets** (voice, audience, detail level) and apply them to a slide deck. This skill documents **PublicApiToneController** at `/api/v2/tones`. Slide decks also expose **per-deck** tone settings under `.../slide-deck/{id}/tone-settings` (see **slide-decks** skill); this skill covers the **shared preset library** endpoints. Authenticate with `X-API-KEY`. --- ## TypeScript types (request / response) Mirrors `PublicApiToneController` / client tone DTOs (field names follow API JSON; use snake_case if your client sends snake_case per server config). ```typescript // --- List (GET) --- // Query: offset (default 0), limit (default 20), search (optional), // visibility (optional, repeat or array: PRIVATE, SYSTEM) type TonePresetListResponse = { data: TonePresetResponse[]; total: number; offset: number; limit: number; }; type TonePresetResponse = { id: string; name: string; description?: string | null; visibility?: string | null; output_language?: string | null; text_detail_level?: string | null; tone?: string | null; voice?: string | null; audience?: string | null; created_at?: string | null; updated_at?: string | null; }; // --- Create (POST) --- type CreateTonePresetRequest = { name: string; description?: string | null; output_language?: string | null; text_detail_level?: string | null; tone?: string | null; voice?: string | null; audience?: string | null; }; // --- Update (PUT /{tone_id}) --- type UpdateTonePresetRequest = { name?: string | null; description?: string | null; output_language?: string | null; text_detail_level?: string | null; tone?: string | null; voice?: string | null; audience?: string | null; }; // --- Apply (POST /{tone_id}/apply) --- type ApplyTonePresetRequest = { project_id: string; slide_deck_id: string; }; type ApplyTonePresetResponse = TonePresetResponse; // applied settings snapshot // --- Save as preset from deck (POST /save-as-preset) — 201 --- type SaveAsPresetRequest = { slide_deck_id: string; name: string; description?: string | null; }; // --- Duplicate (POST /{tone_id}/duplicate) — 201 --- type DuplicateTonePresetRequest = { name: string; }; ``` --- ## List Tone Presets ```bash curl "$LAYERPROOF_BASE_URL/api/v2/tones?offset=0&limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Get Tone Preset ```bash curl "$LAYERPROOF_BASE_URL/api/v2/tones/<tone_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Create Tone Preset ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/tones" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"Boardroom","output_language":"en-US","tone":"Professional"}' ``` --- ## Update Tone Preset ```bash curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/tones/<tone_id>" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"description":"Stricter pacing"}' ``` --- ## Delete Tone Preset Response: 204 No Content (cannot delete system presets — 403). ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/tones/<tone_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Apply Preset to Slide Deck ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/tones/<tone_id>/apply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"project_id":"<project_uuid>","slide_deck_id":"<slide_deck_uuid>"}' ``` --- ## Save Current Deck Settings as Preset Persists the slide deck’s current tone settings as a new preset. Response (201): `TonePresetResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/tones/save-as-preset" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_deck_id":"<slide_deck_uuid>","name":"From deck settings"}' ``` --- ## Duplicate Preset ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/tones/<tone_id>/duplicate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"Copy of Boardroom"}' ``` --- ## Agent behavior | User intent | Endpoint | Method | |-------------|----------|--------| | List presets | `/api/v2/tones` | GET | | Get preset | `/api/v2/tones/{toneId}` | GET | | Create preset | `/api/v2/tones` | POST | | Update preset | `/api/v2/tones/{toneId}` | PUT | | Delete preset | `/api/v2/tones/{toneId}` | DELETE | | Apply to slide deck | `/api/v2/tones/{toneId}/apply` | POST | | Save deck settings as preset | `/api/v2/tones/save-as-preset` | POST | | Duplicate preset | `/api/v2/tones/{toneId}/duplicate` | POST | **Note:** Per-deck tone fields without creating a preset are under **GET/PUT** `.../slide-deck/{slideDeckId}/tone-settings` (slide-decks skill). --- ## Response format (required) - Always show the **raw JSON response** in a JSON code block. - If the response contains image URLs, show images and the JSON.

workspaces

Public API workspace management (X-API-KEY). Create, list, get, update, delete workspaces. Types follow PublicApiWorkspaceController (/api/v2/workspaces).

# Skill: Workspace Management ## Description Manage workspaces. This skill documents the **public API** at `/api/v2/workspaces` (PublicApiWorkspaceController). Authenticate with `X-API-KEY` header. List uses `page` and `page_size` (`page_size` default 20, max 100). **For the first page of results, pass `page=0` explicitly.** --- ## TypeScript types (request / response) Mirrors `PublicApiWorkspaceController` data classes. ```typescript // --- Create (POST) — 201 --- type PublicApiCreateWorkspaceRequest = { name: string; // required, 1–255 chars description?: string | null; default_theme_id?: string | null; // optional theme UUID }; type PublicApiWorkspaceResponse = { id: string; user_id: string; name: string; description: string | null; default_theme_id: string | null; shared_working_dir_live_object_id: string; project_count: number; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 thumbnail_url?: string | null; }; // --- List (GET) --- // Query: page (use 0 for first page), page_size (default 20, max 100) type PublicApiWorkspaceListResponse = { data: PublicApiWorkspaceResponse[]; total: number; page: number; page_size: number; }; // --- Restore (POST /{workspace_id}/restore) --- type PublicApiRestoreWorkspaceRequest = { restore_projects?: boolean; // default true }; type PublicApiRestoreWorkspaceResponse = { workspace_restored: boolean; projects_restored: number; }; // --- List files (GET /{workspace_id}/files) --- // Optional query: type (file classification filter, if supported by server) type PublicApiWorkspaceFileEntry = { id: string; name: string; path: string; file_type: string; mime_type: string; size: number; uploaded_at: string; uploaded_by: string; status: string; presigned_url?: string | null; url_expires_at?: string | null; }; type PublicApiWorkspaceFilesResponse = { files: PublicApiWorkspaceFileEntry[]; total: number; }; // --- Update (PUT) --- type PublicApiUpdateWorkspaceRequest = { name?: string | null; // max 255 if provided description?: string | null; default_theme_id?: string | null; // optional theme UUID }; ``` --- ## Create Workspace Request body: `PublicApiCreateWorkspaceRequest`. Response (201): `PublicApiWorkspaceResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/workspaces" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"<workspace_name>","description":"<description>"}' ``` --- ## List Workspaces Query: `page` (use `0` for the first page), `page_size` (default 20, max 100). Response: `PublicApiWorkspaceListResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/workspaces?page=0&page_size=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## List Deleted Workspaces Soft-deleted workspaces for the current user. Query: `page` (default 0), `page_size` (default 20, max 100). ```bash curl "$LAYERPROOF_BASE_URL/api/v2/workspaces/deleted?page=0&page_size=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Restore Workspace Body optional: `{"restore_projects": true}` (default). Response: `PublicApiRestoreWorkspaceResponse`. ```bash curl -X POST "$LAYERPROOF_BASE_URL/api/v2/workspaces/<workspace_id>/restore" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"restore_projects":true}' ``` --- ## Permanently Delete Workspace Hard-deletes a workspace that is already soft-deleted. Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/workspaces/<workspace_id>/permanently" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## List Files in Workspace Lists files in the workspace shared working directory. Optional query: `type` (file classification). ```bash curl "$LAYERPROOF_BASE_URL/api/v2/workspaces/<workspace_id>/files" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Get Workspace Response: `PublicApiWorkspaceResponse`. ```bash curl "$LAYERPROOF_BASE_URL/api/v2/workspaces/<workspace_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Update Workspace Request body: `PublicApiUpdateWorkspaceRequest`. Response: `PublicApiWorkspaceResponse`. ```bash curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/workspaces/<workspace_id>" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"New name","description":"New description"}' ``` --- ## Delete Workspace Response: 204 No Content. ```bash curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/workspaces/<workspace_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" ``` --- ## Agent behavior When the user asks to manage workspaces (create, list, get, update, delete), do the following. ### 1. Choose the right endpoint | User intent | Endpoint | Method | |-------------|----------|--------| | Create workspace | `/api/v2/workspaces` | POST | | List workspaces | `/api/v2/workspaces?page=0&page_size=20` | GET | | List deleted workspaces | `/api/v2/workspaces/deleted?page=0&page_size=20` | GET | | Restore deleted workspace | `/api/v2/workspaces/{workspaceId}/restore` | POST | | Permanently delete (after soft delete) | `/api/v2/workspaces/{workspaceId}/permanently` | DELETE | | List files in workspace | `/api/v2/workspaces/{workspaceId}/files` | GET | | Get workspace by ID | `/api/v2/workspaces/{workspaceId}` | GET | | Update workspace | `/api/v2/workspaces/{workspaceId}` | PUT | | Delete workspace | `/api/v2/workspaces/{workspaceId}` | DELETE | ### 2. Build and run - **Auth**: 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. - **GET**: Build path and query params (`page`, `page_size` for list). Run curl and show result. - **POST/PUT**: Build JSON body (name, description for create; name/description optional for update). Run curl and show result. - **DELETE**: Build path; run curl. Response is 204 with no body. ### 3. Response handling - Always show the **raw JSON response** in a JSON code block. - For 204 delete, indicate success and no body. - On error, show response body and status code. ### 4. Example workflows **Workflow A — User**: "Create workspace Marketing." 1. Choose POST /api/v2/workspaces. 2. Body: `{"name":"Marketing"}` (or with description). 3. Run curl; show JSON. Returned `id` is the workspace ID for get/update/delete. **Workflow B — User**: "Set up a workspace for Q2, create it if it doesn’t exist, then list my workspaces and show the one I’ll use for new projects." 1. GET `/api/v2/workspaces` with `page`, `page_size`; inspect list for a workspace named "Q2" or similar. 2. If not found: POST `/api/v2/workspaces` with `{"name":"Q2","description":"Q2 campaigns and decks"}`; capture `id` as `workspace_id`. 3. If found: use that workspace’s `id`. Optionally GET `/api/v2/workspaces/{id}` to show full details. 4. Tell user: "Use workspace_id <id> when creating projects (e.g. POST /api/v2/projects with workspace_id in body)." **Workflow C — User**: "Rename workspace X to 'Marketing 2025' and add a description." 1. Resolve workspace ID (from list or user). PUT `/api/v2/workspaces/{workspaceId}` with `{"name":"Marketing 2025","description":"..."}`. 2. Run curl; show JSON. Optionally GET the workspace again to confirm name and description. --- ## 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).