Skip to main content
For most use cases, the slideless CLI handles the upload flow end-to-end. The CLI command is slideless push [path] --title "..." (the CLI reads slideless.json to decide new-vs-update).

Endpoint

POST https://europe-west1-slideless-ai.cloudfunctions.net/commitPresentationVersion

Auth

HeaderValue
AuthorizationBearer cko_… (or cka_…)
Content-Typeapplication/json
Required scope: presentations:write.

Request body

FieldTypeRequiredDescription
presentationIdstringone ofExisting presentation — bumps currentVersion and writes a new manifest.
sessionIdstringone ofSession from precheckAssets — creates a new presentation on this session’s reserved presentationId.
titlestringrequired on new, optional on update1–255 chars. On update, omit or empty to preserve the existing title.
entryPathstringyesThe entry HTML file within files[]. Must be present.
filesarrayyesEvery file in the deck. Each entry: { path, sha256, size, contentType }.
Path rules: path must be deck-root-relative, no .. segments, no leading or trailing slash, no backslashes, no null bytes, ≤ 512 chars. All hashes must exist: the backend checks every sha256 in files[] against the blob store. If any are missing, the call returns 400 blobs-missing and the manifest is not written. Example (new presentation):
{
  "sessionId": "019dba77-...",
  "title": "Q3 investor deck",
  "entryPath": "index.html",
  "files": [
    { "path": "index.html",        "sha256": "...", "size": 12034,  "contentType": "text/html; charset=utf-8" },
    { "path": "styles.css",        "sha256": "...", "size": 3120,   "contentType": "text/css; charset=utf-8" },
    { "path": "images/hero.jpg",   "sha256": "...", "size": 824100, "contentType": "image/jpeg" }
  ]
}
Example (update):
{
  "presentationId": "019dba77-4a1d-716e-8993-61e7c5771a7b",
  "title": "",
  "entryPath": "index.html",
  "files": [ ... ]
}

Response (200)

New presentation (on sessionId)

{
  "success": true,
  "data": {
    "presentationId": "019dba77-4a1d-716e-8993-61e7c5771a7b",
    "version": 1,
    "tokenId": "019dba77-559a-711a-adae-dd00beb88a79",
    "token": "XZv8oWqdn6gUPtmrLSuA0MQ0Zdwj_lODsGXo7btAiymg5z0UmDHDc0_9Kbd5y95a",
    "shareUrl": "https://app.slideless.ai/share/019dba77-.../?token=XZv8..."
  }
}
A default token named "default" is created with versionMode: {type: 'latest'}. It’s the only token — mint more with addPresentationToken.

Update (on presentationId)

{
  "success": true,
  "data": {
    "presentationId": "019dba77-4a1d-716e-8993-61e7c5771a7b",
    "version": 3,
    "shareUrl": "https://app.slideless.ai/share/019dba77-.../?token=..."
  }
}
tokenId/token omitted on update. shareUrl reuses a non-revoked token that follows latest. The bumped currentVersion is now 3; existing tokens on latest see v3 on next load, pinned tokens stay frozen on their version.

Plan caps

CapEnforced
Max files in one manifest500 (free) – 10000 (enterprise)
Max total bytes across all files250 MB (free) – 20 GB (enterprise)
Max HTML file size10 MB (free) – 50 MB (enterprise)
Max per-asset size50 MB (free) – 1 GB (enterprise)
See Presentations for the full table.

What happens on the backend

  1. Validate the request (auth, scopes, ownership, caps).
  2. Confirm every sha256 in files[] exists in the blob store — 400 if any are missing.
  3. Compute nextVersion = isNew ? 1 : currentVersion + 1.
  4. Write manifests/v{N}.json to Cloud Storage (immutable).
  5. Create or update the SharedPresentation Firestore doc (currentVersion = nextVersion).
  6. Clean up the upload session (if applicable).

Errors

StatusCodeCause
400invalid-argumentMissing/bad field, bad path, duplicate path, entryPath not in files[]
400blobs-missingOne or more referenced sha256 hashes are not uploaded. Details include the missing set.
400too-many-filesfiles.length exceeds the plan’s max file count
401unauthenticatedMissing/invalid API key
403permission-deniedKey lacks presentations:write, or caller is not the owner or an active dev collaborator
404not-foundpresentationId or sessionId doesn’t exist
409conflictUpdate’s expectedBaseVersion lags the server. Response body includes { serverVersion }. Pass --force to bypass.
413payload-too-largeTotal bytes or individual file (HTML cap or per-asset cap) exceeded

Next