{"name":"TechTools PasteShare API","version":"3.0","description":"Share files, screenshots, text and code by link: upload with one multipart POST, get a share URL, a direct raw URL per file, and a one-time owner token to delete or edit the share. No account needed.","base_url":"https://techtools.cz/paste-api","tool":"https://techtools.cz/tools/paste-share/","view_url_format":"https://techtools.cz/tools/paste-share/view.html?p=\u003ckey\u003e[#k=\u003ce2e-key\u003e]","authentication":{"public":"None for creating or viewing. Anonymous creates are rate-limited per IP.","owner":"Send the owner_token returned at creation as header X-Paste-Token (or ?token=) to delete / edit a share. A signed-in TechTools creator or admin (shared-auth session cookie) may do the same.","password":"For password-protected shares either POST /pastes/:key/unlock once (the session cookie remembers it) or send header X-Paste-Password on every GET."},"limits":{"max_files_per_share":50,"max_file_bytes":262144000,"max_total_bytes_per_share":262144000,"max_text_bytes":4194304,"rate_limit":"60 shares per hour per IP (200 when signed in)","expirations":["10m","1h","1d","7d","30d","1y","never"],"burn_grace_seconds":600},"endpoints":{"create":{"method":"POST","path":"/pastes","content_type":"multipart/form-data (preferred) or application/json","params":{"files[]":"one or more files (multipart). Up to 50, 250 MB each, 250 MB per share","text":"text or code to share (instead of, or alongside, files)","title":"optional title (≤120 chars)","language":"optional code language for text, e.g. javascript, python, markdown, auto","expiration":"one of 10m | 1h | 1d | 7d | 30d | 1y | never (default 1d)","max_views":"integer ≥1; the share is deleted once reached. 1 = burn after reading","view_once":"legacy alias for max_views=1 (true/false)","password":"optional password (≤128 chars); viewers must unlock","slug":"optional custom link name, 3–40 chars [a-z0-9_-], must be free (see /available)","meta":"optional JSON array aligned with files[]: [{\"thumb\":\"data:image/webp;base64,...\",\"width\":1280,\"height\":720}]","encrypted":"1 when the client encrypted the files itself (see e2e section) — also send manifest","manifest":"e2e only: base64 of the encrypted manifest container"},"json_legacy":"application/json body { content_type: text|image|file, data (text or base64), filename, mime_type, expiration, view_once } is still accepted","response":"201 { success, key, url, owner_token, paste: {…files:[{index, filename, mime_type, size, raw_url, download_url}] } }","examples":["curl -F 'files[]=@screenshot.png' -F expiration=7d https://techtools.cz/paste-api/pastes","curl -F 'files[]=@a.pdf' -F 'files[]=@b.pdf' -F title='Two PDFs' -F password=secret https://techtools.cz/paste-api/pastes","curl -F text=@main.py -F language=python -F max_views=1 https://techtools.cz/paste-api/pastes","curl -H 'Content-Type: application/json' -d '{\"content_type\":\"text\",\"data\":\"hello\",\"expiration\":\"1h\"}' https://techtools.cz/paste-api/pastes"]},"show":{"method":"GET","path":"/pastes/:key","description":"Share metadata + file list (counts one view; may burn the share when max_views is reached). Text shares include the text inline.","errors":{"401":"{ locked: true } — password required","404":"unknown key","410":"expired or burned"},"example":"curl https://techtools.cz/paste-api/pastes/AbCd1234"},"raw":{"method":"GET","path":"/pastes/:key/raw?i=\u003cfile index\u003e[\u0026dl=1]","description":"The bytes of one file. Inline for images/audio/video/PDF/plain text, attachment otherwise or with dl=1. Supports HTTP Range (206) for seeking and resumable downloads. Text shares: i is ignored and the text is returned as text/plain.","example":"curl -O -J 'https://techtools.cz/paste-api/pastes/AbCd1234/raw?i=0\u0026dl=1'"},"zip":{"method":"GET","path":"/pastes/:key/zip","description":"All files of a share as one .zip (stored entries, streamed). Not available for end-to-end encrypted shares.","example":"curl -O -J https://techtools.cz/paste-api/pastes/AbCd1234/zip"},"unlock":{"method":"POST","path":"/pastes/:key/unlock","params":{"password":"the share password"},"description":"Verifies the password, remembers it in the session cookie and returns the share like GET /pastes/:key. 10 attempts per 10 minutes.","example":"curl -c jar -b jar -d password=secret https://techtools.cz/paste-api/pastes/AbCd1234/unlock"},"update":{"method":"PATCH","path":"/pastes/:key","auth":"X-Paste-Token","params":{"title":"string","expiration":"preset id (re-counted from now)","max_views":"integer or empty to remove","password":"new password or empty to remove","language":"code language"},"example":"curl -X PATCH -H 'X-Paste-Token: …' -d expiration=1h https://techtools.cz/paste-api/pastes/AbCd1234"},"delete":{"method":"DELETE","path":"/pastes/:key","auth":"X-Paste-Token","example":"curl -X DELETE -H 'X-Paste-Token: …' https://techtools.cz/paste-api/pastes/AbCd1234"},"status":{"method":"GET","path":"/pastes/status?keys=a,b,c","description":"Liveness + counters for up to 50 keys (for \"my shares\" lists)."},"available":{"method":"GET","path":"/available?slug=my-link","description":"Is a custom link name free?"},"mine":{"method":"GET","path":"/mine","description":"Active shares of the signed-in TechTools user (session cookie)."},"stats":{"method":"GET","path":"/stats","description":"Aggregate counters."}},"e2e_encryption":{"summary":"The browser can encrypt every file (and the title/filenames/thumbnails manifest) with AES-256-GCM before upload. The key is only ever placed in the URL fragment (#k=), which browsers never send to the server, so the server stores ciphertext it cannot read.","key":"AES-GCM 256-bit raw key, base64url (no padding) in the fragment: #k=\u003ckey\u003e","container":"bytes: \"TTE1\" | uint32 LE chunk size (plaintext bytes per chunk, 1048576) | repeated { 12-byte IV | AES-GCM ciphertext (chunk + 16-byte tag) }. Additional data for each chunk = 4-byte big-endian chunk index.","manifest":"JSON { title, text, language, files: [{ name, mime, size, thumb, width, height }] } encrypted with the same container format, base64-encoded and sent as the manifest param; the server exposes it as paste.manifest.","files":"each encrypted file is uploaded as files[] with any name; the server reports kind \"encrypted\" and the viewer restores the real name/mime from the manifest."},"response_fields":{"paste":["key","url","content_type","title","language","encrypted","locked","expiration","expires_at","time_remaining","time_remaining_text","max_views","views_left","view_count","download_count","burned","created_at","file_count","total_size","total_size_text","files","text","manifest","zip_url","legacy"],"file":["index","filename","mime_type","kind","size","size_text","thumb","width","height","previewable","raw_url","download_url"]},"errors":"Every error is JSON { success: false, error, message } with a proper HTTP status (400, 401, 403, 404, 410, 413, 422, 429)."}