Public API
The Deckyard Public API lets you programmatically create, manage, and export presentations. Use it to build integrations, automate workflows, or connect Deckyard with other tools.
Quick Start
Section titled “Quick Start”1. Create an API Key
Section titled “1. Create an API Key”Go to Settings > API Keys and create a new key. Choose the scopes you need:
| Scope | Access |
|---|---|
read | List and view presentations, themes, slide types |
write | Create, update, and delete presentations |
export | Export presentations to various formats |
ai | Use AI-powered generation features, including translation |
comments:read | Read comments on presentations the key owner can access |
comments:write | Create comments and replies, and change a comment’s status |
A new key without explicit scopes gets read and write. The comment scopes are separate from read and write: a key needs them explicitly to touch comments.
Important: Copy your API key immediately - it won’t be shown again.
2. Make Your First Request
Section titled “2. Make Your First Request”curl https://your-instance.com/api/v1/presentations \ -H "Authorization: Bearer dk_live_your_api_key_here"3. Explore the Documentation
Section titled “3. Explore the Documentation”Interactive API documentation is available at /api/v1/docs on your Deckyard instance.
A few endpoints need no API key: GET /api/v1 (the API’s name, version and main entry points), /api/v1/docs, /api/v1/openapi.yaml and the JSON Schema endpoints.
Authentication
Section titled “Authentication”All requests require an API key in the Authorization header:
Authorization: Bearer dk_live_your_api_key_hereKey Format
Section titled “Key Format”API keys use the format dk_live_ followed by a random token. The dk_live_ prefix indicates a production key.
Security
Section titled “Security”- Keys are stored securely (only the hash is saved)
- Revoke keys instantly from Settings if compromised
- Keys inherit the permissions of the user who created them
Rate Limits
Section titled “Rate Limits”Each API key has one rate-limit class, stored on the key. These classes are not plans: every new key gets free, and an admin who needs a higher limit changes the key’s tier column in the database.
| Class | Requests/min | AI calls/day | Exports/day |
|---|---|---|---|
free | 60 | 10 | 50 |
pro | 300 | 100 | 500 |
enterprise | 1000 | Unlimited | Unlimited |
Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. They describe daily usage and reset at midnight UTC, not the per-minute bucket:
X-RateLimit-Limit: 86400X-RateLimit-Remaining: 86155X-RateLimit-Reset: 1706140800Exceeding the per-minute limit returns 429 with Retry-After: 60; exceeding a daily limit returns 429 with the X-RateLimit-* headers. Details in Rate Limiting.
Endpoints
Section titled “Endpoints”Presentations
Section titled “Presentations”List Presentations
Section titled “List Presentations”GET /api/v1/presentationsQuery parameters:
limit(1-100, default 50) - Maximum resultsoffset(default 0) - Skip this many results
curl "https://your-instance.com/api/v1/presentations?limit=10" \ -H "Authorization: Bearer $API_KEY"Get Presentation
Section titled “Get Presentation”GET /api/v1/presentations/{id}Returns the full presentation including all slides.
Create Presentation
Section titled “Create Presentation”POST /api/v1/presentationsContent-Type: application/json
{ "title": "My Presentation", "description": "Optional description", "theme": "deckyard", "language": "en-GB"}Update Presentation
Section titled “Update Presentation”PUT /api/v1/presentations/{id}Content-Type: application/json
{ "title": "Updated Title", "slides": [...]}Delete Presentation
Section titled “Delete Presentation”DELETE /api/v1/presentations/{id}Moves the presentation to trash (soft delete).
Duplicate Presentation
Section titled “Duplicate Presentation”POST /api/v1/presentations/{id}/duplicateCreates a copy of the presentation.
Slides
Section titled “Slides”Work on single slides without sending the whole presentation back. Reads need read, changes need write. A slide type may be given in any accepted spelling (title-slide, core/title-slide, eu.deckyard.slide.title); the stored type is always the registry key.
Get Slide
Section titled “Get Slide”GET /api/v1/presentations/{id}/slides/{slideId}Returns the slide and its index in the presentation.
Create Slide
Section titled “Create Slide”POST /api/v1/presentations/{id}/slidesContent-Type: application/json
{ "type": "title-slide", "content": { }, "notes": "Optional speaker notes", "atIndex": 0}type is required. content is applied on top of the slide type’s defaults and the presentation’s theme. Position the slide with atIndex or afterSlideId; without either it is appended at the end. Returns 201 with the new slide and its index.
Update Slide
Section titled “Update Slide”PUT /api/v1/presentations/{id}/slides/{slideId}Replaces the slide’s type, content, notes and visibility. Fields you leave out keep their current value; the slide’s id and parent are always kept. The slide is validated against its type before it is saved.
Delete Slide
Section titled “Delete Slide”DELETE /api/v1/presentations/{id}/slides/{slideId}The last slide of a presentation cannot be deleted (400).
Reorder Slides
Section titled “Reorder Slides”POST /api/v1/presentations/{id}/slides/reorderContent-Type: application/json
{ "slideIds": ["slide-3", "slide-1", "slide-2"]}Slides are placed in the order given. Slides you leave out keep their relative order after the listed ones; an unknown id is a 400.
Writing raw HTML or CSS into a slide requires that the key’s owner is allowed to edit custom HTML; otherwise the request is refused with 403.
Slide Library
Section titled “Slide Library”Read your organization’s slide library and insert its items into a presentation.
List Library Items
Section titled “List Library Items”GET /api/v1/slide-library?themeId=deckyard&limit=20Requires read. Query parameters: themeId (optional filter), limit and offset. Items in the trash are left out. Each item has its id, name, slideType, themeId, content, tags, createdAt and createdById.
Get Library Item
Section titled “Get Library Item”GET /api/v1/slide-library/{itemId}Requires read.
Add Slide from Library
Section titled “Add Slide from Library”POST /api/v1/presentations/{id}/slides/from-libraryContent-Type: application/json
{ "libraryItemId": "abc123", "afterSlideId": "slide-2"}Requires write. Creates a new slide from the library item, using the presentation’s theme and language. Position it with atIndex or afterSlideId, as when creating a slide. The response includes copiedFrom with the library item’s id and name.
Comments
Section titled “Comments”Read reviewer feedback and respond to it. Requires the comments:read or comments:write scope, and a Deckyard instance running on the database storage backend: file storage has no comment store.
Comments identify people by id only (authorId, resolvedById), never by email address. Each comment carries an editUrl that opens the editor at the commented slide.
List Comments
Section titled “List Comments”GET /api/v1/presentations/{id}/comments?status=openRequires comments:read. Query parameters:
status-open,resolved,dismissedorall(defaultall)slideId- only comments on this slidesince- an ISO 8601 date or datetime
Returns the comments with their replies and the context of the slide they are on.
Create Comment or Reply
Section titled “Create Comment or Reply”POST /api/v1/presentations/{id}/commentsContent-Type: application/json
{ "body": "Can we shorten this title?", "slideId": "slide-2"}Requires comments:write. The comment is written as the key’s owner, who needs permission to comment on the presentation. body is required, at most 5000 characters. Add parentId to reply to an existing comment. Returns 201.
Change Comment Status
Section titled “Change Comment Status”POST /api/v1/comments/{commentId}/statusContent-Type: application/json
{ "status": "resolved"}Requires comments:write. status is resolved, open or dismissed. Only the presentation’s owner or original creator may change a comment’s status; a transition that is not allowed returns 409.
Publishing
Section titled “Publishing”Publish Presentation
Section titled “Publish Presentation”POST /api/v1/presentations/{id}/publishRequires write. Publishes the presentation, the same way publishing from the editor does. Refused on an instance running in sandbox mode.
Get Publish Status
Section titled “Get Publish Status”GET /api/v1/presentations/{id}/publishRequires read. Returns isPublished, and for a published presentation also publishId, slug, path, ogImageUrl and publishedAt.
Unpublish Presentation
Section titled “Unpublish Presentation”DELETE /api/v1/presentations/{id}/publishRequires write. Takes the published version offline.
Translation
Section titled “Translation”Translate Presentation
Section titled “Translate Presentation”POST /api/v1/presentations/{id}/translateContent-Type: application/json
{ "targetLang": "nl", "sourceLang": "en-GB", "vendor": "openai"}Requires ai, write access to the presentation, and AI enabled on the instance; counts toward the daily AI limit. Stores a translated language version inside the presentation.
targetLang(required) - one of the supported languagessourceLang- defaults to the presentation’s active languagevendor- the AI provider to usefillMissing(defaulttrue) - only translate what the existing target version lacksoverwrite(defaultfalse) - replace an existing target version
List Supported Languages
Section titled “List Supported Languages”GET /api/v1/translate/languagesRequires read. Returns each language’s code and English label.
Exports
Section titled “Exports”Export presentations in various formats. Requires the export scope.
JSON Export
Section titled “JSON Export”GET /api/v1/presentations/{id}/export/jsonReturns a portable JSON format that can be imported elsewhere.
HTML Export
Section titled “HTML Export”GET /api/v1/presentations/{id}/export/htmlReturns a standalone HTML file with all assets embedded.
PowerPoint Export
Section titled “PowerPoint Export”GET /api/v1/presentations/{id}/export/pptx?scale=2Query parameters:
scale(1-3, default 2) - Image quality multiplier
PDF Export
Section titled “PDF Export”GET /api/v1/presentations/{id}/export/pdfReturns print-ready HTML optimized for PDF conversion.
AI Features
Section titled “AI Features”Generate content using AI. Requires the ai scope.
List Vendors
Section titled “List Vendors”GET /api/v1/ai/vendorsReturns available AI providers and which are configured. This one needs only read.
Generate Presentation
Section titled “Generate Presentation”POST /api/v1/ai/wizardContent-Type: application/json
{ "content": "Your raw content text here...", "vendor": "openai", "theme": "deckyard", "language": "en-GB"}Generates a complete presentation from text content.
Append Slides
Section titled “Append Slides”POST /api/v1/ai/append-slidesContent-Type: application/json
{ "presentationId": "abc123", "content": "Additional content...", "vendor": "openai"}Generates slides and appends them to an existing presentation.
Resources
Section titled “Resources”List Themes
Section titled “List Themes”GET /api/v1/themesReturns available system and custom themes.
List Slide Types
Section titled “List Slide Types”GET /api/v1/slide-typesReturns slide type definitions with field schemas.
Get Slide Type Schema
Section titled “Get Slide Type Schema”GET /api/v1/slide-types/{slideType}/schemaReturns one slide type’s fields with their metadata, its defaults, and an example slide.
Search Image Library
Section titled “Search Image Library”GET /api/v1/image-library?q=nature&limit=20Search the image library for assets.
JSON Schemas
Section titled “JSON Schemas”The deck format’s JSON Schema, generated from this instance’s slide-type registry. These endpoints need no API key.
GET /api/v1/schema/deck.jsonGET /api/v1/schema/slide-types/{name}.jsonThe first returns the whole-deck schema, the second the content schema of one slide type. See Schemas for how to use them.
Error Handling
Section titled “Error Handling”The API uses standard HTTP status codes:
| Status | Meaning |
|---|---|
200 | Success |
201 | Created |
400 | Bad Request - Invalid input |
401 | Unauthorized - Invalid or missing API key |
403 | Forbidden - Valid key but insufficient scope |
404 | Not Found |
405 | Method Not Allowed - see the Allow header |
429 | Rate Limited - Slow down |
500 | Server Error |
Error responses use one envelope: error is a stable machine code to branch on, message is readable text, and details is optional extra information.
{ "error": "bad_request", "message": "Invalid slide data", "details": ["..."]}Examples
Section titled “Examples”Create and Export Workflow
Section titled “Create and Export Workflow”# Create a presentationRESPONSE=$(curl -s -X POST "https://your-instance.com/api/v1/presentations" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"title": "Q4 Report", "theme": "deckyard"}')
# Extract the IDPRES_ID=$(echo $RESPONSE | jq -r '.presentation.id')
# Export as PowerPointcurl "https://your-instance.com/api/v1/presentations/$PRES_ID/export/pptx" \ -H "Authorization: Bearer $API_KEY" \ -o report.pptxGenerate Presentation from Content
Section titled “Generate Presentation from Content”curl -X POST "https://your-instance.com/api/v1/ai/wizard" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "Our company had a great Q4. Revenue grew 25% year over year...", "vendor": "openai", "theme": "deckyard" }'Python Example
Section titled “Python Example”import requests
API_KEY = "dk_live_your_key_here"BASE_URL = "https://your-instance.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
# List presentationsresponse = requests.get(f"{BASE_URL}/presentations", headers=headers)presentations = response.json()["presentations"]
# Create a new presentationnew_pres = requests.post( f"{BASE_URL}/presentations", headers=headers, json={"title": "API Created", "theme": "deckyard"})print(new_pres.json())OpenAPI Specification
Section titled “OpenAPI Specification”The full OpenAPI 3.0 specification is available at:
GET /api/v1/openapi.yamlImport this into tools like Postman or Insomnia for automatic client generation.
Managing API Keys
Section titled “Managing API Keys”Via Settings UI
Section titled “Via Settings UI”Go to Settings > API Keys to:
- Create new keys with specific scopes
- View key usage statistics
- Revoke compromised keys
Via Internal API
Section titled “Via Internal API”If you need programmatic key management:
# List your keyscurl "https://your-instance.com/api/api-keys" \ -H "Cookie: your-session-cookie"
# Create a keycurl -X POST "https://your-instance.com/api/api-keys" \ -H "Cookie: your-session-cookie" \ -H "Content-Type: application/json" \ -d '{"name": "CI/CD Key", "permissions": ["read", "export"]}'
# Revoke a keycurl -X DELETE "https://your-instance.com/api/api-keys/{key-id}" \ -H "Cookie: your-session-cookie"
# View usagecurl "https://your-instance.com/api/api-keys/{key-id}/usage?days=30" \ -H "Cookie: your-session-cookie"