presentations.ai

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.json

Edit 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.json

The 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:

CodeMeaningCaller action
VALIDATION_FAILEDA path, query, header, or body field was rejected.Read error.details.errors and fix the named fields.
UNAUTHENTICATED / INVALID_TOKENThe Bearer API key is absent or invalid.Supply or rotate the key; do not retry unchanged credentials.
FORBIDDEN / FEATURE_NOT_IN_PLANThe key scope, role, project, or plan disallows the action.Change authorization or plan; a retry alone will not help.
NOT_FOUNDThe resource is absent or outside the key's scope.Check the ID and workspace/project scope.
SOURCES_NOT_READYUploaded files are still being extracted.Retry after extraction completes.
REQUEST_ID_CONFLICTThe request ID was reused with different content.Reuse the original body or increment the ID version.
INSUFFICIENT_CREDITSThe workspace cannot fund generation.Add credits before retrying.
RATE_LIMITEDThe current rate window is exhausted.Wait until Retry-After; inspect the X-RateLimit-* headers.
UPSTREAM_ERROR / INTERNAL_ERRORA 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.

On this page