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
Auth
| Header | Value |
|---|---|
Authorization | Bearer cko_… (or cka_…) |
Content-Type | application/json |
presentations:write.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
presentationId | string | one of | Existing presentation — bumps currentVersion and writes a new manifest. |
sessionId | string | one of | Session from precheckAssets — creates a new presentation on this session’s reserved presentationId. |
title | string | required on new, optional on update | 1–255 chars. On update, omit or empty to preserve the existing title. |
entryPath | string | yes | The entry HTML file within files[]. Must be present. |
files | array | yes | Every file in the deck. Each entry: { path, sha256, size, contentType }. |
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):
Response (200)
New presentation (on sessionId)
"default" is created with versionMode: {type: 'latest'}. It’s the only token — mint more with addPresentationToken.
Update (on presentationId)
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
| Cap | Enforced |
|---|---|
| Max files in one manifest | 500 (free) – 10000 (enterprise) |
| Max total bytes across all files | 250 MB (free) – 20 GB (enterprise) |
| Max HTML file size | 10 MB (free) – 50 MB (enterprise) |
| Max per-asset size | 50 MB (free) – 1 GB (enterprise) |
What happens on the backend
- Validate the request (auth, scopes, ownership, caps).
- Confirm every
sha256infiles[]exists in the blob store — 400 if any are missing. - Compute
nextVersion = isNew ? 1 : currentVersion + 1. - Write
manifests/v{N}.jsonto Cloud Storage (immutable). - Create or update the
SharedPresentationFirestore doc (currentVersion= nextVersion). - Clean up the upload session (if applicable).
Errors
| Status | Code | Cause |
|---|---|---|
400 | invalid-argument | Missing/bad field, bad path, duplicate path, entryPath not in files[] |
400 | blobs-missing | One or more referenced sha256 hashes are not uploaded. Details include the missing set. |
400 | too-many-files | files.length exceeds the plan’s max file count |
401 | unauthenticated | Missing/invalid API key |
403 | permission-denied | Key lacks presentations:write, or caller is not the owner or an active dev collaborator |
404 | not-found | presentationId or sessionId doesn’t exist |
409 | conflict | Update’s expectedBaseVersion lags the server. Response body includes { serverVersion }. Pass --force to bypass. |
413 | payload-too-large | Total bytes or individual file (HTML cap or per-asset cap) exceeded |
Next
- POST /addPresentationToken — mint more named share tokens.
- POST /setTokenVersionMode — pin a token to a specific version.
- GET /getSharedPresentationInfo — inspect every token’s view count.