Header library
Some headers belong to a target, not to a request. Accept: application/vnd.example+json is what that API speaks. X-Api-Version: 2 is which version you are testing against. User-Agent: my-tester/1.0 is how your gateway's access log tells your calls apart from production traffic.
The Metadata tab is per-request, so without somewhere else to put them these headers get retyped into every method, every environment, every workspace — or wrapped in a pre-request script, which is a lot of machinery for three static strings. Environments do not solve it either: they give you variables that a header value can reference, not a place to define the header.
A header set is a name, a scope, and a list of header rows. Sets whose scope matches the request apply automatically; you can flip any of them off — or a non-matching one on — for a single call.
Where it lives
Settings → Workspace → Header library. The library belongs to the workspace, not to your browser profile: a team's API conventions travel with the project, so the library round-trips through .bww export / import alongside collections and environments.
Above any header or metadata editor you get a chip strip: one chip per set, a count of the headers that will actually be sent, and a Manage link back into the editor. The strip is hidden entirely when the library is empty — an empty strip costs vertical space to say nothing.
Scopes
| Scope | Applies when | Example |
|---|---|---|
Everywhere |
always | a X-Trace header you want on every call while debugging |
URL host |
the request URL's host matches | api.example.com |
Service |
the discovered service matches | UserService |
Method |
one specific method matches | UserService.GetUser |
Host matching ignores scheme, port, path and credentials, so api.example.com, https://api.example.com and https://api.example.com:8443/v1/pets all name the same host. Service and method names compare case-insensitively, and a package-qualified service name (acme.users.v1.UserService) parses correctly in a method scope — the last dot is the separator.
A scope Bowire cannot read falls back to Everywhere rather than disappearing. A set nobody can reach is worse than one that shows up in the wrong place: at least you can see it and fix the scope.
Precedence
Lowest first:
- Library sets, in library order. A later set overwrites an earlier one that names the same header. Reorder the sets to change who wins.
- The request's own rows. A header typed into the Metadata tab always wins, so a library can never silently override what you are looking at.
Header names compare case-insensitively — HTTP says they are, and Accept beside accept is a bug every time — but the first spelling seen is the one that ships.
An unticked row contributes nothing and shadows nothing. Turning off a request's Accept row lets the library's Accept through; it does not mean "send no Accept". To suppress a library header for one call, turn its chip off.
The effective-headers preview
Layered headers create a question the moment they start working: why is my request sending that? The N effective button on the chip strip expands the merged result — every header in send order, its value after variable substitution, and where it came from. A header that beat someone else is marked, and the tooltip names who lost.
Chips carry the same information from the other direction: a set that is on but is being overridden further down shows a warning glyph, so it says so rather than quietly not mattering.
Variables
Header values in a library set go through the same {{name}} substitution as anywhere else, resolved against the active environment at send time — so a set can carry Authorization: Bearer {{token}} and follow you across environments. Header names are not substituted.
See Variables and environments for the resolution order.
Toggling for one request
Clicking a chip sets a per-request answer that overrides the scope. Setting it back to what the scope already says removes the override again, so a request that agrees with its scope stores nothing — and a later scope edit still reaches it. A chip switched by hand is drawn with a dashed edge, so a deliberate one-off is distinguishable from the automatic behaviour.
What it does not do
- It does not reach the CLI yet.
bowire callandbowire testdo not read the library, so a request run from the command line sends only its own headers. Follow the tracking issue before relying on the library in CI. - It is not per-team sharing. The library travels with the workspace; sharing it is a workspace-sharing concern.
- Saving a request to a collection stores the request's own rows, not the merged result. The library re-applies when the collection item runs, which is what you want when the set later changes — but it does mean a collection is not a frozen record of every header that went out.
Tracked in #95.