Skip to main content
For most use cases, the slideless CLI handles the upload flow end-to-end. This reference is for custom tooling.

Endpoint

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

Auth

HeaderValue
AuthorizationBearer cko_… (or cka_…)
Content-Typemultipart/form-data; boundary=...
Required scope: presentations:write.

Multipart fields

Order-independent. Send all five in one request:
FieldRequiredDescription
presentationIdone ofExisting presentation to upload into (update flow).
sessionIdone ofUpload session (new-presentation flow). You need one of presentationId or sessionId.
sha256yesDeclared hash of the bytes being uploaded (64 lowercase hex chars).
contentTypeyesMIME type. Stored on the blob; returned in Content-Type headers when the viewer serves this asset.
fileyesThe raw bytes. Any field name accepted for the file part.

Hash verification

The backend recomputes the SHA-256 of the received bytes and compares against the declared sha256. If they don’t match, the blob is deleted and the call returns 400 hash-mismatch. This prevents a malicious client from smuggling corrupt content into another user’s namespace.

Response (200)

{
  "success": true,
  "data": {
    "sha256": "4edd6a4b20278337c9cd35ef2b71e375522abd1c7563301dca7eebac31b5665e",
    "size": 723
  }
}
size: 0 indicates the blob was already present — upload was skipped (idempotent).

Plan caps

The per-file cap depends on your plan:
PlanPer-file cap
Free50 MB
Starter100 MB
Pro250 MB
Business500 MB
Enterprise1 GB
Uploads over the cap fail with 413 payload-too-large.

Example

curl

curl -sS -X POST \
  -H "Authorization: Bearer $SLIDELESS_API_KEY" \
  -F "presentationId=019dba77-4a1d-716e-8993-61e7c5771a7b" \
  -F "sha256=4edd6a4b20278337c9cd35ef2b71e375522abd1c7563301dca7eebac31b5665e" \
  -F "contentType=image/svg+xml" \
  -F "file=@./images/hero.svg" \
  https://europe-west1-slideless-ai.cloudfunctions.net/uploadPresentationAsset

Node.js (native FormData + Blob)

import { readFile } from 'fs/promises';
import { createHash } from 'crypto';

const bytes = await readFile('./images/hero.svg');
const sha256 = createHash('sha256').update(bytes).digest('hex');
const blob = new Blob([bytes], { type: 'image/svg+xml' });
const form = new FormData();
form.append('presentationId', '019dba77-...');
form.append('sha256', sha256);
form.append('contentType', 'image/svg+xml');
form.append('file', blob, 'blob');

const res = await fetch(
  'https://europe-west1-slideless-ai.cloudfunctions.net/uploadPresentationAsset',
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.SLIDELESS_API_KEY}` },
    body: form,
  },
);
const { data } = await res.json();
console.log('uploaded', data.sha256, '(' + data.size + ' bytes)');

Errors

StatusCodeCause
400invalid-argumentMissing field, bad sha256 format, or malformed multipart body
400hash-mismatchUploaded bytes don’t match declared sha256 (blob was deleted)
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
413payload-too-largeBlob exceeds the plan’s per-file cap

Next