Skip to main content
An interceptor is a transparent proxy. Specter sits inline between your client and the acquirer: it receives the acquirer request body, maps it into a standard Decision API request, evaluates that request, and either forwards the original request unchanged (ALLOW) or returns a configured response (BLOCK / REVIEW) without contacting the acquirer. The evaluation is identical to the API pattern — the same rulesets, backends, and outcomes. Only the transport differs: you point your acquirer URL at Specter instead of calling the Decision API yourself, so no fraud logic is needed in your backend.

Runtime flow

POST /api/interceptors/{ref}
Authorization: Bearer <token with interceptors:execute>
Content-Type: application/json

<acquirer request body>
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.
The decision is logged with 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 acquirer, and the decision rides along in the response header.
  1. The merchant sends the request to the acquirer through the Specter interceptor.
  2. Specter engages backends in shadow mode.
  3. Specter forwards the request to the acquirer.
  4. The acquirer returns the result.
  5. Specter returns the acquirer’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.
  1. The merchant sends the request to the acquirer through the Specter interceptor.
  2. Specter engages backends.
  3. Specter forwards the request to the acquirer only if the decision outcome is ALLOW.
  4. The acquirer returns the result.
  5. Specter returns the acquirer’s exact result, with the decision information in the response header.

Configuration

Interceptors are configured through the Admin API (scopes admin:interceptors:read / admin:interceptors:write) and have their own DRAFT → ACTIVE lifecycle with activate and rollback.
{
  "description": "Adyen checkout interceptor",
  "active": true,
  "destination": {
    "url": "https://checkout-test.adyen.com/v70/payments",
    "timeout_ms": 5000
  },
  "field_mapping": [
    { "source": "$.amount.value", "target": "transaction.amount" },
    { "source": "$.amount.currency", "target": "transaction.currency" },
    { "source": "$.reference", "target": "transaction.reference" },
    { "source": "$.shopperIP", "target": "device.ip" },
    {
      "source": "$.paymentMethod.encryptedCardNumber",
      "filter": "first(6)",
      "target": "credential.first_six"
    },
    {
      "source": "$.paymentMethod.encryptedCardNumber",
      "filter": "last(4)",
      "target": "credential.last_four"
    },
    { "const": "masked_pan", "target": "credential.type" }
  ],
  "responses": {
    "block": {
      "mode": "template",
      "status_code": 422,
      "content_type": "application/json",
      "body": {
        "message": "Request blocked by fraud rules",
        "reference": "{{ decision_id }}"
      }
    },
    "review": {
      "mode": "decision"
    }
  }
}

Field mapping

Each entry builds part of the Decision API request — the target names a field of that request (transaction.amount, credential.type, …). Entries are evaluated in order and merged.
EntryExampleEffect
Source{ "source": "$.amount.value", "target": "transaction.amount" }Copy a value from the inbound body.
Const{ "const": "masked_pan", "target": "credential.type" }Assign a static value.
Source + filter{ "source": "$.pan", "filter": "first(6)", "target": "credential.first_six" }Transform before assigning.
Source paths support $ (root) and $.a.b.c dot notation. Missing paths produce no output — partial mappings are valid.

Filters

Filters chain with | (e.g. "downcase | first(6)"):
FilterDescription
first(n)First n characters.
last(n)Last n characters.
tail(n)All characters after position n.
map({...})Map a value via a lookup table.
to_intParse a numeric string to an integer.
downcaseLowercase the string.

Responses

Each outcome key (block, review) maps to a response config:
  • decision mode — returns the standard Specter decision map as-is.
  • template mode — returns a static body with placeholders resolved at runtime.
PlaceholderResolves to
{{ decision_id }}UUID of the logged decision
{{ decision }}BLOCK or REVIEW
{{ source }}Rule source (backend name or condition)
{{ credential_fingerprint }}Credential fingerprint
{{ latency_ms }}Evaluation latency in milliseconds
{{ triggered_rules }}JSON array of triggered rule IDs
When no response is configured for an outcome, Specter defaults to decision mode.

Header forwarding (ALLOW)

On ALLOW, Specter forwards the request to the destination and:
  • Strips reserved headers: authorization, content-length, content-type, host.
  • Resolves x-{label}-name / x-{label}-value header pairs into a single {name}: {value} header — used to inject acquirer credentials without exposing them in the body.
  • Appends content-type: application/json and x-specter-decision-id: <uuid>.
The acquirer response (headers, body, status) is returned to the caller unchanged.

API

The direct-call alternative when you control the payment backend.