{"id":"defb40ec357a0b85a88c1327449681dab34b390a696cee25dba419fe96ace69d","pubkey":"1336a17e161d0e8af2b68ee95ad2a479fc38bef96a17d6127ea02a40d28dd97e","created_at":1762372097,"kind":30817,"tags":[["d","bud-10"],["title","BUD-10: Blossom URI Schema"],["summary","Defines the blossom: URI, which carries a blob hash, its extension, and hints about the servers where it can be found."],["s","draft"],["t","blossom"],["t","bud"],["alt","A specification: BUD-10: Blossom URI Schema"],["client","openspecs-import"],["published_at","1762271055"],["proxy","https://github.com/hzrd149/blossom/blob/b5bd2801d1763aa635fc8fea7a76597e0eb18990/buds/10.md","web"],["x","cf4a3d74ee8861d1b0a754cf634dd818cf0ffd0b37c56ac7e5b8f49b5006f25e"]],"content":"# BUD-10\n\n## Blossom URI Schema\n\n`draft` `optional`\n\nDefines 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.\n\n## URI Format\n\nThe `blossom:` URI schema MUST follow this format:\n\n```\nblossom:<sha256>.<ext>[?param1=value1&param2=value2...]\n```\n\n### Components\n\n- `blossom:` - The URI scheme identifier\n- `<sha256>` - A 64 character lowercase hexadecimal sha256 hash of the blob\n- `.<ext>` - A file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`). If the file extension is unknown, it MUST default to `.bin`\n- `[?params]` - Optional query parameters for discovery hints\n\n### Examples\n\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin\n```\n\n## Query Parameters\n\nThe `blossom:` URI MAY include the following optional query parameters to assist with blob discovery:\n\n### `as` - Author\n\nThe `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.\n\nClients can use this parameter to lookup the author's [BUD-03](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crx4nlkq6) server list (`kind:10063`) and attempt to retrieve the blob from those servers.\n\nExample:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0\n```\n\nMultiple authors:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036\n```\n\n### `xs` - Server\n\nThe `xs` parameter specifies a server domain where the blob may be available. This parameter MAY be repeated multiple times to specify multiple server hints.\n\nThe value SHOULD be a domain name only. Clients MUST assume the server operates at the root of the domain as per [BUD-01](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crz6eas0q#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://`.\n\nExample:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth\n```\n\nWith optional scheme:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=https://cdn.satellite.earth\n```\n\nMultiple servers:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net\n```\n\n### `sz` - Size\n\nThe `sz` parameter MAY be used to specify the size of the blob in bytes. This can help clients:\n\n- Verify the downloaded blob matches the expected size\n- Display download progress or estimated time\n- Decide whether to download the blob based on size constraints\n- Pre-allocate storage space\n\nExample:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?sz=184292\n```\n\nThe 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.\n\n### Combined Parameters\n\nAll parameters MAY be combined in a single URI:\n\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&xs=blossom.primal.net&sz=184292\n```\n\n## Client Implementation\n\n### Parsing blossom URIs\n\nWhen parsing a `blossom:` URI, clients MUST:\n\n1. Verify the URI starts with the `blossom:` scheme\n2. Extract the 64 character hexadecimal sha256 hash\n3. Extract the file extension (which MUST be present)\n4. Parse any query parameters (`as`, `xs`, and `sz`) into appropriate types to handle multiple values\n\n### Resolution Strategy\n\nWhen resolving a `blossom:` URI to retrieve the actual blob, clients SHOULD attempt retrieval in the following order:\n\n1. **Server Hints**: If the URI contains `xs` parameters, attempt to retrieve the blob from each specified server in the order they appear\n   - For servers without a protocol scheme, try `https://` first, then `http://`\n   - Request the blob using the [BUD-01](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crz6eas0q#get-sha256---get-blob) `GET /<sha256>` endpoint\n   - Include the file extension from the URI if present\n   - If the `sz` parameter is present, verify the `Content-Length` header matches before downloading\n\n2. **Author Server Lists**: If the URI contains `as` parameters, for each author pubkey:\n   - Fetch the author's [BUD-03](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crx4nlkq6) server list (`kind:10063`)\n   - Attempt to retrieve the blob from each server in the author's list in order\n   - If multiple authors are specified, try each author's server list before giving up\n\n3. **Fallback Servers**: If the blob cannot be found using hints, clients MAY fallback to:\n   - Well-known public Blossom servers\n   - Local cache or previously known locations\n   - User-configured default servers\n\nWhen downloading is complete, if the `sz` parameter was provided, clients SHOULD verify that the downloaded blob size matches the expected size.\n\n### Example Resolution Flow\n\nGiven this URI:\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292\n```\n\nA client would:\n\n1. Try `http://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf`\n2. Check that `Content-Length` header is `184292` before downloading\n3. If that fails, fetch the `kind:10063` server list for pubkey `ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0`\n4. Try each server from the author's list in order\n5. Verify the downloaded blob is exactly `184292` bytes\n6. If still not found, fallback to well-known servers or local cache\n\n### Creating and Sharing blossom URIs\n\nWhen creating or sharing a `blossom:` URI, clients MUST:\n\n1. Always include the sha256 hash\n2. Always include a file extension - if the file extension is unknown or cannot be determined, default to `.bin` (similar to how [BUD-01](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crz6eas0q#get-sha256---get-blob) defaults the MIME type to `application/octet-stream`)\n\nClients SHOULD also:\n\n3. Include the `sz` parameter with the blob size in bytes to help with verification and download management\n4. Include at least one `xs` parameter pointing to a server where the blob is known to exist\n5. Include the `as` parameter with the uploader's pubkey to enable future discovery via their server list\n6. Include multiple `xs` parameters if the blob has been mirrored to multiple servers\n\nExample of creating a URI after upload:\n\n```javascript\n// After uploading to cdn.satellite.earth\nconst uri = `blossom:${sha256}.${ext}?xs=cdn.satellite.earth&as=${userPubkey}&sz=${size}`;\n```\n\n## Use Cases\n\nThe `blossom:` URI schema enables several use cases:\n\n- **Decentralized Content Addressing**: Share content by hash with discovery hints instead of relying on a single server URL\n- **Resilient Links**: Links that can survive server outages by including multiple server hints or author information\n- **P2P Sharing**: Share blob references that don't depend on a specific server remaining online\n\n## Examples\n\n### Minimal URI\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf\n```\n\n### Unknown File Type\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin\n```\n\n### With Single Server Hint\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth\n```\n\n### With Size and Author\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292\n```\n\n### Full Featured URI\n```\nblossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292\n```\n\n### Image with Multiple Authors and Servers\n```\nblossom:a7b3c2d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1.png?xs=cdn.example.com&xs=media.nostr.build&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036&as=b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e&sz=2547831\n```\n\n","sig":"5001abdadc98127493ef8827dcca37009dac96a78100e1202f5a42f454651c11d81302b669f9cd7c37bed14054ccaf2e65a917ee0c72215433a6cf0c338449a7"}