Multipart Body Transport for BRC-105 Payments
John Calhoun ([email protected])
1. Abstract
This document specifies an alternative transport mechanism for the x-bsv-payment data defined in BRC-105. When a payment transaction encoded in BEEF or Atomic BEEF format exceeds practical HTTP header size limits, the client transmits the payment as a named part within a multipart/form-data request body instead of an HTTP header value.
The existing header-based transport defined in BRC-105 is preserved unchanged and remains the default for small payments. This specification adds a negotiated, backward-compatible body transport for large payments.
2. Motivation
BRC-105 specifies that the client sends payment data in the x-bsv-payment HTTP header. This works well for small transactions, but HTTP headers are subject to practical size limits that vary by infrastructure:
Cloudflare Workers enforce approximately 128 KB total header size
Most reverse proxies and CDNs enforce 8–16 KB per header value
Node.js defaults to 16 KB maximum header size (configurable)
BEEF transactions grow with unconfirmed ancestor chain depth. Since BEEF must include the full raw transaction for every unconfirmed ancestor back to the last confirmed input (only confirmed ancestors can be represented compactly as BUMPs), the BEEF size is cumulative: the BEEF for transaction N in a chain includes the full transaction data of transactions 1 through N-1. Each chained payment adds its raw transaction (~200–700 bytes) to the cumulative BEEF of its ancestors.
Applications that perform rapid sequential payments — such as autonomous agents making dozens of paid API calls per task, or wallets consolidating fragmented UTXOs — routinely chain transactions faster than blocks confirm. Since block confirmations average 10 minutes by consensus, any application making multiple payments per minute will accumulate unconfirmed chains.
Empirical measurements from a production wallet database (7,416 transactions) demonstrate the growth:
Baseline avg
—
4.9 KB
~60 links
~1 min
15.6 KB
~120 links
~2 min
42 KB
~180 links
~3 min
75 KB
~300 links
~5 min
155.7 KB
Each row represents the BEEF payload for a single transaction — one micropayment. The 155.7 KB entry exceeds the Cloudflare Workers 128 KB header limit. These measurements were taken with BEEF compaction active (upgrading confirmed ancestors to BUMPs every 15 minutes); without compaction or during sustained activity between block confirmations, sizes grow further. Historical observations in the same database include individual BEEFs exceeding 400 KB.
These payloads cannot be transmitted as HTTP header values.
multipart/form-data (RFC 7578) is the natural choice for body transport: it is a well-established standard with universal library support, separates the payment data from the original request payload without ambiguity, and request body size limits on modern platforms are orders of magnitude larger than header limits.
3. Relationship to BRC-105
BRC-105 defines the complete HTTP micropayment protocol: the 402 Payment Required response, derivation prefix/suffix exchange, payment JSON structure, and server verification flow. This specification does not modify any of those semantics.
BRC-118 adds a single concern: an alternative transport for the x-bsv-payment JSON when it exceeds header size limits. The payment JSON structure, derivation logic, nonce replay protection, transaction verification, and internalizeAction() processing defined in BRC-105 are all unchanged. The only difference is where the payment bytes reside in the HTTP request.
4. Specification
4.1 Transport Negotiation
The server advertises supported transport mechanisms in the 402 Payment Required response via a new optional header:
The value is a comma-separated list of transport names.
Defined transport names are
header(BRC-105 default) andmultipart(this specification).If the header is absent, the client MUST assume only
headertransport is supported.Servers implementing this specification SHOULD include this header in all
402responses.
4.2 Client Transport Selection
The client selects the transport mechanism based on the size of the serialized x-bsv-payment JSON and the server's advertised transports:
If the payment JSON fits within HTTP header size limits and the server supports
headertransport, the client SHOULD use header transport as defined in BRC-105.If the payment JSON exceeds header size limits and the server advertises
multiparttransport, the client MUST use multipart body transport as defined in Section 4.3.If the payment JSON exceeds header size limits and the server does not advertise
multiparttransport, the client SHOULD attempt header transport and handle any resulting errors.
A recommended threshold for switching to multipart transport is 8 KB (8,192 bytes), which provides a safe margin under the most restrictive common header limits.
4.3 Multipart Body Transport Format
When using multipart body transport, the client sends the payment and original request payload as a multipart/form-data request body containing two parts:
x-bsv-payment
application/json
Yes
The payment JSON object (identical format to the header value)
body
Varies
No
The original request payload with its native Content-Type
The x-bsv-payment part carries the same JSON structure as the header transport:
The body part carries the original request payload. Its Content-Type matches what the client would have sent as the request Content-Type without multipart wrapping. If the original request has no body (e.g., a GET-equivalent POST), the body part MAY be omitted.
All other BRC-105 and BRC-103/BRC-104 headers remain as HTTP headers and are not affected by this transport.
4.4 Request Examples
4.4.1 JSON API Request with Multipart Payment
4.4.2 Binary Payload with Multipart Payment
4.5 Server Transport Detection
The server determines which transport is in use by examining the request Content-Type header:
If
Content-Typestarts withmultipart/form-data— extract the payment JSON from thex-bsv-paymentpart and the request payload from thebodypart.Otherwise — read the payment JSON from the
x-bsv-paymentHTTP header and treat the request body as the payload directly.
Both paths feed into the identical payment verification pipeline defined in BRC-105 Section 6.4. The transport mechanism has no effect on payment semantics or verification logic.
When using multipart transport, the server MUST reconstruct the request for downstream handling such that the handler receives only the body part content with its associated Content-Type. The handler MUST NOT be exposed to the multipart wrapper or the payment part.
4.6 Boundary Format
The multipart boundary string SHOULD include sufficient randomness to avoid collisions with request payload content. A recommended format is:
For example: ----BsvPayment7a3f9e1b0c4d2e8f
5. Backward Compatibility
This specification is fully backward compatible with BRC-105:
Existing clients that send
x-bsv-paymentas a header continue to work without modification. Header transport is not deprecated.Existing servers that do not implement multipart extraction continue to work with header-transport clients. The
x-bsv-payment-transportsheader is optional; its absence signals header-only support.Payment semantics are unchanged. The JSON structure, derivation logic, amount verification, and internalization flow are identical regardless of transport.
No migration timeline. Header transport can be used indefinitely for transactions that fit within header limits.
6. Security Considerations
Authentication Compatibility
BRC-103/BRC-104 mutual authentication signs the raw HTTP request as transmitted. When using multipart transport, the client signs the request with the
multipart/form-dataContent-Type and the full multipart body. The server verifies the signature against the same raw request. The authentication guarantee is preserved because the signed content matches the transmitted content exactly.Authentication verification MUST occur before multipart extraction. The server verifies the BRC-103 signature on the complete request (including the multipart body), then extracts the payment and payload parts for processing.
No New Attack Surface
The multipart transport does not introduce new trust assumptions. The same mutually authenticated channel carries the same payment data in a different encoding. Multipart boundary parsing uses well-established RFC 7578 implementations.
Replay Protection
The nonce-based replay protection defined in BRC-105 Section 8 applies identically. The
derivationPrefixuniqueness guarantee is independent of transport mechanism.
Header Size and Denial of Service
HTTP header size limits exist as a defense against denial-of-service attacks. Servers must allocate memory to buffer and parse all headers before the request can be authenticated or processed. Requiring servers to raise header limits to accommodate large BEEF payloads weakens this protection and increases exposure to resource exhaustion attacks. Body transport avoids this concern entirely: request bodies support streaming and chunked parsing with well-established memory management, and servers can enforce body size limits independently of header limits.
7. Implementations
Server (Cloudflare Workers):
bsv-auth-cloudflaremiddleware —prepare_multipart_payment()extracts payment from multipart body, deployed across 9 x402 service agents.Client (Rust):
rust-bsv-worm—build_multipart_body()inx402/payment.rs, auto-switches at 8 KB threshold when server advertises multipart support.Client (Python):
codex-x402—build_multipart_body()inlib/payment.py, identical threshold and format.
8. References
BRC-105: HTTP Service Monetization Framework
BRC-103: Peer-to-Peer Mutual Authentication and Certificate Exchange Protocol
BRC-104: HTTP Transport for BRC-103
BRC-62: Background Evaluation Extended Format (BEEF) Transactions
BRC-95: Atomic BEEF Transactions
BRC-74: BSV Unified Merkle Path (BUMP) Format
BRC-29: Simple Authenticated BSV P2PKH Payment Protocol
RFC 7578: Returning Values from Forms: multipart/form-data
Last updated
Was this helpful?

