Summary
Neither docs/nips/NIP-CW.md nor docs/bridge-channel-window.md shows a complete POST /query request body. Both present the window request as a bare filter object, which is what a reader implementing from the docs will send, and the relay rejects it with a 400. The body must be a JSON array of filters.
Reproduce
Send the request body exactly as the docs show it, with a valid NIP-98 header from a relay member:
POST /query
Content-Type: application/json
Authorization: Nostr <base64 kind:27235>
{"kinds":[9],"limit":1}
Response:
400 Bad Request
{"error":"invalid filters: invalid type: map, expected a sequence at line 1 column 0"}
A {"filters": [...]} wrapper is rejected identically. The array form works:
[{"kinds":[9],"limit":1}]
200 OK
[ ...signed events... ]
Why the docs read this way
docs/nips/NIP-CW.md §Request:
A window request is a standard filter plus extension fields, submitted wherever the relay accepts filters (for Buzz: the NIP-98-authenticated HTTP bridge POST /query):
followed by a fenced block containing a single object.
docs/bridge-channel-window.md §Request:
A standard bridge filter plus extension fields:
followed by the same single-object shape.
Both sentences are strictly true, because they describe the filter, not the request body. But neither document states that POST /query accepts an array, and no example anywhere in either file shows a complete body. /query is referenced three times across the two files and never once with a body a reader could copy.
The implementation is unambiguous
crates/buzz-relay/src/api/bridge.rs:
// Two-pass parse: preserve raw JSON for custom extension fields (before_id,
// depth_limit, feed_types) that nostr::Filter silently drops.
let raw_filters: Vec<Value> = serde_json::from_slice(body)
.map_err(|e| api_error(StatusCode::BAD_REQUEST, &format!("invalid filters: {e}")))?;
The array is correct and consistent with NIP-01, where REQ carries one or more filters. The gap is only that the docs never say so.
Suggested fix
One line in each §Request, plus one complete example. For example in docs/nips/NIP-CW.md:
The request body is a JSON array of filters, as on any NIP-01 filter surface. A window request is one such filter:
Minor, same area
The error text invalid filters: invalid type: map, expected a sequence at line 1 column 0 describes the serde failure rather than the contract. Something like expected a JSON array of filters would point a reader at the fix directly. Not important if the docs carry a full example.
Context
Found while implementing a browser client against the channel-window surface. The endpoint itself behaves exactly as specified once the body shape is right; top_level, the composite until + before_id cursor, and the 39006 bounds overlay are not in question here. This is a documentation issue only.
Summary
Neither
docs/nips/NIP-CW.mdnordocs/bridge-channel-window.mdshows a completePOST /queryrequest body. Both present the window request as a bare filter object, which is what a reader implementing from the docs will send, and the relay rejects it with a400. The body must be a JSON array of filters.Reproduce
Send the request body exactly as the docs show it, with a valid NIP-98 header from a relay member:
Response:
A
{"filters": [...]}wrapper is rejected identically. The array form works:Why the docs read this way
docs/nips/NIP-CW.md§Request:followed by a fenced block containing a single object.
docs/bridge-channel-window.md§Request:followed by the same single-object shape.
Both sentences are strictly true, because they describe the filter, not the request body. But neither document states that
POST /queryaccepts an array, and no example anywhere in either file shows a complete body./queryis referenced three times across the two files and never once with a body a reader could copy.The implementation is unambiguous
crates/buzz-relay/src/api/bridge.rs:The array is correct and consistent with NIP-01, where
REQcarries one or more filters. The gap is only that the docs never say so.Suggested fix
One line in each §Request, plus one complete example. For example in
docs/nips/NIP-CW.md:Minor, same area
The error text
invalid filters: invalid type: map, expected a sequence at line 1 column 0describes the serde failure rather than the contract. Something likeexpected a JSON array of filterswould point a reader at the fix directly. Not important if the docs carry a full example.Context
Found while implementing a browser client against the channel-window surface. The endpoint itself behaves exactly as specified once the body shape is right;
top_level, the compositeuntil+before_idcursor, and the39006bounds overlay are not in question here. This is a documentation issue only.