# US Brand Signal Rule Router (`zinin/us-brand-signal-rule-router`) Actor

Route normalized US-brand signals through ordered, explicit rules into a deterministic machine-readable plan. No network, destinations, webhooks, or inferred identity.

- **URL**: https://apify.com/zinin/us-brand-signal-rule-router.md
- **Developed by:** [Tim Zinin](https://apify.com/zinin) (community)
- **Categories:** Automation, Marketing, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## US Brand Signal Rule Router

Turn normalized US-brand intelligence signals into one deterministic routing plan. Supply explicit signal rows and ordered rules; receive every signal exactly once with its matched route IDs, unmatched IDs, per-route counts, warnings, and reproducible digests. The Actor does not send messages, call destinations, fetch URLs, or infer brand identity.

### Input

Send 1-50 inline signals and 1-20 rules in `firstMatch` or `allMatches` mode. This complete synthetic example can be pasted into the Apify input editor:

```json
{
  "schemaVersion": "1.0",
  "mode": "firstMatch",
  "signals": [
    {
      "signalId": "sig-nike-launch-001",
      "brandName": "Nike",
      "eventType": "product_launch",
      "severity": "high",
      "confidence": 0.96,
      "sourceName": "brand-monitor-fixture",
      "country": "US",
      "analysisStatus": "unreviewed",
      "observedAt": "2026-08-05T10:00:00.000Z"
    },
    {
      "signalId": "sig-acme-incident-002",
      "brandName": "Acme Labs",
      "eventType": "safety_incident",
      "severity": "critical",
      "confidence": 0.91,
      "sourceName": "brand-monitor-fixture",
      "country": "US",
      "analysisStatus": "reviewed",
      "observedAt": "2026-08-05T10:01:00.000Z"
    },
    {
      "signalId": "sig-unmatched-003",
      "brandName": "Contoso",
      "eventType": "news_item",
      "severity": "low",
      "confidence": 0.42,
      "sourceName": "press-fixture",
      "country": "US",
      "analysisStatus": "unknown",
      "observedAt": "2026-08-05T10:02:00.000Z"
    }
  ],
  "rules": [
    {
      "ruleId": "rule-critical",
      "routeId": "risk-review",
      "eventType": null,
      "severity": "critical",
      "confidenceMin": 0.8,
      "confidenceMax": null,
      "sourceName": null,
      "country": "US",
      "analysisStatus": null
    },
    {
      "ruleId": "rule-launch",
      "routeId": "launch-review",
      "eventType": "product_launch",
      "severity": null,
      "confidenceMin": 0.9,
      "confidenceMax": null,
      "sourceName": "brand-monitor-fixture",
      "country": "US",
      "analysisStatus": "unreviewed"
    },
    {
      "ruleId": "rule-high-confidence",
      "routeId": "confidence-review",
      "eventType": null,
      "severity": null,
      "confidenceMin": 0.9,
      "confidenceMax": 1,
      "sourceName": null,
      "country": null,
      "analysisStatus": null
    }
  ]
}
```

Rules can match only `eventType`, `severity`, inclusive `confidenceMin`/`confidenceMax`, `sourceName`, `country`, and `analysisStatus`. There is no expression language, regex, code, URL, webhook, or destination field. In `firstMatch`, the first matching rule wins. In `allMatches`, every matching route is retained in rule order.

### Dataset result

A successful run writes exactly one paid routing plan:

```json
{
  "schemaVersion": "1.0",
  "mode": "firstMatch",
  "signals": {
    "sig-acme-incident-002": { "matchedRouteIds": ["risk-review"] },
    "sig-nike-launch-001": { "matchedRouteIds": ["launch-review"] },
    "sig-unmatched-003": { "matchedRouteIds": [] }
  },
  "unmatchedSignalIds": ["sig-unmatched-003"],
  "routeCounts": { "risk-review": 1, "launch-review": 1, "confidence-review": 0 },
  "warnings": ["unmatched_signals_present"],
  "inputDigest": "sha256:421ee443a0061e0fe0654b61c18dc4bec9a6beca8c61a77ba20e0091517e2a37",
  "resultDigest": "sha256:a13b4f9a49fc68740a41b5bbbc4a07767c6280d609389b1e3dfbd379e3203c23"
}
```

Signal IDs and route IDs are JSON object keys, so each appears once. Signals are ordered by UTF-8 bytes for output and digest purposes. Rule order remains semantic.

### OUTPUT receipt

The default KVS key `OUTPUT` records confirmed delivery and billing truth:

```json
{
  "schemaVersion": "1.0",
  "status": "result-found",
  "deliveryState": "confirmed_paid_result",
  "planDigest": "sha256:a13b4f9a49fc68740a41b5bbbc4a07767c6280d609389b1e3dfbd379e3203c23",
  "attemptedPushCount": 1,
  "datasetWriteCount": 1,
  "resultChargeDelta": 1,
  "confirmedResultChargeCount": 1,
  "chargedCount": 2,
  "eventChargeLimitReached": false,
  "datasetItemBillingEvent": null
}
```

A successful receipt requires the custom `result-found` counter proof `0 -> 1`, the documented SDK aggregate `chargedCount: 2` (paid `result-found` plus zero-price default Dataset item), and a boolean `eventChargeLimitReached` value. The local/test harness may use `chargedCount: 1` only with that exact counter proof. The boolean is preserved in `OUTPUT`; `true` means the successful current charge left no room for the next event of that type. Contradictory delivery data fails closed. Failure truth distinguishes a confirmed paid Dataset result from a confirmed charge whose push delivery is unknown. If KVS or Actor exit fails after a confirmed paid push, the failure signal retains the plan digest, exact charge delta, Dataset-delivery fact, and OUTPUT write count; the Actor never retries the paid push.

### API and MCP usage

After the Actor is public, submit the same input through the Apify API:

```bash
curl -sS -X POST \
  'https://api.apify.com/v2/acts/zinin~us-brand-signal-rule-router/runs?waitForFinish=60' \
  -H 'Authorization: Bearer YOUR_APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  --data @input.json
```

An MCP client connected to Apify can pass the same object to its Actor-call tool:

```json
{
  "actorId": "zinin/us-brand-signal-rule-router",
  "input": {
    "schemaVersion": "1.0",
    "mode": "firstMatch",
    "signals": [{
      "signalId": "sig-demo-001",
      "brandName": "Demo Brand",
      "eventType": "recall",
      "severity": "critical",
      "confidence": 0.95,
      "sourceName": "synthetic-fixture",
      "country": "US",
      "analysisStatus": "unreviewed",
      "observedAt": "2026-08-05T10:00:00.000Z"
    }],
    "rules": [{
      "ruleId": "rule-risk",
      "routeId": "risk-review",
      "eventType": "recall",
      "severity": null,
      "confidenceMin": 0.9,
      "confidenceMax": null,
      "sourceName": null,
      "country": "US",
      "analysisStatus": null
    }]
  }
}
```

This is an invocation shape, not a claim that a separate MCP server or catalog registration already exists.

### Pricing and discounts

Pay per event uses only Actor start plus one `result-found` routing plan. There is no default Dataset-item event.

| Apify tier | Discount | Start | Routing plan | Successful total |
|---|---:|---:|---:|---:|
| FREE | 0% | $0.00500 | $0.02000 | $0.02500 |
| BRONZE | 5% | $0.00475 | $0.01900 | $0.02375 |
| SILVER | 10% | $0.00450 | $0.01800 | $0.02250 |
| GOLD | 15% | $0.00425 | $0.01700 | $0.02125 |
| PLATINUM | 18% | $0.00410 | $0.01640 | $0.02050 |
| DIAMOND | 20% | $0.00400 | $0.01600 | $0.02000 |

The buyer cap is checked before routing. Missing, mixed, extra, or malformed event prices fail closed. Each separate Actor run is a separate purchase; there is no cross-run replay ledger.

### Limits and validation

- 1-50 signals and 1-20 rules; serialized canonical input is at most 256 KiB.
- Runtime target: LIMITED visibility, 512 MB memory, 90 seconds.
- IDs are unique bounded ASCII values and cannot be all-numeric. Text is NFC, at most 128 Unicode characters and 256 UTF-8 bytes; BOM and Unicode line/paragraph separators are rejected.
- Confidence values are finite, between zero and one, and canonicalized on a nine-decimal grid.
- Timestamps are strict UTC ISO values with milliseconds, valid calendar dates, and years from `0001` through `9999`.
- No Dataset input, BYOK, proxy, fetch, destination call, state, replay, ledger, or inferred identity.

### Related Actors

These optional neighboring Actors were independently read back as public and non-deprecated in the fleet pre-ship receipts. This Actor does not call them.

| Actor | How it fits |
|---|---|
| [Intent Signal Aggregator](https://apify.com/zinin/intent-signal-aggregator) | Produce hiring and news intent signals before deterministic routing. |
| [Company Profile Lookup](https://apify.com/zinin/company-lookup) | Add explicit company context before building normalized signal rows. |
| [Shopify Store Intelligence](https://apify.com/zinin/shopify-store-intelligence) | Produce public catalog and merchant observations for a routing workflow. |
| [Funding Round Tracker](https://apify.com/zinin/funding-round-tracker) | Supply funding signals that can be mapped to analyst routes. |
| [Patent Filing Monitor](https://apify.com/zinin/patent-monitor) | Supply patent events for research and competitive-intelligence routes. |

### FAQ

**Does a route ID send a message?** No. It is only a machine-readable label in the plan.

**Can a rule run code or regex?** No. Unknown fields and non-explicit predicates are rejected.

**What happens to unmatched signals?** They remain in `signals`, appear in `unmatchedSignalIds`, and produce one warning.

**Are input permutations stable?** Signal permutations produce the same plan and digests. Reordering rules can change `firstMatch` results by design.

**Does the Actor deduplicate separate runs?** No. Every run is an independent purchase.

### Store text

**SEO title:** US Brand Signal Rule Router | Deterministic Routing Plan

**Meta description:** Route normalized US-brand intelligence signals through safe ordered rules into one deterministic machine-readable plan with exact digests and billing receipts.

**Keywords:** US brand intelligence, signal routing, rule engine, deterministic JSON, marketing automation, MCP Actor

Built by [zinin](https://apify.com/zinin).

# Actor input Schema

## `schemaVersion` (type: `string`):

Closed input and output contract version.

## `mode` (type: `string`):

firstMatch uses the first matching rule; allMatches retains every matching rule in input order.

## `signals` (type: `array`):

Closed rows. Runtime additionally enforces unique IDs, NFC, 256 UTF-8-byte text bounds, a 256 KiB envelope, strict calendar timestamps, and finite 9-decimal confidence values.

## `rules` (type: `array`):

Closed explicit predicates. Runtime additionally enforces unique rule/route IDs, NFC and UTF-8 byte bounds, and confidenceMin <= confidenceMax because the Store schema dialect cannot compare sibling values.

## Actor input object example

```json
{
  "schemaVersion": "1.0",
  "mode": "firstMatch",
  "signals": [
    {
      "signalId": "sig-nike-launch-001",
      "brandName": "Nike",
      "eventType": "product_launch",
      "severity": "high",
      "confidence": 0.96,
      "sourceName": "brand-monitor-fixture",
      "country": "US",
      "analysisStatus": "unreviewed",
      "observedAt": "2026-08-05T10:00:00.000Z"
    }
  ],
  "rules": [
    {
      "ruleId": "route-high-risk",
      "routeId": "risk-review",
      "eventType": null,
      "severity": "critical",
      "confidenceMin": 0.8,
      "confidenceMax": null,
      "sourceName": null,
      "country": "US",
      "analysisStatus": null
    }
  ]
}
```

# Actor output Schema

## `OUTPUT` (type: `string`):

Closed receipt with the plan digest and confirmed result-found charge delta.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "signals": [
        {
            "signalId": "sig-nike-launch-001",
            "brandName": "Nike",
            "eventType": "product_launch",
            "severity": "high",
            "confidence": 0.96,
            "sourceName": "brand-monitor-fixture",
            "country": "US",
            "analysisStatus": "unreviewed",
            "observedAt": "2026-08-05T10:00:00.000Z"
        }
    ],
    "rules": [
        {
            "ruleId": "route-high-risk",
            "routeId": "risk-review",
            "eventType": null,
            "severity": "critical",
            "confidenceMin": 0.8,
            "confidenceMax": null,
            "sourceName": null,
            "country": "US",
            "analysisStatus": null
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zinin/us-brand-signal-rule-router").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "signals": [{
            "signalId": "sig-nike-launch-001",
            "brandName": "Nike",
            "eventType": "product_launch",
            "severity": "high",
            "confidence": 0.96,
            "sourceName": "brand-monitor-fixture",
            "country": "US",
            "analysisStatus": "unreviewed",
            "observedAt": "2026-08-05T10:00:00.000Z",
        }],
    "rules": [{
            "ruleId": "route-high-risk",
            "routeId": "risk-review",
            "eventType": None,
            "severity": "critical",
            "confidenceMin": 0.8,
            "confidenceMax": None,
            "sourceName": None,
            "country": "US",
            "analysisStatus": None,
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("zinin/us-brand-signal-rule-router").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "signals": [
    {
      "signalId": "sig-nike-launch-001",
      "brandName": "Nike",
      "eventType": "product_launch",
      "severity": "high",
      "confidence": 0.96,
      "sourceName": "brand-monitor-fixture",
      "country": "US",
      "analysisStatus": "unreviewed",
      "observedAt": "2026-08-05T10:00:00.000Z"
    }
  ],
  "rules": [
    {
      "ruleId": "route-high-risk",
      "routeId": "risk-review",
      "eventType": null,
      "severity": "critical",
      "confidenceMin": 0.8,
      "confidenceMax": null,
      "sourceName": null,
      "country": "US",
      "analysisStatus": null
    }
  ]
}' |
apify call zinin/us-brand-signal-rule-router --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=zinin/us-brand-signal-rule-router",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/pKbb5MYUPHIKuFg2S/builds/gty8vSnNgbkyKswdM/openapi.json
