ALLOW) or
returns a configured response (BLOCK / REVIEW) without contacting the destination.
The evaluation is identical to the API pattern — the same rulesets,
backends, and outcomes. Only the transport differs: you point the destination URL at Specter instead of
calling the Decision API yourself, so no decision logic is needed in your backend.
Runtime flow
1
Map
Specter applies the interceptor’s
field_mapping to the inbound body to build a
Decision API request.2
Decide
The decision request is evaluated against the active ruleset for its
context.
3
Forward or respond
ALLOW → forward the original body unchanged to the destination and stream
the response back. BLOCK / REVIEW → return the configured response
without calling the destination.integration: "interceptor" and the interceptor reference.
Progressive rollout
The interceptor is built to be adopted in stages, so you can de-risk each step before it touches live traffic. Each stage adds one capability on top of the last.1
Passthrough
Activate the interceptor with no field mapping. Specter
forwards every request unchanged and auto-discovers the fields it sees,
giving you the data to build the mapping. No decision is made, and no
x-specter-decision-id header is added.2
Mapping
Add the field mapping. Specter now builds and validates a decision request
from each inbound body, so you can confirm the request is understood. With
no blocking rules yet, traffic still flows through untouched.
3
Shadow decisions
Add rules and backends in shadow mode (
live: false). Specter evaluates
and logs the decision and returns its ID in the x-specter-decision-id
header, but shadow rules never change the outcome — so every request is
still forwarded. You measure decision quality against real traffic with zero
customer impact.4
Active
Switch the rules and backends to live. Specter now enforces the decision: it
forwards on
ALLOW and returns the configured response on BLOCK /
REVIEW.Transparent interceptor (shadow)
Specter observes but never blocks: every request reaches the destination, and the decision rides along in the response header.- The merchant sends the request to the destination through the Specter interceptor.
- Specter engages backends in shadow mode.
- Specter forwards the request to the destination.
- The destination returns the result.
- Specter returns the destination’s exact result, with the decision information in the response header.
Active interceptor
Once you trust the decisions, switch to live. Specter forwards only approved requests; everything else is short-circuited with your configured response.- The merchant sends the request to the destination through the Specter interceptor.
- Specter engages backends.
- Specter forwards the request to the destination only if the decision outcome is
ALLOW. - The destination returns the result.
- Specter returns the destination’s exact result, with the decision information in the response header.
Configuration
Interceptors are configured through the Admin API (scopesadmin:interceptors:read / admin:interceptors:write)
and have their own DRAFT → ACTIVE lifecycle with activate and rollback.
Field mapping
Each entry builds part of the Decision API request — thetarget names a field of the built-in transaction schema
(transaction.amount, credential.type, …). Entries are evaluated in order and merged.
Interceptors map onto the built-in
transaction schema only; the context an interceptor names must
resolve to a transaction-bound ruleset. This is enforced at both ends: creating or updating an
interceptor rejects with 422 when a target is not declared by the transaction schema (dynamic
metadata.<key> targets are accepted, although the editor’s target list does not enumerate them) or
when the named context currently resolves to a custom-bound ruleset — such an interceptor could never
execute. A context with no active ruleset yet is accepted, since the binding is not knowable at that
point; if it later resolves custom-bound, executing the interceptor refuses with 502 INTERCEPTOR_BINDING_UNSUPPORTED naming the context and the bound schema. Passthrough interceptors
(empty mapping) never touch the binding and are not refused.
Source paths support
$ (root) and $.a.b.c dot notation. Missing paths produce no output — partial mappings are valid.
Add "sensitive": true to a row whose value must not appear in the payload copy stored on the decision;
the copy is otherwise redacted by the classification markers of the schema, never by guessing from a source
field’s name.
Filters
Filters chain with| (e.g. "downcase | first(6)"). These are mapping filters, distinct from the
filter() pipes of rule conditions:
Responses
Each outcome key (block, review) maps to a response config:
decisionmode — returns the standard Specter decision map as-is.templatemode — returns a static body with placeholders resolved at runtime.
When no response is configured for an outcome, Specter defaults to
decision mode.
Header forwarding (ALLOW)
OnALLOW, Specter forwards the request to the destination and:
- Strips reserved headers:
authorization,content-length,content-type,host. - Resolves
x-{label}-name/x-{label}-valueheader pairs into a single{name}: {value}header — used to inject destination credentials without exposing them in the body. - Appends
content-type: application/jsonandx-specter-decision-id: <uuid>.
Related
API
The direct-call alternative when you control the payment backend.