> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pecta.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# RTB gates: OpenRTB quality checks for bidders

> Six in-process gates that validate OpenRTB bid responses against their originating requests — designed for DSPs, SSPs, and ad exchanges.

RTB gates are a specialized set of quality checks built for programmatic advertising pipelines. Unlike general gates that evaluate a single output, every RTB gate receives both the original OpenRTB **request** (`ctx.input`) and the bidder's **response** (`ctx.output`). This lets gates cross-reference fields like impression IDs, floor prices, and blocked categories across the bid exchange boundary.

These gates are aimed at DSPs building bidding agents, SSPs validating responses before auction, and ad exchanges enforcing protocol compliance at scale. All six gates run in-process inside your Node.js application — no network hop, no added latency beyond the gate logic itself.

## Available RTB gates

| Gate             | Import                       | What it checks                                                         |
| ---------------- | ---------------------------- | ---------------------------------------------------------------------- |
| `tmaxGuard`      | `gates.rtb.tmaxGuard()`      | Skips downstream gates when the OpenRTB `tmax` deadline is exhausted   |
| `impidMatch`     | `gates.rtb.impidMatch()`     | Every `bid.impid` in the response matches a `imp.id` in the request    |
| `adomainVerify`  | `gates.rtb.adomainVerify()`  | Bids do not contain placeholder or malformed advertiser domains        |
| `bidSanity`      | `gates.rtb.bidSanity()`      | Bid prices are not unrealistically far above the impression floor      |
| `audienceSafety` | `gates.rtb.audienceSafety()` | Child-directed inventory does not serve unsafe creative categories     |
| `bcatCompliance` | `gates.rtb.bcatCompliance()` | Creative categories do not appear in the request's `bcat` blocked list |

## Full RTB engine setup

Pass the full OpenRTB request as `input` and the bid response as `output`. Set `tmaxMs` and `startedAt` on the context so `tmaxGuard` can calculate remaining deadline budget.

```typescript theme={null}
import { createEngine, gates } from "@pecta/core";

const engine = createEngine({
  gates: [
    gates.rtb.tmaxGuard({ bufferMs: 15 }),
    gates.rtb.impidMatch(),
    gates.rtb.adomainVerify(),
    gates.rtb.bidSanity({ maxFloorMultiple: 50 }),
    gates.rtb.audienceSafety(),
    gates.rtb.bcatCompliance(),
  ],
  timeout: 15,
});

const result = await engine.evaluate({
  agent_id: "dsp-bidder-prod",
  input: openRtbRequest,
  output: openRtbResponse,
  tmaxMs: openRtbRequest.tmax,
  startedAt: requestStartMs,
});

if (!result.passed) {
  console.error("blocked:", result.gates.filter((g) => !g.passed));
}
```

## Request and response context

RTB gates differ from general gates in one key way: they need **both** sides of the bid exchange.

* `ctx.input` — the raw OpenRTB 2.5/2.6 bid request object
* `ctx.output` — the raw OpenRTB bid response object
* `ctx.tmaxMs` — the `tmax` value from the request (milliseconds)
* `ctx.startedAt` — wall-clock timestamp (ms) when the request arrived

Gates that only need one side (such as `bcatCompliance`, which reads `bcat` from the request) will skip gracefully when the relevant field is absent rather than failing hard.

## Gate ordering

<Note>
  Always place `tmaxGuard` first in your gate list. When the `tmax` deadline budget is exhausted, `tmaxGuard` returns `skipped: true` and the engine's `failFast` behavior short-circuits all remaining gates. This prevents wasted evaluation time on a bid that is already too late to use.
</Note>

A `skipped` result is treated as a pass — it does not count against the agent's reputation score and does not block the bid. The remaining gates in the list are not run once a skip is triggered via the engine's fail-fast path.
