REST API
Upload otomatis — single-shot untuk file < 4 MB, chunked untuk yang lebih besar. Maks 20 MB per file. Tanpa autentikasi.
01
Contoh kode
Langsung pakai — setiap contoh sudah handle dedup, small/large file, dan retry otomatis.
js
// Auto pilih single-shot atau chunked
const ENDPOINT = 'https://stash.app';
const CHUNK_SIZE = 2097152;
async function stashUpload(file, expiry = '1d') {
const sha = await sha256(file);
const lookup = await fetch(`${ENDPOINT}/api/lookup`, {
method:'POST', headers:{'content-type':'application/json'},
body: JSON.stringify({ sha })
}).then(r => r.json());
if (lookup.hit) return lookup;
if (file.size < CHUNK_SIZE) {
const form = new FormData();
form.append('file', file); form.append('expiry', expiry); form.append('sha', sha);
return fetch(`${ENDPOINT}/api/upload`, { method:'POST', body:form }).then(r => r.json());
}
const uploadId = crypto.randomUUID().replace(/-/g,'').slice(0,16);
const total = Math.ceil(file.size / CHUNK_SIZE);
let next = 0;
await Promise.all(Array.from({ length:3 }, async () => {
while (next < total) {
const i = next++;
const frm = new FormData();
frm.append('uploadId', uploadId); frm.append('index', String(i));
frm.append('total', String(total));
frm.append('chunk', file.slice(i*CHUNK_SIZE, Math.min((i+1)*CHUNK_SIZE, file.size)), `part-${i}`);
await fetch(`${ENDPOINT}/api/upload/chunk`, { method:'POST', body:frm });
}
}));
return fetch(`${ENDPOINT}/api/upload/finish`, {
method:'POST', headers:{'content-type':'application/json'},
body: JSON.stringify({ uploadId, total, name:file.name, mime:file.type, size:file.size, sha, expiry })
}).then(r => r.json());
}
async function sha256(file) {
const d = await crypto.subtle.digest('SHA-256', await file.arrayBuffer());
return Array.from(new Uint8Array(d)).map(b => b.toString(16).padStart(2,'0')).join('');
}
const r = await stashUpload(input.files[0], '1mo');
console.log(r.url, r.dl, r.preview);02
POST /api/upload
Single-shot untuk file < 4 MB. Body: multipart/form-data.
Request body
| field | tipe | wajib | keterangan |
|---|---|---|---|
file | File | ya | maks 4 MB |
expiry | string | — | 5m 1h 1d 1mo forever · default 1d |
sha | hex | — | SHA-256 untuk dedup otomatis |
thumbId | string | — | dari /api/upload/thumb |
Response 200
json
{
"ok": true,
"id": "abc123XYZ_",
"url": "https://stash.app/f/abc123XYZ_",
"dl": "https://stash.app/f/abc123XYZ_?dl=1",
"preview": "https://stash.app/preview/abc123XYZ_",
"name": "video.mp4",
"size": 1843201,
"mime": "video/mp4",
"sha": "e3b0c44...",
"uploaded_at": 1714521600000,
"expires_at": 1714608000000
}03
Chunked upload
Untuk file ≥ 4 MB. Kirim tiap chunk ke /chunk, lalu /finish.
POST /api/upload/chunk
| field | tipe | keterangan |
|---|---|---|
uploadId | string | ID unik, sama untuk semua chunk |
index | integer | urutan 0-based |
total | integer | total chunk |
chunk | File | disarankan 2 MB per chunk |
POST /api/upload/finish — body JSON
json
{ "uploadId":"abc...", "total":5, "name":"video.mp4", "mime":"video/mp4", "size":10485760, "sha":"<opsional>", "expiry":"1d" }04
POST /api/lookup
Cek apakah file dengan SHA-256 tertentu sudah ada. Kalau hit, langsung pakai URL-nya.
bash
curl -s -X POST https://stash.app/api/lookup \
-H 'content-type: application/json' \
-d '{"sha":"e3b0c44..."}'
# hit → { "hit": true, "url": "...", "dl": "...", "preview": "..." }
# miss → { "hit": false }05
GET /f/[id]
Stream file langsung. Mendukung Range header — kompatibel dengan <video> dan <audio>.
| query | efek |
|---|---|
?dl=1 | paksa download (Content-Disposition: attachment) |
?raw=1 | skip halaman OG, langsung stream |
html
<video src="https://stash.app/f/abc123XYZ_" controls></video>
<a href="https://stash.app/f/abc123XYZ_?dl=1">Unduh</a>
<a href="https://stash.app/preview/abc123XYZ_">Preview</a>06
Batasan
20 MB
ukuran maks per file
4 MB
batas single-shot
2 MB
chunk ideal
5
pilihan masa berlaku
SHA-256
dedup otomatis
Range
streaming support