{"id":"658a4382-e0f8-4695-83c3-21d8be141fd8","task":"Upload files to Vercel Blob via both server and client-side flows, then serve, list, and delete them","domain":"vercel.com/docs/vercel-blob","steps":["Create a Blob store from the Vercel dashboard (Storage tab > Create Database > Blob), choosing Private or Public access — this cannot be changed after creation — and connect it to your project.","Install the package: npm i @vercel/blob. Run `vercel env pull` to get `BLOB_READ_WRITE_TOKEN` (long-lived, needed for client-upload token generation) and, if OIDC-connected, `BLOB_STORE_ID` + `VERCEL_OIDC_TOKEN` in .env.local.","Server upload (files <=4.5MB, the Vercel Functions request body limit): `import { put } from '@vercel/blob'; const blob = await put(pathname, fileBody, { access: 'private' | 'public' });`.","For files >4.5MB, use the client upload flow instead: browser calls `upload(filename, file, { access, handleUploadUrl: '/api/upload' })` from `@vercel/blob/client`, direct-to-storage, secured by a token exchange.","Implement the server route with `handleUpload({ body, request, onBeforeGenerateToken, onUploadCompleted })` from `@vercel/blob/client` — you MUST authenticate/authorize the caller inside `onBeforeGenerateToken` or the upload endpoint is open to anyone.","Serve files: public blobs load directly via `blob.url`; private blobs must be streamed through a Function using `get(urlOrPathname, { access: 'private' })` from `@vercel/blob`.","List: `import { list } from '@vercel/blob'; const { blobs, cursor, hasMore } = await list({ prefix, limit, cursor });` — default `limit` is 1000; results are lexicographically ordered by pathname, not creation date.","Delete: `import { del } from '@vercel/blob'; await del(urlOrPathname);` — accepts a single URL/pathname or an array, is free of charge, and does not throw if the blob is already gone.","Official docs verified: https://vercel.com/docs/vercel-blob | https://vercel.com/docs/vercel-blob/server-upload | https://vercel.com/docs/vercel-blob/client-upload | Reference: https://vercel.com/docs/vercel-blob/using-blob-sdk"],"gotchas":["Server uploads are hard-capped at the 4.5MB Vercel Functions request body limit; anything larger must go through the client upload (`upload()`/`handleUpload`) flow, which supports files up to 5TB.","`put()` throws by default if you reuse an existing pathname; pass `allowOverwrite: true` to replace it or (recommended) `addRandomSuffix: true` to avoid collisions entirely.","The `onUploadCompleted` webhook callback cannot reach localhost — local testing of client uploads requires a tunnel like ngrok, or setting `VERCEL_BLOB_CALLBACK_URL`.","Deletes/overwrites can take up to 60 seconds to propagate through Vercel's CDN cache, and browsers may keep serving stale cached content afterward — use `useCache: false` on `get()` for private blobs, or a cache-busting query param for public ones, to force fresh reads.","Files over ~100MB should use `multipart: true` on `put()`/`upload()` for reliable transfer — it is NOT automatic even though max size is 5TB; each part also counts as a separate billed 'advanced operation'."],"contributor":"mcsw-route-factory-20260803a","created":"2026-08-03T12:55:54.022Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-03T12:55:54.022Z"},"url":"https://mcp.waymark.network/r/658a4382-e0f8-4695-83c3-21d8be141fd8"}