114 Commits

Author SHA1 Message Date
hzrd149
342cae9e51 switch URI to use "blossom" instead of "blob" 2025-11-05 13:48:17 -06:00
hzrd149
05a6c68dd8 Require file extension 2025-11-04 09:48:40 -06:00
hzrd149
fe8906369c Add blob URI spec
Another BUD-10
2025-11-04 09:44:15 -06:00
hzrd149
f1847b56d7 Merge pull request #65 from hzrd149/list-pagination
Use cursor based pagination instead of date based pagination
2025-11-04 09:18:31 -06:00
hzrd149
0ccf399577 Merge branch 'master' into list-pagination 2025-11-04 09:17:20 -06:00
hzrd149
7efca7a2a5 Update pagination method for /list/<pubkey> endpoint 2025-11-04 09:14:33 -06:00
hzrd149
e8d0a1ec44 Merge pull request #29 from quentintaranpino/BUD07-paid-storage
BUD-07 Paid storage
2025-07-30 12:58:36 -05:00
hzrd149
847f449acf Merge branch 'master' into BUD07-paid-storage 2025-07-30 12:57:34 -05:00
hzrd149
90affdd4d9 Update to use cashu NUT-24 2025-07-30 12:55:58 -05:00
hzrd149
385913adef Merge pull request #74 from aaccioly-open-source/docs/make-file-extension-detection-mandatory
Clarify requirements around file extensions, Content-Type, Content-Length and redirection.
2025-06-23 17:41:30 -05:00
Anthony Accioly
39ce39aa4d fix: correct grammar in bud/01 redirect requirements
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2025-06-23 14:21:32 +01:00
Anthony Accioly
85de0197f0 fix: correct typo in Content-Length headers description in blob retrieval documentation 2025-06-17 23:18:13 +01:00
Anthony Accioly
658c608b11 fix: update authorization event reference link in mirroring documentation 2025-06-17 23:03:27 +01:00
Anthony Accioly
b1a336fe75 Add optional file extension normalization during upload 2025-06-17 23:03:27 +01:00
Anthony Accioly
611272e251 Enhance proxying and redirection specification for blob retrieval 2025-06-17 23:03:27 +01:00
Anthony Accioly
1a085ed7bf fix: clarify Content-Type handling for blob retrieval and mirroring 2025-06-17 23:02:05 +01:00
Anthony Accioly
cacfa520dd Clarify requirements around Content-Type and Content-Length
- Specify that the server must return the MIME type in the Content-Type header for blob retrieval.
- Clarify fallback behaviour for unknown MIME types to application/octet-stream.
- Improve the description of how servers should infer MIME types and handle Content-Length for mirror requests.
2025-06-17 23:01:20 +01:00
Anthony Accioly
5ef2889547 Make type mandatory in the blob descriptor 2025-06-17 22:54:54 +01:00
hzrd149
e1299a6ce5 Merge pull request #73 from hzrd149/update-has-blob
Clarify has blob endpoint in BUD-01
2025-06-17 15:50:04 -05:00
hzrd149
6a27b156ba Merge pull request #71 from hzrd149/define-buds
Add BUD-00 to define BUDs and common language
2025-06-17 15:21:31 -05:00
hzrd149
977d0be083 explicitly require content-type and content-length 2025-06-17 15:00:33 -05:00
hzrd149
2cbdc130a0 Merge pull request #70 from hzrd149/missing-head
Add missing HEAD for CORS headers
2025-06-17 14:55:42 -05:00
hzrd149
065756a976 Merge pull request #75 from SwimmingRieux/patch-1
Fix typo: Change 'where' to 'were' in (BUD-02)
2025-06-09 18:21:24 -05:00
Sadeq
d6c2f9721f Fix typo: Change 'where' to 'were' in Blob upload and management (BUD-02) 2025-06-06 18:56:56 +03:30
hzrd149
3f2aa40eb9 Merge pull request #72 from hzrd149/clarify-bud-04
Clarify wording on BUD-04
2025-05-30 11:34:42 -05:00
hzrd149
0baee02851 add fallback to application/octet-stream 2025-05-24 12:08:00 -05:00
hzrd149
620d74c2a2 Clarify has blob endpoint in BUD-01
Require headers to be identical to get endpoint
2025-05-13 10:50:44 -05:00
hzrd149
2d1593d634 Clarify wording on BUD-04 2025-05-13 10:32:09 -05:00
hzrd149
fca1c42406 Add missing HEAD for CORS headers 2025-05-13 09:31:54 -05:00
hzrd149
66e6dcec74 Add BUD-00 to define BUDs and common language 2025-05-13 09:31:19 -05:00
hzrd149
3ae2361b41 switch to cursor and limit with optional date filters 2025-05-12 09:38:25 -05:00
hzrd149
2aa65cc373 Fix spelling mistakes 2025-04-25 08:00:47 -05:00
Quentin
542c654045 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2025-04-20 18:37:03 +02:00
hzrd149
39d1ae9e93 add alternative line for cursor based pagination 2025-03-30 10:13:35 +01:00
hzrd149
a63959f1e0 Use offset limit pagination instead of date based pagination 2025-03-30 10:02:21 +01:00
hzrd149
60e9f287fe Merge pull request #62 from hzrd149/mirror-clarify-auth
Clarify authorization requirements in BUD-04
2025-03-30 09:46:16 +01:00
hzrd149
782d382ca7 Clarify authorization requirements in BUD-04: change MUST to MAY for the Authorization header and specify auth type 2025-03-17 21:41:34 +00:00
hzrd149
6105ea6a6f Merge pull request #60 from v0l/patch-2
Use array for nip94 tags
2025-03-09 09:17:20 +00:00
Kieran
a3546a5bc3 Update 08.md 2025-02-26 21:20:25 +00:00
Kieran
9d8b3cb677 Update 08.md 2025-02-26 21:16:03 +00:00
hzrd149
b29ada0e11 Update README.md 2025-02-11 08:59:38 -06:00
hzrd149
9832ac4582 Merge pull request #38 from hzrd149/require-ext-in-url
modify BUD-02: require the file extension in the url field
2025-02-06 12:25:19 -06:00
hzrd149
d5225114af Merge pull request #54 from hzrd149/require-media-auth
Change /media endpoint to require "media" auth
2025-01-28 18:14:35 -06:00
hzrd149
55781b0125 Merge pull request #56 from kehiy/report-07
bud-09: blob report.
2025-01-28 18:03:38 -06:00
k.
eaa37c348d Update 09.md 2025-01-07 17:37:14 +00:00
k.
52abe4467a Update 09.md 2025-01-04 19:01:39 +00:00
k.
8487a70a22 Update buds/09.md
Co-authored-by: Kieran <kieran@harkin.me>
2025-01-04 17:38:54 +00:00
k.
9e468f8749 Update buds/09.md
Co-authored-by: Kieran <kieran@harkin.me>
2025-01-04 17:37:58 +00:00
k.
72d5c1690a Update README.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2025-01-03 14:59:53 +00:00
k.
287b32b531 Update buds/01.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2025-01-03 14:59:39 +00:00
Kay
4e6e322aa3 fix requests. 2025-01-03 12:55:43 +00:00
Kay
fa676debf3 fix requests. 2025-01-03 12:51:09 +00:00
Kay
e5462c3e1a small fixes. 2025-01-02 11:18:02 +00:00
Kay
7a9111f54d small fixes. 2025-01-02 11:17:48 +00:00
Kay
29cbfbf504 bud-07: media report. 2025-01-02 11:13:28 +00:00
hzrd149
995f715c96 Merge pull request #55 from kehiy/master
typos.
2025-01-01 14:03:41 -06:00
k.
550d8693e0 Update 04.md 2025-01-01 19:38:47 +00:00
k.
b50a5374b3 Update 01.md 2025-01-01 19:38:07 +00:00
hzrd149
c195efdf30 Change /media endpoint to require "media" auth 2024-12-26 09:44:15 -06:00
hzrd149
8b5d740aa4 Merge pull request #49 from hzrd149/bud-08-fix-size
Require NIP-94 values to be strings
2024-12-08 13:03:16 -06:00
hzrd149
db49443b1f Merge pull request #50 from hzrd149/clarify-root-paths
Clarify root paths
2024-12-03 12:19:19 -06:00
quentintaranpino
8e12280410 fix typo 2024-12-03 13:06:04 +01:00
quentintaranpino
4d9b22a96c remove recurring payments 2024-12-03 13:03:23 +01:00
Quentin
3cb8c92197 Merge branch 'master' into BUD07-paid-storage 2024-12-03 13:02:24 +01:00
hzrd149
a91360634f Merge pull request #47 from hzrd149/range-requests
Recomend range requests to BUD-01
2024-12-02 14:51:28 -06:00
hzrd149
c99b4898f5 add comment about videos 2024-12-02 10:56:43 -06:00
hzrd149
1a44035b7d spelling 2024-12-02 10:52:00 -06:00
hzrd149
ec40af6b95 clarify root paths 2024-12-02 10:50:46 -06:00
hzrd149
13fa0f485d Merge pull request #42 from hzrd149/media-head
Update BUD-05: Add HEAD /media endpoint
2024-11-30 18:49:02 -06:00
hzrd149
34a50d09f5 require NIP-94 values to be strings 2024-11-26 09:15:39 -06:00
hzrd149
36a741a87b add range requests section to BUD-01 2024-11-23 09:26:38 -06:00
hzrd149
c5d90aa74d Add HEAD /media endpoint 2024-11-22 16:51:51 -06:00
hzrd149
2d7e013b47 BUD-02 require the file extension in the url field 2024-11-22 13:44:50 -06:00
hzrd149
854218f573 fix header in BUD-05 2024-11-21 15:16:59 -06:00
hzrd149
bafed19c7f Add BUD-05 to readme 2024-11-21 15:16:21 -06:00
hzrd149
37f6255e4e Merge pull request #21 from hzrd149/media-endpoint
BUD-05 Media optimazation endpoint
2024-11-21 15:13:54 -06:00
Quentin
463f28da7b error handling 402->400. Special note for Head requests 2024-11-20 21:22:20 +01:00
Quentin
73fcfbfbd3 update BUD-07 2024-11-20 20:57:46 +01:00
Quentin
f9f44fc592 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-11-20 16:32:04 +01:00
Quentin
38274c6a5e Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-11-20 16:28:13 +01:00
Quentin
8f95ad7468 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-11-20 16:27:35 +01:00
Quentin
ffe55bbffc Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-11-20 16:26:17 +01:00
Quentin
0d039843a0 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-11-20 16:25:58 +01:00
Quentin
cda53cf47a Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-11-20 16:25:33 +01:00
Quentin
e003b22318 Fix typos. 2024-11-20 12:40:39 +01:00
Quentin
8600dbecfc Recurring payments. 2024-11-20 12:35:18 +01:00
Quentin
0aa5a9dd6f Refactored to clarify payment header encoding and method-specific requirements 2024-11-20 12:14:00 +01:00
Quentin
18a57e361c Merge branch 'master' into BUD07-paid-storage 2024-11-19 10:45:46 +01:00
Quentin
970fc2b072 fix typo 2024-11-18 12:41:51 +01:00
Quentin
8a4728e3e6 remove some texts 2024-11-18 12:41:43 +01:00
Quentin
b450680b00 fix typo 2024-11-18 12:39:10 +01:00
Quentin
3524b81bac fix typos 2024-11-18 12:37:37 +01:00
Quentin
bf417ae115 using different headers for each payment method 2024-11-18 12:28:43 +01:00
hzrd149
afa1290a6a Merge pull request #32 from fiatjaf/x-reason
X-Reason, a header for all user-facing error messages to go
2024-11-12 14:20:13 +00:00
Quentin
5c0ecbb4fa fix typo 2024-11-12 10:01:43 +01:00
fiatjaf
b7e4e96ed5 remove old Error Responses section. 2024-11-11 13:03:56 -03:00
hzrd149
ee1fca7ef5 fix headers on BUD-08 2024-11-11 11:54:47 +00:00
hzrd149
06edffe984 Merge pull request #33 from lescuer97/optional_auth
Change auth  for upload as optional
2024-11-11 10:22:28 +00:00
hzrd149
097537d70c Merge pull request #34 from aaccioly-open-source/expand-on-cors-headers
Expand BUD-01 CORS headers documentation
2024-11-06 09:35:13 +00:00
Anthony Accioly
1262ffa989 Expand BUD-01 CORS headers documentation 2024-11-05 22:14:38 +00:00
leonardo
5d774643e8 auth for upload as optional 2024-11-02 13:55:53 +00:00
Quentin
942fb60e97 Update BUD-07 for multiple L2; discard L402 2024-11-01 10:55:49 +01:00
fiatjaf
c746be27e3 X-Reason, a header for all user-facing error messages to go. 2024-10-29 13:11:34 -03:00
quentintaranpino
cd778dec22 change backward compatibility text 2024-09-16 09:22:58 +02:00
quentintaranpino
40a7cd943c fix typos 2024-09-12 10:04:30 +02:00
quentintaranpino
7a57b0c19a Backward compatibility proposal 2024-09-12 10:00:58 +02:00
Quentin
f0ac329e90 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-09-12 09:48:34 +02:00
Quentin
b6bd9b9a94 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-09-12 09:48:26 +02:00
Quentin
c3f7a5da0d Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-09-12 09:48:20 +02:00
Quentin
17d6814fd0 Update buds/07.md
Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com>
2024-09-12 09:48:05 +02:00
Quentin
2bd04954a4 Paid storage 2024-09-10 10:41:34 +02:00
hzrd149
81bd6f856f simplify media endpoint 2024-09-09 14:57:46 -05:00
hzrd149
85f5b57245 Merge branch 'master' into media-endpoint 2024-09-09 14:57:22 -05:00
hzrd149
73461b47b2 add rough draft for media endpoint 2024-07-30 20:17:29 -05:00
12 changed files with 560 additions and 101 deletions

View File

@@ -4,15 +4,33 @@ Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private k
## What is it?
Blossom is a spec for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers
Blossom is a specification for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers
## What are blobs
Blobs are packs of binary data addressed by their sha256 hash
## How does it work?
## Protocol specification (BUDs)
Blossom Servers expose four endpoints for managing blobs
BUDs or **Blossom Upgrade Documents** are short documents that outline an additional feature that a blossom server may implement.
## BUDs
- [BUD-00: Blossom Upgrade Documents](./buds/00.md)
- [BUD-01: Server requirements and blob retrieval](./buds/01.md)
- [BUD-02: Blob upload and management](./buds/02.md)
- [BUD-03: User Server List](./buds/03.md)
- [BUD-04: Mirroring blobs](./buds/04.md)
- [BUD-05: Media optimization](./buds/05.md)
- [BUD-06: Upload requirements](./buds/06.md)
- [BUD-07: Payment required](./buds/07.md)
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
- [BUD-09: Blob Report](./buds/09.md)
- [BUD-10: Blossom URI Schema](./buds/10.md)
## Endpoints
Blossom Servers expose a few endpoints for managing blobs
- `GET /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob)
- `HEAD /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob)
@@ -27,21 +45,10 @@ Blossom Servers expose four endpoints for managing blobs
- `Authentication`: Signed [nostr event](./buds/02.md#delete-authorization-required)
- `PUT /mirror` [BUD-04](./buds/04.md#put-mirror---mirror-blob)
- `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required)
## Protocol specification (BUDs)
BUDs stand for **Blossom Upgrade Documents**.
See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-02](./buds/02.md) for a detailed explanation of the endpoints
## BUDs
- [BUD-01: Server requirements and blob retrieval](./buds/01.md)
- [BUD-02: Blob upload and management](./buds/02.md)
- [BUD-03: User Server List](./buds/03.md)
- [BUD-04: Mirroring blobs](./buds/04.md)
- [BUD-06: Upload requirements](./buds/06.md)
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
- `HEAD /media` [BUD-05](./buds/05.md#head-media)
- `PUT /media` [BUD-05](./buds/05.md#put-media)
- `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization)
- `PUT /report` [BUD-09](./buds/09.md)
## Event kinds

19
buds/00.md Normal file
View File

@@ -0,0 +1,19 @@
# BUD-00
## Blossom Upgrade Documents
`draft` `mandatory`
This document details the common language for all following BUDs
## Language
All occurences of "MUST", "MUST NOT", "SHOULD", "SHOULD NOT" MUST be interpreted as per [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119)
## BUDs
BUDs or "Blossom Upgrade Documents" are short documents that outline an additional requirement or feature that a blossom server MUST or MAY implement.
## Blobs
Blobs are raw binary data addressed by the sha256 hash of the data.

View File

@@ -8,7 +8,17 @@ _All pubkeys MUST be in hex format_
## Cross origin headers
Servers MUST set the `Access-Control-Allow-Origin: *`, `Access-Control-Allow-Headers: Authorization,*` and `Access-Control-Allow-Methods: GET, PUT, DELETE` headers on all endpoints to ensure compatibility with apps hosted on other domains
Servers MUST set the `Access-Control-Allow-Origin: *` header on all responses to ensure compatibility with applications hosted on other domains.
For [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests) (`OPTIONS`) requests,
servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, HEAD, PUT,
DELETE` headers.
The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours.
## Error responses
Every time a server sends an error response (HTTP status codes >=400), it may include a human-readable header `X-Reason` that can be displayed to the user.
## Authorization events
@@ -18,7 +28,7 @@ Authorization events must be generic and must NOT be scoped to specific servers.
Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, or `delete`
Events MUST have the `content` set to a human readable string explaining to the user what the events inteded use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc
Events MUST have the `content` set to a human readable string explaining to the user what the events intended use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc
All events MUST have a [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md) `expiration` tag set to a unix timestamp at which the event should be considered expired.
@@ -26,7 +36,7 @@ Authorization events MAY have multiple `x` tags for endpoints that require a sha
Example event:
```json
```jsonc
{
"id": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb",
"pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e",
@@ -35,7 +45,7 @@ Example event:
"created_at": 1708773959,
"tags": [
["t", "upload"],
// Authorization events MAY have multiple "x" tags
// Authorization events MAY have multiple "x" tags.
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
["expiration", "1708858680"]
],
@@ -61,42 +71,39 @@ Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQ
## Endpoints
All endpoints MUST be served from the root path (eg. `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs
## Error Responses
For HTTP `4xx` and `5xx` status codes servers MUST repond with `Content-Type: application/json` and a JSON object containing `message`
The `message` field MUST be human readable and should explain the reason for the error. Optionally servers may include other fields for the client with more information about the error
Example Error response:
```
HTTP/2 401
content-type: application/json; charset=utf-8
content-length: 32
access-control-allow-origin: *
access-control-expose-headers: *
access-control-allow-headers: authorization,*
access-control-allow-methods: get, put, delete
{"message":"Missing Auth event"}
```
All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST be accessible from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs
## GET /sha256 - Get Blob
The `GET /<sha256>` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME type
The `GET /<sha256>` endpoint MUST return the contents of the blob in the response body. the `Content-Type` header SHOULD beset to the appropriate MIME-type
The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc
If the endpoints returns a 301 or 302 redirect it MUST redirect to a URL containing the same sha256 hash as requested blob.
This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash
Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` header. If the
server does not know the MIME type of the blob, it MUST default to `application/octet-stream`
### Proxying and Redirection (Optional)
If the endpoint returns a redirection 3xx status code such as 307 or 308 ([RFC 9110 section
15.4](https://datatracker.ietf.org/doc/html/rfc9110#name-redirection-3xx)), it MUST redirect to a URL containing the
same sha256 hash as the requested blob. This ensures that if a user copies or reuses the redirect URL, it will
contain the original sha256 hash.
While the final blob may not be served from a Blossom server (e.g. CDN, IPFS, object storage, etc.), the destination
server MUST set the `Access-Control-Allow-Origin: *` header on the response to allow cross-origin requests, as well as
the `Content-Type` and `Content-Length` headers to ensure the blob can be correctly displayed by clients. Two ways to
guarantee this are:
1. Proxying the blob through the Blossom server, allowing it to override headers such as `Content-Type`.
2. Manipulating the redirect URL to include a file extension that matches the blob type, such as `.pdf`, `.png`, etc. If
the server is unable to determine the MIME type of the blob, it MUST default to `application/octet-stream` and MAY
include a file extension in the URL that reflects the blob type (e.g. `.bin`, `.dat`, etc.).
### Get Authorization (optional)
The server may optionally require authorization when retrieving blobs from the `GET /<sha256>` endpoint
In this case the server MUST perform additional checks on the authorization event
In this case, the server MUST perform additional checks on the authorization event
1. A `t` tag MUST be present and set to `get`
2. The event MUST contain either a `server` tag containing the full URL to the server or MUST contain at least one `x` tag matching the sha256 hash of the blob being retrieved
@@ -141,6 +148,15 @@ Example event for retrieving multiple blobs from single server:
## HEAD /sha256 - Has Blob
The `HEAD /<sha256>` endpoint MUST respond with either a `200` or `404` status code
The `HEAD /<sha256>` endpoint SHOULD be identical to the `GET /<sha256>` endpoint except that it MUST NOT return the
blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2)
The endpoint MUST respond with the same `Content-Type` and `Content-Length` headers as the `GET /<sha256>` endpoint.
The endpoint MUST accept an optional file extension in the URL similar to the `GET /<sha256>` endpoint. ie. `.pdf`, `.png`, etc
## Range requests
To better support mobile devices, video files, or low bandwidth connections. servers should support range requests ([RFC 7233 section 3](https://www.rfc-editor.org/rfc/rfc7233#section-3)) on the `GET /<sha256>` endpoint and signal support using the `accept-ranges: bytes` and `content-length` headers on the `HEAD /<sha256>` endpoint
See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) for more details

View File

@@ -12,12 +12,14 @@ Defines the `/upload`, `/list` and `DELETE /<sha256>` endpoints
A blob descriptor is a JSON object containing `url`, `sha256`, `size`, `type`, and `uploaded` fields
- `url` A publicly accessible URL to the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint (optionally with a file extension)
- `url` A publicly accessible URL to the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint with a file extension
- `sha256` The sha256 hash of the blob
- `size` The size of the blob in bytes
- `type` (optional) The MIME type of the blob
- `type` The MIME type of the blob (falling back to `application/octet-stream` if unknown)
- `uploaded` The unix timestamp of when the blob was uploaded to the server
Servers MUST include a file extension in the URL in the `url` field to allow clients to easily embed the URL in social posts or other content
Servers MAY include additional fields in the descriptor like `magnet`, `infohash`, or `ipfs` depending on other protocols they support
Example:
@@ -36,18 +38,25 @@ Example:
The `PUT /upload` endpoint MUST accept binary data in the body of the request and MAY use the `Content-Type` and `Content-Length` headers to get the MIME type and size of the data
The endpoint MUST NOT modify the blob in any way and should return the exact same sha256 that was uploaded. This is critical to allow users to re-upload their blobs to new servers
The endpoint MUST NOT modify the blob in any way and SHOULD return the exact same sha256 that was uploaded. This is critical to allow users to re-upload their blobs to new servers
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the upload was successful or an error object if it was not
Servers MAY reject an upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
Servers MAY reject an upload for any reason and SHOULD respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
### Upload Authorization (required)
### File extension normalization (Optional)
Servers MUST accept an authorization event when uploading blobs and should perform additional checks
When storing blobs, servers MAY normalise the file extension to a standard format (e.g. `.pdf`, `.png`, etc.) based on
the MIME type of the blob. This can be especially useful when the `GET /<sha256>` endpoint is redirected to an external
URL (see the [proxying and redirection section from BUD-01](./01.md#proxying-and-redirection-optional)), as external
servers may rely on the file extension to serve the blob correctly.
### Upload Authorization (Optional)
Servers MAY accept an authorization event when uploading blobs and SHOULD perform additional checks
1. The `t` tag MUST be set to `upload`
2. MUST contain at least one `x` tag matching the sha256 hash of the blob being uploaded
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the body of the request
Example Authorization event:
@@ -67,21 +76,23 @@ Example Authorization event:
}
```
## GET /list/pubkey - List Blobs
## GET /list/pubkey - List Blobs (Optional)
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that were uploaded by the specified pubkey
The endpoint MUST support a `since` and `until` query parameter to limit the returned blobs by their `uploaded` date
The endpoint MUST support `cursor` and `limit` query parameters for cursor based pagination. The `cursor` parameter MUST be the `sha256` hash of the last blob in the previous page, or omitted to request the first page. The `limit` parameter specifies the maximum number of results to return. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order and MUST NOT include the blob at the cursor
Servers may reject a list for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
The endpoint MAY support `since` and `until` query parameters to filter the list of blobs by their `uploaded` date. These parameters are deprecated for pagination purposes as they do not preserve server resources
Servers MAY reject a list request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
### List Authorization (optional)
The server may optionally require Authorization when listing blobs uploaded by the pubkey
The server MAY optionally require Authorization when listing blobs uploaded by the pubkey
In this case the server must perform additional checks on the authorization event
In this case the server MUST perform additional checks on the authorization event
1. The `t` tag must be set to `list`
1. The `t` tag MUST be set to `list`
Example Authorization event:
@@ -104,16 +115,16 @@ Example Authorization event:
Servers MUST accept `DELETE` requests to the `/<sha256>` endpoint
Servers may reject a delete request for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
Servers MAY reject a delete request for any reason and SHOULD respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
### Delete Authorization (required)
Servers MUST accept an authorization event when deleting blobs
Servers should perform additional checks on the authorization event
Servers SHOULD perform additional checks on the authorization event
1. The `t` tag must be set to `delete`
2. MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted
1. The `t` tag MUST be set to `delete`
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted
When multiple `x` tags are present on the authorization event the server MUST only delete the blob listed in the URL.

View File

@@ -68,7 +68,7 @@ Take the following event as an example
Once the client discovers that the URL `https://cdn.broken-domain.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf` is no longer available. It can perform the following steps to find the blob:
1. Get the SHA256 has from the URL
1. Get the SHA256 hash from the URL
2. Look for the authors server list `kind:10063`
3. If found, Attempt to retrieve the blob from each `server` listed started with the first
4. If not found, the client MAY fallback to using a well-known popular blossom server to retrieve the blob

View File

@@ -8,34 +8,39 @@ Defines the `/mirror` endpoint
## PUT /mirror - Mirror Blob
A server may expose a `PUT /mirror` endpoint to allow users to copy a blob from a URL instead of uploading it
A server MAY expose a `PUT /mirror` endpoint to allow users to copy a blob from a URL instead of uploading it
Clients MUST pass the URL of the remote blob as a stringified JSON object in the request body
```json
// request body
```jsonc
// request body...
{
"url": "https://cdn.satellite.earth/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf"
}
```
Clients MUST set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-required)
Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-optional). When using authorization, the event MUST be of type "upload".
The `/mirror` endpoint MUST download the blob from the specified URL and verify that there is at least one `x` tag in the authorization event matching the sha256 hash of the download blob
**Multiple `x` tags MUST NOT be interpreted as the user requesting a bulk mirror.**
**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting to mirror multiple blobs.**
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the mirroring was successful or an error object if it was not
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful
or a `4xx` status code and error message if it was not.
Servers should re-use the `Content-Type` header returned from the URL to discover the mime type of the blob. if none is returned it may use the file extension in the URL
The destination server SHOULD use the `Content-Type` header returned from the origin server to infer the mime type of
the blob. If the `Content-Type` header is not present the destination server SHOULD attempt to detect the `Content-Type`
from the blob contents and file extension, falling back to `application/octet-stream` if it cannot determine the type.
Servers MAY reject a mirror request for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
Servers MAY use the `Content-Length` header to determine the size of the blob.
Servers MAY reject a mirror request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection.
## Example Flow
1. Client signs authorization event and uploads blob to Server A
1. Server A returns blob descriptor with `url`
1. Client sends the `url` to Server B `/mirror` using the original authorization event
1. Server B downloads blob from Server A using the url
1. Server B verifies downloaded blob hash matches `x` tag in authorization event
1. Server B returns [Blob Descriptor](./02.md#blob-descriptor)
1. Client signs an `upload` authorization event and uploads blob to Server A
1. Server A returns a [Blob Descriptor](./02.md#blob-descriptor) with the `url`
1. Client sends the `url` to Server B `/mirror` using the original `upload` authorization event
1. Server B downloads the blob from Server A using the `url`
1. Server B verifies the downloaded blob hash matches the `x` tag in the authorization event
1. Server B returns a [Blob Descriptor](./02.md#blob-descriptor)

48
buds/05.md Normal file
View File

@@ -0,0 +1,48 @@
# BUD-05
## Media optimization endpoints
`draft` `optional`
Defines the `PUT /media` endpoint for processing and optimizing media
## PUT /media
The `PUT /media` endpoint MUST accept binary data in the body of the request and MAY use the `Content-Type` and `Content-Length` headers to get the MIME type and size of the media
The server should preform any optimizations or conversions it deems necessary in order to make the media more suitable for distribution
The endpoint MUST respond with a `2xx` status and a [blob descriptor](./02.md#blob-descriptor) of the new processed blob
Servers MAY reject media uploads for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
### Upload Authorization
Servers MAY require a `media` [authorization event](./02.md#upload-authorization-required) to identify the uploader
If a server requires a `media` authorization event it MUST perform the following checks
1. The `t` tag MUST be set to `media`
2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request
## HEAD /media
Servers MUST respond to `HEAD` requests on the `/media` endpoint in a similar way to the `HEAD /upload` endpoint defined in [BUD-06](./06.md)
## Limitations
This endpoint is intentionally limited to optimizing a single blob with the goal of making it easier to distribute
How the blob is optimized is the sole responsibility of the server and the client should have no say in what optimization process is used
The goal of this endpoint is to provide a simple "trusted" optimization endpoint clients can use to optimize media for distribution
If a longer optimization or transformation process is needed, or if the client needs to specify how a blob should be transformed. there are other tools and protocol that should be used.
## Client Implementation
Clients MAY let a user selected a "trusted processing" server for uploading images or short videos
Once a server has been selected, the client uploads the original media to the `/media` endpoint of the trusted server and get the optimized blob back
Then the client can ask the user to sign another `upload` authorization event for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob

View File

@@ -8,14 +8,13 @@ Defines how clients can verify if the upload can be completed before sending the
## HEAD /upload - Upload requirements
The `HEAD /upload` endpoint `MUST` use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Upload-Message` to indicate some human readable message about the upload requirements.
The `HEAD /upload` endpoint MUST use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Reason` to indicate some human readable message about the upload requirements.
### Headers
- `X-SHA-256`: A string that represents the blob's SHA-256 hash.
- `X-Content-Length`: An integer that represents the blob size in bytes.
- `X-Content-Type`: A string that specifies the blob's MIME type, like `application/pdf` or `image/png`.
- `X-Upload-Message`: A human readable message that explains the reason why the upload cannot proceed.
### Upload Authorization
@@ -39,36 +38,36 @@ Example response from the server if the upload can be done:
HTTP/1.1 200 OK
```
If the upload cannot proceed, the server `MUST` return an appropriate `4xx` HTTP status code and a custom header `X-Upload-Message` with a human readable error message.
If the upload cannot proceed, the server MUST return an appropriate `4xx` HTTP status code and a custom header `X-Reason` with a human readable error message.
Some examples of error messages:
```http
HTTP/1.1 400 Bad Request
X-Upload-Message: Invalid X-SHA-256 header format. Expected a string.
X-Reason: Invalid X-SHA-256 header format. Expected a string.
```
```http
HTTP/1.1 401 Unauthorized
X-Upload-Message: Authorization required for uploading video files.
X-Reason: Authorization required for uploading video files.
```
```http
HTTP/1.1 403 Forbidden
X-Upload-Message: SHA-256 hash banned.
X-Reason: SHA-256 hash banned.
```
```http
HTTP/1.1 411 Length Required
X-Upload-Message: Missing X-Content-Length header.
X-Reason: Missing X-Content-Length header.
```
```http
HTTP/1.1 413 Content Too Large
X-Upload-Message: File too large. Max allowed size is 100MB.
X-Reason: File too large. Max allowed size is 100MB.
```
```http
HTTP/1.1 415 Unsupported Media Type
X-Upload-Message: Unsupported file type.
X-Reason: Unsupported file type.
```

105
buds/07.md Normal file
View File

@@ -0,0 +1,105 @@
BUD-07
======
Paid upload and download
---------------
`draft` `optional`
Payment requirements for blob storage.
## Payment Required
Some servers MAY require payment for uploads, downloads, or any other endpoint. In such cases, these endpoints MUST return a **402 Payment Required** status code.
Some endpoints a server may require payment for:
- [`HEAD /upload`](./06.md) to signal that payment is required for the `PUT` request ( if [BUD-06](./06.md) is supported )
- [`PUT /upload`](./02.md#put-upload---upload-blob) to require payment for uploads
- [`HEAD /<sha256>`](./01.md#head-sha256---has-blob) to signal that payment is required for the `GET` request
- [`GET /<sha256>`](./01.md#get-sha256---get-blob) to require payment for downloads ( maybe charge by MB downloaded? )
- [`HEAD /media`](./05.md) and [`PUT /upload`](./05.md) to require payment for media optimizations ( if [BUD-06](./06.md) is supported )
When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method.
## Server headers
The 402 status code and `X-{payment_method}` header is used by the server to inform the client that a payment is required for the requested operation. The server MUST provide specific headers for each supported payment method.
Supported payment methods:
- `X-Cashu`: Payment details for the cashu payment method, adhering to the [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md) standard.
- `X-Lightning`: Payment details for the lightning payment method, adhering to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard.
If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response.
Schema:
```http
HTTP/1.1 402 Payment Required
X-{payment_method}: "<encoded_payload_according_to_{payment_method}_spec>"
```
### `X-Cashu` Header
When using the X-Cashu header, the server MUST adhere to the [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md) standard.
Example for cashu:
```http
HTTP/1.1 402 Payment Required
X-Cashu: creqApWF0gaNhdGVub3N0cmFheKlucHJvZmlsZTFxeTI4d3VtbjhnaGo3dW45ZDNzaGp0bnl2OWtoMnVld2Q5aHN6OW1od2RlbjV0ZTB3ZmprY2N0ZTljdXJ4dmVuOWVlaHFjdHJ2NWhzenJ0aHdkZW41dGUwZGVoaHh0bnZkYWtxcWd5ZGFxeTdjdXJrNDM5eWtwdGt5c3Y3dWRoZGh1NjhzdWNtMjk1YWtxZWZkZWhrZjBkNDk1Y3d1bmw1YWeBgmFuYjE3YWloYjdhOTAxNzZhYQphdWNzYXRhbYF4Imh0dHBzOi8vbm9mZWVzLnRlc3RudXQuY2FzaHUuc3BhY2U
```
### `X-Lightning` Header
When using the X-Lightning header, the server MUST adhere to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard.
Example for lightning:
```http
HTTP/1.1 402 Payment Required
X-Lightning: lnbc30n1pnnmw3lpp57727jjq8zxctahfavqacymellq56l70f7lwfkmhxfjva6dgul2zqhp5w48l28v60yvythn6qvnpq0lez54422a042yaw4kq8arvd68a6n7qcqzzsxqyz5vqsp5sqezejdfaxx5hge83tf59a50h6gagwah59fjn9mw2d5mn278jkys9qxpqysgqt2q2lhjl9kgfaqz864mhlsspftzdyr642lf3zdt6ljqj6wmathdhtgcn0e6f4ym34jl0qkt6gwnllygvzkhdlpq64c6yv3rta2hyzlqp8k28pz
```
### Client implementation
Clients MUST parse and validate the `X-{payment_method}` header received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the same `X-{payment_method}` header.
The client MUST provide the payment proof when re-trying the request using the same `X-{payment_method}` header that was chosen. The payment proof MUST align with the payment method specification:
- For cashu the payment proof should be a serialized `cashuB` token in the `X-Cashu` header according to [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md#client-payment).
- For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md).
Schema:
```http
X-{payment_method}: "<encoded_payment_proof_according_to_{payment_method}_spec>"
```
Example for Cashu:
```http
X-Cashu: cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4NTAxNDkyMThhZjkwZjcxNmE1MmJmNGE1ZWQzNDdlNDhlY2MxM2Y3NzM4OGFjWCECRFODGd5IXVW
```
Example for Lightning:
```http
X-Lightning: 966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba
```
**Special Note on HEAD Requests**
The HEAD endpoints are only used to retrieve blob or server information. They MUST NOT be retried with payment proof. Instead, clients should complete the payment and proceed with the `PUT` or `GET` request.
### Error handling
If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **400 Bad request** status code and include a `X-Reason` header with a human-readable message. The client SHOULD inform the user about the error and provide a way to retry the request.
### Extending with Future Payment Methods
To support future payment methods (e.g., other Layer 2 solutions), the specification allows the addition of new X-{payment_method} headers. Each new method MUST adhere to the following:
New methods MUST use a unique `X-{payment_method}` header containing the specific payment details.
New methods MUST adhere their own specification, which MUST be publicly available and linked in the header.

View File

@@ -1,16 +1,18 @@
# Nostr File Metadata Tags
# BUD-08
## Nostr File Metadata Tags
`draft` `optional`
Describes how a server could return nostr [NIP-94 File Metadata](https://github.com/nostr-protocol/nips/blob/master/94.md) tags from the `/upload` and `/mirror` endpoints
## Returning tags
### Returning tags
As described in [BUD-02](./02.md#blob-descriptor) servers MAY add any additional fields to a blob descriptor
Servers MAY return an additional `nip94` field in the [blob descriptor](./02.md#blob-descriptor) from the `/upload` or `/mirror` endpoints
The `nip94` field should contain a JSON object with the keys being the tag names defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md)
The `nip94` field should contain a JSON array with KV pairs as defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md)
An example response would look like:
@@ -21,13 +23,13 @@ An example response would look like:
"size": 184292,
"type": "application/pdf",
"uploaded": 1725909682,
"nip94": {
"url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf",
"m": "application/pdf",
"x": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
"size": 184292,
"magnet": "magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf",
"i": "9804c5286a3fb07b2244c968b39bc3cc814313bc"
}
"nip94": [
["url", "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf"],
["m", "application/pdf"],
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
["size", "184292"],
["magnet", "magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf"],
["i", "9804c5286a3fb07b2244c968b39bc3cc814313bc"]
]
}
```

40
buds/09.md Normal file
View File

@@ -0,0 +1,40 @@
# BUD-09
## Blob Report
`draft` `optional`
This bud defines a new endpoint for clients and users to report blobs to servers.
### PUT /report - reporting a blob
The request body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with one or more `x` tags containing the hashes of the blobs being reported.
Example:
```jsonc
{
"kind": 1984,
"tags": [
["x", "<blob-sha256>", "<type-based-on-nip-56>"],
["x", "<another-blob-sha256>", "<type-based-on-nip-56>"]
],
"content": "<human readable report details>",
// other fields...
}
```
The clients can include `e` or `p` tags to point to the event or the profile that contains this media if they want to make this report event useful for relays as well.
Server MUST respond to a report request with a success code or a code in the 4xx/5xx range if there was any error.
### Client behavior
The clients can show a blob report button on posts or in blob details. Or its RECOMMENDED to merge this with normal nostr report and send it to both relays and blossom server. other clients can receive it from relays and hide or blur reported blob from trusted friends.
### Server behavior
The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request.
Servers MAY consider removed blobs sha256 as blocked to prevent rewrite.
Servers SHOULD advertise a route or landing page to provide their rules and terms of service which affects the report process.

207
buds/10.md Normal file
View File

@@ -0,0 +1,207 @@
# BUD-10
## Blossom URI Schema
`draft` `optional`
Defines a URI schema for referencing Blossom blobs similar to magnet links. This allows users to share blob references that include discovery hints for locating the blob on other Blossom servers.
## URI Format
The `blossom:` URI schema MUST follow this format:
```
blossom:<sha256>.<ext>[?param1=value1&param2=value2...]
```
### Components
- `blossom:` - The URI scheme identifier
- `<sha256>` - A 64 character lowercase hexadecimal sha256 hash of the blob
- `.<ext>` - A file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`). If the file extension is unknown, it MUST default to `.bin`
- `[?params]` - Optional query parameters for discovery hints
### Examples
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin
```
## Query Parameters
The `blossom:` URI MAY include the following optional query parameters to assist with blob discovery:
### `as` - Author
The `as` parameter specifies the hex pubkey of a user who uploaded the blob. This parameter MAY be repeated multiple times to specify multiple potential authors.
Clients can use this parameter to lookup the author's [BUD-03](./03.md) server list (`kind:10063`) and attempt to retrieve the blob from those servers.
Example:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0
```
Multiple authors:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036
```
### `xs` - Server
The `xs` parameter specifies a server domain where the blob may be available. This parameter MAY be repeated multiple times to specify multiple server hints.
The value SHOULD be a domain name only. Clients MUST assume the server operates at the root of the domain as per [BUD-01](./01.md#endpoints). The protocol scheme (http/https) MAY be included but is optional. When no scheme is specified, clients SHOULD try both `https://` and `http://` with preference given to `https://`.
Example:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth
```
With optional scheme:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=https://cdn.satellite.earth
```
Multiple servers:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net
```
### `sz` - Size
The `sz` parameter MAY be used to specify the size of the blob in bytes. This can help clients:
- Verify the downloaded blob matches the expected size
- Display download progress or estimated time
- Decide whether to download the blob based on size constraints
- Pre-allocate storage space
Example:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?sz=184292
```
The size MUST be a positive integer representing the exact number of bytes in the blob. Clients SHOULD verify that the downloaded blob size matches the `sz` parameter if provided.
### Combined Parameters
All parameters MAY be combined in a single URI:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&xs=blossom.primal.net&sz=184292
```
## Client Implementation
### Parsing blossom URIs
When parsing a `blossom:` URI, clients MUST:
1. Verify the URI starts with the `blossom:` scheme
2. Extract the 64 character hexadecimal sha256 hash
3. Extract the file extension (which MUST be present)
4. Parse any query parameters (`as`, `xs`, and `sz`) into appropriate types to handle multiple values
### Resolution Strategy
When resolving a `blossom:` URI to retrieve the actual blob, clients SHOULD attempt retrieval in the following order:
1. **Server Hints**: If the URI contains `xs` parameters, attempt to retrieve the blob from each specified server in the order they appear
- For servers without a protocol scheme, try `https://` first, then `http://`
- Request the blob using the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint
- Include the file extension from the URI if present
- If the `sz` parameter is present, verify the `Content-Length` header matches before downloading
2. **Author Server Lists**: If the URI contains `as` parameters, for each author pubkey:
- Fetch the author's [BUD-03](./03.md) server list (`kind:10063`)
- Attempt to retrieve the blob from each server in the author's list in order
- If multiple authors are specified, try each author's server list before giving up
3. **Fallback Servers**: If the blob cannot be found using hints, clients MAY fallback to:
- Well-known public Blossom servers
- Local cache or previously known locations
- User-configured default servers
When downloading is complete, if the `sz` parameter was provided, clients SHOULD verify that the downloaded blob size matches the expected size.
### Example Resolution Flow
Given this URI:
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
```
A client would:
1. Try `http://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf`
2. Check that `Content-Length` header is `184292` before downloading
3. If that fails, fetch the `kind:10063` server list for pubkey `ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0`
4. Try each server from the author's list in order
5. Verify the downloaded blob is exactly `184292` bytes
6. If still not found, fallback to well-known servers or local cache
### Creating and Sharing blossom URIs
When creating or sharing a `blossom:` URI, clients MUST:
1. Always include the sha256 hash
2. Always include a file extension - if the file extension is unknown or cannot be determined, default to `.bin` (similar to how [BUD-01](./01.md#get-sha256---get-blob) defaults the MIME type to `application/octet-stream`)
Clients SHOULD also:
3. Include the `sz` parameter with the blob size in bytes to help with verification and download management
4. Include at least one `xs` parameter pointing to a server where the blob is known to exist
5. Include the `as` parameter with the uploader's pubkey to enable future discovery via their server list
6. Include multiple `xs` parameters if the blob has been mirrored to multiple servers
Example of creating a URI after upload:
```javascript
// After uploading to cdn.satellite.earth
const uri = `blossom:${sha256}.${ext}?xs=cdn.satellite.earth&as=${userPubkey}&sz=${size}`;
```
## Use Cases
The `blossom:` URI schema enables several use cases:
- **Decentralized Content Addressing**: Share content by hash with discovery hints instead of relying on a single server URL
- **Resilient Links**: Links that can survive server outages by including multiple server hints or author information
- **P2P Sharing**: Share blob references that don't depend on a specific server remaining online
## Examples
### Minimal URI
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
```
### Unknown File Type
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin
```
### With Single Server Hint
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth
```
### With Size and Author
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
```
### Full Featured URI
```
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
```
### Image with Multiple Authors and Servers
```
blossom:a7b3c2d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1.png?xs=cdn.example.com&xs=media.nostr.build&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036&as=b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e&sz=2547831
```