Blossom Batch Upload
Blossom Batch Upload
This document drafts a backward-compatible Blossom extension for uploading multiple blobs in one request.
It is intentionally not part of the current Blossom spec. It is a proposed BUD shape that keeps existing Blossom semantics intact by introducing a new endpoint rather than changing PUT /upload.
Status
- Draft proposal
- Not a published Blossom BUD
- Intended to be compatible with current Blossom BUD-02, BUD-06, and BUD-11 semantics
Why It Exists
Current Blossom upload is single-blob shaped:
PUT /uploadaccepts one binary request bodyHEAD /uploadvalidates one hash, one size, and one MIME type- upload auth scopes naturally to one implied blob hash
That works well for independent blob storage, but it creates extra request overhead for note sync flows where one logical publish may need several attachments.
Batch upload reduces:
- HTTP request count
- repeated auth verification
- repeated storage-limit checks
- repeated round trips for attachment-heavy note sync
Compatibility Goals
This proposal is designed to avoid breaking existing Blossom clients and servers.
PUT /uploadremains unchangedHEAD /uploadremains unchanged- single-blob auth and hash semantics remain unchanged
- clients must treat batch upload as optional
- servers may implement batch upload without affecting standard Blossom behavior
Endpoint
POST /upload-batchContent-Type: multipart/form-data; boundary=...Authorization: Nostr <base64url event>Why a new endpoint:
PUT /uploadcurrently hashes the exact request body, somultipart/form-datawould hash the multipart envelope rather than a blob- overloading
/uploadwould break the existing “one body equals one blob” rule - a new endpoint keeps BUD-02 intact
Request Format
The request body is multipart/form-data with:
- exactly one
manifestpart containing JSON - one binary part per upload item
Example manifest:
{ "uploads": [ { "part": "file-1", "sha256": "88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576", "size": 184292, "type": "application/pdf", "filename": "paper.pdf" }, { "part": "file-2", "sha256": "2c26b46b68ffc68ff99b453c1d30413413422f1640bae4b6d1fbbf4b1b0e9c4f", "size": 1234, "type": "image/png", "filename": "diagram.png" } ]}Rules:
manifestmust be valid JSON- each
uploads[*].partmust match one multipart file part name - each file part must contain exactly one blob
- servers must compute SHA-256 over each file part body, not over the multipart envelope
- servers must not modify blob bytes before hashing or persisting them
filenameis advisory only
Authorization
This proposal reuses Blossom auth from BUD-11.
Required auth shape:
kind: 24242t=upload- standard
expirationhandling - optional
servertags as in BUD-11
Hash scoping for batch upload:
- clients should include one
xtag per uploaded blob hash - if one or more
xtags are present, the server must require that every uploaded blob hash appears in anxtag - a token must not authorize blobs whose hashes are absent from the uploaded parts
This is stricter than single-blob PUT /upload, because the request implies multiple blob hashes instead of one X-SHA-256.
Server Processing Rules
For each manifest item, the server should:
- locate the matching multipart file part
- compute the SHA-256 of the exact part body
- verify it matches the manifest
sha256 - verify size and MIME expectations if provided
- apply normal upload authorization and policy checks
- persist the blob or attach ownership if the blob already exists
- return a Blob Descriptor for successful items
Servers may deduplicate existing blobs exactly as they do for PUT /upload.
Responses
Full success
If every blob succeeds, the server should return 200 OK:
{ "uploaded": [ { "part": "file-1", "descriptor": { "url": "https://cdn.example.com/88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576.pdf", "sha256": "88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576", "size": 184292, "type": "application/pdf", "uploaded": 1774896077 } } ]}Partial success
If some blobs succeed and others fail, the server may return 207 Multi-Status:
{ "results": [ { "part": "file-1", "status": 200, "descriptor": { "url": "https://cdn.example.com/88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576.pdf", "sha256": "88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576", "size": 184292, "type": "application/pdf", "uploaded": 1774896077 } }, { "part": "file-2", "status": 413, "error": "file too large" } ]}Whole-request failure
Servers should use normal 4xx or 5xx responses when the request itself is invalid, for example:
- malformed multipart body
- missing
manifestpart - duplicate or unknown
partreferences - invalid authorization token
- manifest/file hash mismatch
Relationship to Existing Blossom Endpoints
This proposal does not replace PUT /upload.
- clients may continue using standard single-blob upload
- servers may support only
PUT /upload - clients should fall back to single-blob upload when batch upload is unavailable
Suggested Capability Advertisement
If Blossom evolves a capability advertisement document, this proposal should be advertised explicitly, for example:
{ "batch_upload": true, "max_batch_items": 32, "max_batch_bytes": 52428800, "partial_success": true}Until then, clients should treat POST /upload-batch support as implementation-specific.
Open Questions
- Should partial success be required, optional, or forbidden?
- Should there be a
HEAD /upload-batchpreflight endpoint for validating a manifest before sending bytes? - Should manifest
typebe required or advisory? - Should the response preserve request order, or may it be server-defined?
- Should uploaded parts be allowed to omit
filenameentirely?
Recommendation
If proposed upstream, this should be a new BUD with a new endpoint, not a reinterpretation of BUD-02.
That keeps current Blossom upload semantics stable while allowing attachment-heavy clients to reduce upload overhead substantially.