Configuring routing rules
Routing rules determine how RTB Fabric maps incoming HTTP requests to links. Each rule specifies conditions that a request must satisfy. When a request arrives at the gateway, RTB Fabric evaluates rules across all links and forwards the request to the link whose highest-priority matching rule wins.
Routing rule structure
You create routing rules using the CreateLinkRoutingRule API. Each rule consists of a numeric priority and a set of conditions. The ruleId is system-generated.
{ "gatewayId": "rtb-gw-abc123def456", "linkId": "link-001", "priority": 1, "conditions": { "hostHeader": "bid.example.com", "pathPrefix": "/openrtb" }, "clientToken": "unique-idempotency-token" }
| Field | Type | Required | Description |
|---|---|---|---|
| gatewayId | String | Yes | The responder gateway that owns the link. |
| linkId | String | Yes | The link to attach the rule to. |
| priority | Integer (1-1000) | Yes | Evaluation priority. Lower values indicate higher precedence. Must be unique within a link. |
| conditions | Object | Yes | One or more match conditions. At least one condition must be specified. |
| clientToken | String | Yes | Idempotency token. |
The response includes a system-generated ruleId (pattern: rule-[a-z0-9-]+) and a status field. Use the GetLinkRoutingRule API to check when the rule reaches ACTIVE status.
Supported match types
RTB Fabric supports six match types. All conditions within a single rule use AND logic — every specified condition must match for the rule to apply.
Host header exact match (hostHeader)
Matches the Host header of the incoming request against an exact hostname value.
Comparison: Case-insensitive, per RFC 7230 Section 5.4.
Port stripping: The port component is stripped before comparison. A request to
bid.example.com:443matches a rule withhostHeaderset tobid.example.com.IPv6 handling: Bracket-enclosed IPv6 addresses are handled correctly. A request with
Host: [::1]:8080is matched against[::1]after port stripping.
Example:
{ "conditions": { "hostHeader": "east-bid.dsp.example.com" } }
This condition matches requests with Host: east-bid.dsp.example.com, Host: East-Bid.DSP.Example.com, and Host: east-bid.dsp.example.com:443.
Host header wildcard match (hostHeaderWildcard)
Matches the Host header against a wildcard pattern. The hostHeader and hostHeaderWildcard conditions are mutually exclusive — a single rule cannot contain both.
Syntax: The wildcard character
*replaces exactly one DNS label (single-level matching), per RFC 6125 Section 6.4.3.Comparison: Case-insensitive, port-stripped.
Restrictions: The pattern
*.example.commatchesapi.example.combut does not matcha.b.example.com(multi-level) orexample.com(the parent domain itself).
Example:
{ "conditions": { "hostHeaderWildcard": "*.dsp.example.com" } }
| Incoming Host | Matches? |
|---|---|
| east-bid.dsp.example.com | Yes |
| west-bid.dsp.example.com | Yes |
| a.b.dsp.example.com | No (multi-level) |
| dsp.example.com | No (parent domain) |
Path prefix match (pathPrefix)
Matches the URL path against a prefix value with segment-boundary awareness.
Segment-boundary matching: The prefix
/apimatches/api,/api/, and/api/users, but does not match/api2or/apiary. The match verifies that the character immediately following the prefix is either/, end-of-path, or the prefix itself ends with/.Trailing slash normalization:
/apiand/api/are equivalent as prefix values.
Example:
{ "conditions": { "pathPrefix": "/openrtb/bid" } }
| Incoming path | Matches? |
|---|---|
| /openrtb/bid | Yes |
| /openrtb/bid/ | Yes |
| /openrtb/bid/v2 | Yes |
| /openrtb/bidstream | No (not a segment boundary) |
| /openrtb | No (prefix is longer than the path) |
Path exact match (pathExact)
Matches the URL path using a byte-for-byte comparison. The pathPrefix and pathExact conditions are mutually exclusive — a single rule cannot contain both.
Case sensitivity: The comparison is case-sensitive.
/OpenRTB/Biddoes not match/openrtb/bid.No percent-decoding: Percent-encoded characters are compared as-is.
/path%2Ftodoes not match/path/to.Trailing slash significance:
/openrtb/bidand/openrtb/bid/are different paths.
Example:
{ "conditions": { "pathExact": "/openrtb/bid/v2" } }
Query string equals match (queryStringEquals)
Matches a specific query string key-value pair.
URL decoding: Both the key and value are URL-decoded before comparison. A query parameter
format=jsonmatches regardless of whether the URL containsformat=jsonorformat%3Djsonin the encoded form.Case sensitivity: After URL decoding, comparison is case-sensitive.
Example:
{ "conditions": { "queryStringEquals": { "key": "format", "value": "json" } } }
A request to /bid?format=json matches. A request to /bid?format=XML does not match (case-sensitive value comparison).
Important
Each rule supports at most one queryStringEquals condition. The queryStringEquals and queryStringExists conditions are mutually exclusive — a single rule cannot contain both. To match on multiple query parameters, create separate rules with appropriate priorities.
Query string exists match (queryStringExists)
Checks whether a specific query string key is present, regardless of its value.
URL decoding: The key is URL-decoded before the presence check.
Case sensitivity: After URL decoding, the key comparison is case-sensitive.
Example:
{ "conditions": { "queryStringExists": "debug" } }
A request to /bid?debug=true matches. A request to /bid?debug (key present with no value) also matches. A request to /bid?Debug=true does not match (case-sensitive key).
Important
Each rule supports at most one queryStringExists condition. The queryStringExists and queryStringEquals conditions are mutually exclusive — a single rule cannot contain both.
Composite rules
All conditions within a single rule are combined with AND logic. A request must satisfy every specified condition for the rule to match.
The following rule matches requests that meet all three criteria simultaneously:
{ "gatewayId": "rtb-gw-abc123def456", "linkId": "link-001", "priority": 10, "conditions": { "hostHeader": "bid.example.com", "pathPrefix": "/openrtb/bid", "queryStringEquals": { "key": "format", "value": "json" } }, "clientToken": "unique-idempotency-token" }
A request to https://bid.example.com/openrtb/bid/v2?format=json matches this rule. A request to https://bid.example.com/openrtb/bid/v2?format=xml does not match because the queryStringEquals condition fails.
Note
There is no OR logic within a single rule. To express OR conditions, create multiple rules with different priorities.
Rule evaluation order
RTB Fabric evaluates routing rules globally across all links, not per-link. The evaluation follows this process:
Flatten — Collect all routing rules from all links on the gateway.
Sort — Sort rules by
priorityin ascending order (lower values first).Evaluate — Iterate through sorted rules. The first rule whose conditions all match the incoming request wins.
Resolve — Forward the request to the link that owns the winning rule.
Priority must be unique within each link. Across different links, rules may share the same priority value. If two rules from different links have the same priority and both match, the result is non-deterministic. Assign distinct priority values across all links to avoid ambiguous routing.
Example: Interleaved priorities across links
Consider two links with the following rules:
Link A (link-east) has two rules with priorities 1 and 3:
| Rule | Priority | Conditions |
|---|---|---|
| rule-east-openrtb | 1 | hostHeader: east-bid.example.com, pathPrefix: /openrtb |
| rule-east-native | 3 | hostHeader: east-bid.example.com, pathPrefix: /native |
Link B (link-west) has two rules with priorities 2 and 4:
| Rule | Priority | Conditions |
|---|---|---|
| rule-west-openrtb | 2 | hostHeader: west-bid.example.com, pathPrefix: /openrtb |
| rule-west-native | 4 | hostHeader: west-bid.example.com, pathPrefix: /native |
The global evaluation order is: rule-east-openrtb (1) → rule-west-openrtb (2) → rule-east-native (3) → rule-west-native (4).
A request to https://west-bid.example.com/openrtb/bid skips rule-east-openrtb (host mismatch), matches rule-west-openrtb (priority 2), and routes to link-west.
Link ID resolution chain
When a request arrives at the gateway, RTB Fabric resolves the target link using a three-step resolution chain. Rule-based routing is the final step in this chain:
URL extraction — Check if the request URL contains an explicit link ID.
Host header extraction — Check if the Host header maps directly to a link.
Rule-based routing — Evaluate routing rules to determine the target link.
RTB Fabric uses the first method that returns a result. Rule-based routing applies only when the first two methods do not resolve a link ID.
Example: Multi-partner routing
The following example demonstrates routing for a partner (AnyCompany) with multiple regional endpoints and path-based traffic segmentation.
AnyCompany operates four combinations of region and traffic type:
| Endpoint | Path | Traffic type | Link ID |
|---|---|---|---|
| east-bid.dsp.example.com | /openrtb/bid | OpenRTB (East) | link-anyco-east-openrtb |
| east-bid.dsp.example.com | /native/bid | Native (East) | link-anyco-east-native |
| west-bid.dsp.example.com | /openrtb/bid | OpenRTB (West) | link-anyco-west-openrtb |
| west-bid.dsp.example.com | /native/bid | Native (West) | link-anyco-west-native |
Rule on link 1 (link-anyco-east-openrtb):
{ "gatewayId": "rtb-gw-abc123def456", "linkId": "link-anyco-east-openrtb", "priority": 1, "conditions": { "hostHeader": "east-bid.dsp.example.com", "pathPrefix": "/openrtb" }, "clientToken": "token-east-openrtb" }
Rule on link 2 (link-anyco-east-native):
{ "gatewayId": "rtb-gw-abc123def456", "linkId": "link-anyco-east-native", "priority": 2, "conditions": { "hostHeader": "east-bid.dsp.example.com", "pathPrefix": "/native" }, "clientToken": "token-east-native" }
Rule on link 3 (link-anyco-west-openrtb):
{ "gatewayId": "rtb-gw-abc123def456", "linkId": "link-anyco-west-openrtb", "priority": 3, "conditions": { "hostHeader": "west-bid.dsp.example.com", "pathPrefix": "/openrtb" }, "clientToken": "token-west-openrtb" }
Rule on link 4 (link-anyco-west-native):
{ "gatewayId": "rtb-gw-abc123def456", "linkId": "link-anyco-west-native", "priority": 4, "conditions": { "hostHeader": "west-bid.dsp.example.com", "pathPrefix": "/native" }, "clientToken": "token-west-native" }
With this configuration:
A request to
https://east-bid.dsp.example.com/openrtb/bidroutes tolink-anyco-east-openrtb(priority 1).A request to
https://east-bid.dsp.example.com/native/bidroutes tolink-anyco-east-native(priority 2).A request to
https://west-bid.dsp.example.com/openrtb/bidroutes tolink-anyco-west-openrtb(priority 3).A request to
https://west-bid.dsp.example.com/native/bidroutes tolink-anyco-west-native(priority 4).
Note
Because each rule combines a distinct hostHeader and pathPrefix, the priority ordering in this example affects evaluation performance but not correctness — only one rule can match any given request. Assign lower priority values to higher-traffic routes for faster evaluation.
Testing routing rules with /resolve-link
The gateway exposes a /resolve-link endpoint that evaluates your routing rules against a given URL without sending actual traffic. Use this endpoint to verify that rules are configured correctly before migrating DNS.
Request: GET /resolve-link?url=<url-encoded-value>
The url query parameter must be a fully qualified, URL-encoded URL (including scheme, host, path, and optional query string).
Responses:
| Status | Meaning | Response body |
|---|---|---|
| 200 | A routing rule matched | {"link_id": "link-abc123", "rule_id": "rule-xyz789"} |
| 404 | No routing rule matched | {"message": "No routing rules matched the provided URL"} |
| 400 | Missing or invalid input | {"message": "Missing or invalid 'url' query parameter"} |
Example:
curl "https://<GATEWAY_ENDPOINT>/resolve-link?url=https%3A%2F%2Fbid.example.com%2Fopenrtb%2Fbid"
A successful match returns the link_id and rule_id of the first matching rule:
{"link_id": "link-abc123", "rule_id": "rule-xyz789"}
Note
The /resolve-link endpoint evaluates rules in the same global priority order as live traffic. A 404 response indicates that no rule matches — review your rule conditions and priorities. See Troubleshooting inbound external links with custom domains if requests return unexpected results.