| name | slides |
| description | 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.
type CroppedRegion = {
x: number;
y: number;
width: number;
height: number;
};
type SlideImageEditRequest = {
instruction: string;
input_image_path: string;
other_reference_image_paths?: string[];
cropped_region?: CroppedRegion;
mask_image_path?: string;
model_preset?: string | null;
openai_gpt_image_quality?: string | null;
};
type AcceptImageEditRequest = {
live_object_id: string;
target_node_id?: string;
override_image_path?: string;
};
type RevertSlideRequest = {
history_entry_id: string;
node_id?: string;
};
type ObjectRemovalRequest = {
input_image_path: string;
mask_path?: string;
cropped_region?: CroppedRegion;
};
type ExtractTextRequest = {
node_id?: string;
node_image_path?: string;
};
type SaveKonvaNodesRequest = {
konva_nodes: Record<string, unknown>;
konva_order: string[];
base_snapshot_id?: string;
};
type TriggerWorkflowResponse = {
activity_id: string;
workflow_type: string;
live_object_id: string;
};
type AcceptImageEditResponse = {
id: string;
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.
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:
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.
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.
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.
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:
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.
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:
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).
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
Step 1 — Check environment variables first. Before running any curl command, verify both LAYERPROOF_BASE_URL and LAYERPROOF_API_KEY are set on the user's machine:
if [[ -z "${LAYERPROOF_BASE_URL}" ]]; then
echo "ERROR: LAYERPROOF_BASE_URL is not set."
return 1
fi
if [[ -z "${LAYERPROOF_API_KEY}" ]]; then
echo "ERROR: LAYERPROOF_API_KEY is not set."
return 1
fi
If running from a project directory with a .env.local file, load it first:
if [[ -f .env.local ]]; then
set -a
source .env.local
set +a
fi
Step 2 — Auth: Every request must include X-API-KEY: $LAYERPROOF_API_KEY. Read LAYERPROOF_BASE_URL and LAYERPROOF_API_KEY from the environment; if missing, tell the user to set them.
Step 3 — Path: Resolve project_id and slide_id from context (e.g. from project/slide-deck list or user input). If missing, ask the user.
Step 4 — 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."
- Choose
POST /api/v2/projects/{projectId}/slides/{slideId}/image-edit.
- Resolve projectId and slideId (from user or ask).
- Build body:
{"instruction":"Make the background darker","input_image_path":"/path/to/slide/image"} (user may need to provide image path).
- 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."
- Resolve projectId; get slide ids from slide-deck GET deck (e.g.
slides[0].id, slides[2].id).
- 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.
- Poll
GET /api/v2/jobs/{activity_id_1} and .../jobs/{activity_id_3} until both DONE. If either fails, report which slide and reason.
- 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).
- 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)."
- Resolve projectId and slideId for slide 2. POST
.../slides/{slideId}/extract-text (body per API); capture activity_id.
- Poll
GET /api/v2/jobs/{activity_id} until DONE. When DONE, output may contain extracted text or updated asset reference.
- 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).