{"id":"06a48864e71ac7d37da7288a188b2ac7b9f17150a9ef798c56e9f222aa70cca8","pubkey":"1336a17e161d0e8af2b68ee95ad2a479fc38bef96a17d6127ea02a40d28dd97e","created_at":1776353799,"kind":30817,"tags":[["d","bud-06"],["title","BUD-06: Upload requirements"],["summary","Defines HEAD /upload, a preflight request telling a client whether an upload would be accepted before it sends the bytes."],["s","draft"],["t","blossom"],["t","bud"],["alt","A specification: BUD-06: Upload requirements"],["client","openspecs-import"],["published_at","1725956590"],["proxy","https://github.com/hzrd149/blossom/blob/b5bd2801d1763aa635fc8fea7a76597e0eb18990/buds/06.md","web"],["x","41e6570b616f1546754b79880dd2342364a944bd9110cfb69654884a60cb0853"]],"content":"# BUD-06\n\n## Upload requirements\n\n`draft` `optional`\n\nServers MAY implement `HEAD /upload` as an optimization step before `PUT /upload`.\nClients can use it to avoid uploading blobs that would be rejected, and servers can use it to evaluate whether an upload attempt would be accepted based on the supplied metadata and current server policy.\n\nThis pre-flight request is only an optimization. Clients MAY skip it entirely, and the result is not a guarantee of the eventual `PUT /upload` outcome because server state may change between requests.\n\nClients that want to check whether a blob already exists on the server SHOULD use [`HEAD /<sha256>` from BUD-01](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crz6eas0q#head-sha256---has-blob).\n\nThe `HEAD /upload` endpoint MUST use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the sha256 hash, MIME type and size of the blob that will be uploaded, returning an HTTP status code and an optional custom header `X-Reason` to indicate a human readable message about the upload requirements. Because `HEAD` responses do not include a message body, clients MUST determine the result from the status code and response headers alone.\n\n### Headers\n\n- `X-SHA-256`: A lowercase hex-encoded sha256 string that represents the blob's hash.\n- `X-Content-Length`: An integer that represents the blob size in bytes.\n- `X-Content-Type`: A string that specifies the blob's MIME type, like `application/pdf` or `image/png`.\n\n### Status codes\n\nServers SHOULD use the following status codes for `HEAD /upload` responses:\n\n| Status Code                  | Meaning                                                                                                      |\n| ---------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| `200 OK`                     | Based on the supplied headers and current server policy, the upload would be accepted and the client MAY proceed with `PUT /upload`. |\n| `400 Bad Request`            | The request headers are malformed.                                                                           |\n| `401 Unauthorized`           | Authorization is required and missing or invalid. See [BUD-11](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95cnzuvmwmm#endpoint-authorization-requirements). |\n| `402 Payment Required`       | Payment is required before the upload can proceed. See [BUD-07](nostr:naddr1qvzqqqrcvypzqyek59lpv8gw3tetdrhfttf2g70u8zl0j6sh6cf8agp2grfgmkt7qqrxyaty95crwt8m678).                                    |\n| `403 Forbidden`              | The request is understood but not allowed by server policy.                                                  |\n| `411 Length Required`        | A required `X-Content-Length` header is missing.                                                             |\n| `413 Content Too Large`      | The blob would exceed server size limits.                                                                    |\n| `415 Unsupported Media Type` | The blob type is not supported.                                                                              |\n| `429 Too Many Requests`      | The client has exceeded a rate limit or quota.                                                               |\n| `503 Service Unavailable`    | The upload service is temporarily unavailable.                                                               |\n\nIf included, `X-Reason` MUST be treated as a human readable diagnostic message only and clients MUST NOT parse it for control flow.\n\nClients that do not implement this optimization may still perform `PUT /upload` directly, and servers MUST handle that correctly.\n\nAfter receiving `200 OK` from `HEAD /upload`, clients MUST still be prepared for `PUT /upload` to return either `200 OK` or `201 Created`, depending on whether the blob already existed when the upload was processed.\n\n### Examples\n\nExample request from the client:\n\n```http\nX-Content-Type: application/pdf\nX-Content-Length: 184292\nX-SHA-256: 88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576\n```\n\nExample response from the server if the upload may proceed:\n\n```http\nHTTP/1.1 200 OK\n```\n\nIf the upload cannot proceed, the server SHOULD return one of the status codes defined above. The server MAY include `X-Reason` with a human readable error message.\n\nSome examples of error messages:\n\n```http\nHTTP/1.1 400 Bad Request\nX-Reason: Invalid X-SHA-256 header format. Expected a string.\n```\n\n```http\nHTTP/1.1 413 Content Too Large\nX-Reason: File too large. Max allowed size is 100MB.\n```\n","sig":"3133e6752f17afa7dcd9c79be93ed53d9f603efb0f60ede0c65dc790851eb0c7bab8699cc27d982c930818174862b4c5da7dd1d5ff24f508367a559152142bb5"}