Files
blossom/buds/01.md
2026-01-13 19:48:31 -08:00

5.5 KiB

BUD-01

Server requirements and blob retrieval

draft mandatory

All pubkeys MUST be in hex format

Cross origin headers

Servers MUST set the Access-Control-Allow-Origin: * header on all responses to ensure compatibility with applications hosted on other domains.

For preflight (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.

Endpoints

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 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

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), 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 first perform the base validation checks defined in BUD-11, then perform the following additional checks:

  1. A t tag MUST be present and set to get
  2. The authorization token MUST contain either a server tag (limiting the token to specific servers) or MUST contain at least one x tag matching the sha256 hash of the blob being retrieved (scoping the token to specific blob hashes). see BUD-11.

If the client did not send an Authorization header the server must respond with the appropriate HTTP status code 401 (Unauthorized)

Example authorization token for retrieving a single blob:

{
  "id": "06d4842b9d7f8bf72440471704de4efa9ef8f0348e366d097405573994f66294",
  "pubkey": "ec0d11351457798907a3900fe465bfdc3b081be6efeb3d68c4d67774c0bc1f9a",
  "kind": 24242,
  "content": "Get bitcoin.pdf",
  "created_at": 1708771927,
  "tags": [
    ["t", "get"],
    ["expiration", "1708857340"],
    ["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"]
  ],
  "sig": "22ecb5116ba143e4c3d6dc4b53d549aed6970ec455f6d25d145e0ad1fd7c0e26c465b2e92d5fdf699c7050fa43e6a41f087ef167208d4f06425f61548168fd7f"
}

Example authorization token for retrieving multiple blobs from single server:

{
  "id": "d9484f18533d5e36f000f902a45b15a7eecf5fbfcb046789756d57ea87115dc5",
  "pubkey": "b5f07faa8d3529f03bd898a23dfb3257bab8d8f5490777c46076ff9647e205dc",
  "kind": 24242,
  "content": "Get blobs from example.com",
  "created_at": 1708771927,
  "tags": [
    ["t", "get"],
    ["expiration", "1708857340"],
    ["server", "cdn.example.com"]
  ],
  "sig": "e402ade78e1714d40cd6bd3091bc5f4ada8e904e90301b5a2b9b5f0b6e95ce908d4f22b15e9fb86f8268a2131f8adbb3d1f0e7e7afd1ab0f4f08acb15822a999"
}

HEAD /sha256 - Has Blob

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

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) 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 for more details