API documentation
Create pushes from scripts — provisioning, onboarding, CI — while keeping end-to-end encryption.
Authentication
Generate a personal token in Account → API tokens (shown only once), then pass it as a header:
Authorization: Bearer ppush_xxxxxxxxxxxxxxxxxxxxThe API only accepts already-encrypted content. The server never encrypts anything itself — that is what guarantees zero-knowledge. Use the provided CLI (recommended) or implement the format below.
The CLI (recommended)
tools/ppush-cli.mjs (in the repository) encrypts locally then calls the API. Node ≥ 20, no dependencies.
export PPUSH_URL=https://ppush.online
export PPUSH_TOKEN=ppush_xxx
# password, 3 views max, 7 days
ppush-cli.mjs --password "S3cret!" --views 3 --days 7
# text from stdin
cat config.yml | ppush-cli.mjs --text -
# file with passphrase and private note
ppush-cli.mjs --file dump.sql.gz --passphrase "sesame" --note "backup for Bob"
# → prints the full URL, decryption key included in the fragmentOptions: --days N · --views N · --passphrase X · --note "…" · --no-retrieval-step · --no-deletable
Endpoints
/api/pushesBearer or sessionCreates a push. JSON body:
{
"kind": "PASSWORD" | "TEXT" | "FILE" | "URL",
"ciphertext": "<base64>", // encrypted payload (see format)
"blobPath": "xxx.bin", // FILE only (see POST /api/blobs)
"passphrase": "optional",
"expireAfterDays": 7, // 1..30
"expireAfterViews": 5, // 1..50
"retrievalStep": true,
"deletableByViewer": true,
"note": "optional private reference"
}Response 201: { "slug", "url", "expiresAt", … }. The link to share is url + "#" + base64url_key — only you know the key.
/api/blobsBearer or sessionUpload of a file's encrypted blob (raw body, max ~90 MB with an account). Response: { "blobPath": "xxx.bin", "size": 123 } to pass next to POST /api/pushes.
/api/pushes?page=1&filter=activeBearer or sessionPaginated list of your pushes. filter: active | expired | (omitted = all).
/api/pushes/:slugBearer or sessionPush details + full audit log (events: CREATED, VIEW, FAILED_PASSPHRASE, EXPIRED, OWNER_DELETE, VIEWER_DELETE, with IP and user-agent).
/api/pushes/:slugBearer or sessionExpires the push immediately (permanent purge of the payload).
/api/p/:slugpublicPublic metadata of a push (kind, expired or not, passphrase required…). Does not consume a view.
/api/p/:slug/revealpublicReveals the ciphertext and consumes a view. Body: { "passphrase": "…" } if required. For a FILE, also returns a single-use viewToken for GET /api/p/:slug/blob?vt=….
/api/p/:slug/burnpublicDestruction by the recipient (if allowed at creation).
/api/storagepublicTransparent fair use of file storage: { "availableBytes", "upcoming": [{ "bytes", "at" }] } — upcoming lists upcoming space releases (cumulative, by latest expiry date). When authenticated, adds "user": { "usedBytes", "availableBytes", "quotaBytes" } (personal active-files quota). An upload refused for lack of space returns 507 with an estimate of the next window.
Encryption format (v1)
If you do not use the CLI, produce the ciphertext as follows (AES-256-GCM, WebCrypto or equivalent):
Key : 32 random bytes → base64url → link fragment (#…)
Payload : JSON { "t": "PASSWORD|TEXT|URL", "d": "<secret>" }
(FILE: { "t":"FILE", "d":"", "name", "mime", "size" })
ciphertext = 0x01 ‖ IV(12 bytes) ‖ AES-256-GCM(payload, AAD="ppush:v1:meta")
→ base64 in the "ciphertext" field
Files (blob): 8 MiB chunks, each framed:
[length u32 BE] [IV 12 bytes] [ct+tag]
AAD of chunk i: "ppush:v1:<i>:<1 if last, else 0>"Limits & errors
- Error responses:
{ "error": "message" }with the appropriate HTTP status (400validation,401auth,403forbidden,404not found,409conflict,410expired,413too large,429rate limit). - Per-IP rate limiting on sensitive endpoints (login, passphrase, reveal). On a
429, wait and retry. - Encrypted text payload: 1024 KB max · files: 90 MB max (account) · retention: 30 days / 50 views max. Without an account: 7 days / 5 views, files 10 MB.
- Fair-use file storage: shared global space (see
GET /api/storage) + personal quota of 3 GB of active files per account. When full →507with an estimate of upcoming space releases. - An API token has the rights of its owner (creation, listing, expiration of their pushes). Revocable at any time from the account page.
See also the About page and token management.