Skip to content

Suppression (suppressed, BCODE3 / ICODE2)

How Sierra exposes OPAC suppression across the REST API and the MARC export. Suppression is not deletion — a suppressed record is live and fully retrievable; it is merely hidden from the public discovery layer. If you are building a patron-facing slice, this is the flag you filter on.

suppressed is a read-only boolean on bibs and items

Behavior: GET bibs?fields=id,suppressed and GET items?fields=id,suppressed both return a boolean suppressed on every record (e.g. {"id": "1000165", "suppressed": true}). It is a computed reflection of an underlying fixed field (below), not an independently writable field — it appears in the API's list of PUT-rejected read-only fields (see Write semantics).

Type: By design.

How to handle: Read it freely to know a record's discovery visibility. To change suppression, edit the underlying fixed field (BCODE3 for bibs, ICODE2 for items), not suppressed.

How we know: Live read-only probes on sierra-test (v6), 2026-06-21: both endpoints returned the boolean; suppressed is also enumerated among the read-only top-level fields rejected on PUT.

suppressed=true is a valid filter param on both endpoints

Behavior: GET bibs?suppressed=true&fields=id,suppressed (and the items equivalent) returns only suppressed records — the symmetric counterpart to deleted=true&deletedDate=... for deletions. Suppressed records are otherwise included by default: a plain deleted=false query, and the MARC export, both return suppressed records inline (suppression does not hide a record from queries the way deletion does).

Type: By design.

How to handle: Use suppressed=true to enumerate the suppressed set directly, or request the suppressed field on a normal sweep and filter client-side. Do not assume a normal harvest excludes suppressed records — it doesn't; you simply can't tell which are suppressed unless you ask for the field (or read the MARC fixed-field below).

How we know: Probes on sierra-test, 2026-06-21: suppressed=true returned all-suppressed pages on both bibs and items; a default deleted=false window contained suppressed:true records inline.

Suppression is carried in the MARC export — bib 998$e (BCODE3), item 945$o (ICODE2)

Behavior: The boolean is computed from a Sierra fixed field — BCODE3 ("Suppress (BCODE3)") for bibs, ICODE2 ("Suppress (ICODE2)") for items. Critically, those fixed fields are present in the MARC export Sierra generates via bibs/marc: BCODE3 lands in 998$e and ICODE2 in 945$o (the 945 item-data field). On the deployment observed, the suppressed value is 's' and the unsuppressed value is '-', correlating 1:1 with the REST suppressed boolean. So a MARC-based harvest already carries suppression — no separate JSON fetch is required to capture it.

Type: By design.

How to handle: If you harvest MARC, extract 998$e (bib) and 945$o (item) to capture suppression for free, in the same pass — and to backfill it from already-stored MARC with zero new API calls. Store the raw code, not a hard-coded boolean — and do not assume 's' is the only suppressed code. The reliable rule is the inverse: '-' is the OPAC-display (not-suppressed) value, and any other code is suppressed (suppressed = code != '-'). On one production deployment, BOTH 's' and 'd' occur and both map to REST suppressed=true (the 's'-only assumption from a test-environment sample missed the 'd', which only appeared in production data). So keep the raw code in the lake and apply coalesce(code,'-') <> '-' (or NOT IN (<your library's display code>)) downstream; that survives codes you haven't enumerated yet. Confirm your deployment's display code by correlating the fixed-field value against the REST suppressed boolean across a varied sample, including a full-corpus pass — rare codes hide in the long tail.

How we know: sierra-test v6, 2026-06-21, via the two-phase bibs/marc export used by a production harvest. A known-suppressed bib (.b1000165, BCODE3=s, REST suppressed=true) had 998$e='s'; four unsuppressed bibs in the same page had 998$e='-'. A known-suppressed item (ICODE2=s, REST suppressed=true) had 945$o='s'; an unsuppressed item on the same bib had 945$o='-'. The per-record GET bibs/{id}/marc endpoint returned 400 on this version — MARC is available only through the two-phase batch export. Full-corpus confirmation: a complete MARC re-parse of ~2.08M prod bibs + ~4.65M items found 998$e ∈ {-: 2,080,029; s: 12,079; d: 1} and 945$o ∈ {-; s: 464,229} — the single d bib (3947502) returned REST suppressed=true, confirming the != '-' rule and that a test-only sample under-counts the code set.

Does toggling suppression bump updatedDate?

Behavior: Because suppressed reflects a fixed field, an interactive suppress toggle is a record edit and bumps updatedDate — so a normal change poll re-fetches the record and a MARC harvest re-captures 998$e/945$o. The standing caveat is batch fixed-field updates (Sierra Global Update), a known class that may alter the fixed field without bumping updatedDate; not specifically confirmed for suppression.

Type: By design (with a batch-op residual).

How to handle: Rely on the change poll for interactive toggles. Cover the batch-op residual with a periodic id/field reconciliation — a cheap fields=id,suppressed re-sweep compared against your stored value — the same reconcile the Change polling page prescribes for deletions. A one-time baseline (re-derive from stored MARC, or one fields=id,suppressed sweep) seeds the column.

How we know: Design-resolved from the fixed-field semantics above plus the API's read-only treatment of suppressed; the batch-op exception is the documented Global-Update behavior, flagged here as an unverified residual to reconcile against rather than a confirmed bump.