API reference
Every endpoint of the presentations.ai REST API, grouped by resource.
All endpoints live under /api/v1 and authenticate with a workspace API key as
a Bearer token (see the overview). The machine-readable spec is at
/openapi.json.
Browse by resource using the sidebar: start with decks for creation and export, requests for polling generation, and credits for usage.
Review an outline before rendering
Outline generation is stateless. Generate a typed outline, edit its JSON locally, then send the reviewed outline to the deck endpoint. The second request skips outline generation and runs the edited structure through slide rendering and export.
curl -fsS "$PRESENTATIONSAI_BASE_URL/outlines" \
-H "Authorization: Bearer $PRES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Turn the Q3 results into a concise board update",
"slide_count": "8",
"level_of_detail": "standard"
}' \
| jq '.outline' > reviewed-outline.jsonEdit reviewed-outline.json: reorder, add, remove, or rewrite slides while
preserving the PresentationOutline
shape. Then wrap it in a deck request and submit it with a caller-owned request ID.
jq '{
name: "Q3 customer review",
outline: .,
export_format: "PPTX"
}' reviewed-outline.json > deck-request.json
curl -i "$PRESENTATIONSAI_BASE_URL/decks" \
-H "Authorization: Bearer $PRES_API_KEY" \
-H "Content-Type: application/json" \
-H "Request-Id: q3-customer-review-v1" \
--data-binary @deck-request.jsonThe default response is 202 Accepted. Poll its status_url; a successful
terminal response has status: "COMPLETED" and a non-null
export.download_url. Reusing the same Request-Id and body is safe. If the
body changes, use a new versioned ID such as q3-customer-review-v2.
Errors and asynchronous failures
Every HTTP error uses the same envelope:
{
"error": {
"code": "NOT_FOUND",
"message": "Deck not found.",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}Branch client behavior on error.code, not the human-readable message. The
most important codes are:
| Code | Meaning | Caller action |
|---|---|---|
VALIDATION_FAILED | A path, query, header, or body field was rejected. | Read error.details.errors and fix the named fields. |
UNAUTHENTICATED / INVALID_TOKEN | The Bearer API key is absent or invalid. | Supply or rotate the key; do not retry unchanged credentials. |
FORBIDDEN / FEATURE_NOT_IN_PLAN | The key scope, role, project, or plan disallows the action. | Change authorization or plan; a retry alone will not help. |
NOT_FOUND | The resource is absent or outside the key's scope. | Check the ID and workspace/project scope. |
SOURCES_NOT_READY | Uploaded files are still being extracted. | Retry after extraction completes. |
REQUEST_ID_CONFLICT | The request ID was reused with different content. | Reuse the original body or increment the ID version. |
INSUFFICIENT_CREDITS | The workspace cannot fund generation. | Add credits before retrying. |
RATE_LIMITED | The current rate window is exhausted. | Wait until Retry-After; inspect the X-RateLimit-* headers. |
UPSTREAM_ERROR / INTERNAL_ERROR | A dependency or the service failed. | Retry only idempotent operations and retain trace_id for support. |
A 202 response means the request was durably accepted, not that rendering
succeeded. Generation failures are reported by the polled request resource as
status: "FAILED", stage: "FAILED", and a sanitized error string. They are
not later HTTP 5xx responses.