Competitive Signal Business Rules Router avatar

Competitive Signal Business Rules Router

Pricing

from $17.00 / 1,000 delivered signal routing plans

Go to Apify Store
Competitive Signal Business Rules Router

Competitive Signal Business Rules Router

Turn buyer-supplied normalized signals and ordered rules into one deterministic routing plan. Preserve matched routes, unmatched signals, warnings, stable digests, evidence gaps, human review action, and current-run billing truth without contacting destinations.

Pricing

from $17.00 / 1,000 delivered signal routing plans

Rating

0.0

(0)

Developer

Tim Zinin

Tim Zinin

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

11 days ago

Last modified

Share

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, reproducible digests, and a review-bound decision layer. The Actor does not send messages, call destinations, fetch URLs, verify sources, or infer brand identity.

The public default is contract 1.1. It adds an evidence and decision boundary to the Dataset plan plus a current-run KVS OUTPUT receipt with work counters, Dataset-delivery truth, named-event settlement, terminal KVS state, and replay safety. Explicit schemaVersion: "1.0" remains available and preserves the frozen legacy plan and success receipt byte-for-byte.

Signal Rule Router: buyer input to evidence-backed action

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:

{
"schemaVersion": "1.1",
"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.

Enhanced 1.1 Dataset result

A successful 1.1 computation creates one settlement-neutral routing plan. The plan says it is eligible for the linked result-found operation, but it never claims that payment succeeded. Paid, free, anomalous, and unknown settlement truth belongs only to the current run's KVS OUTPUT.

The plan retains the legacy routing fields and adds decision:

{
"schemaVersion": "1.1",
"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:611bf0ca6ca78081b769d43c87eacaaa5ba88c2c5f5309d04eecc7a263c8b7ef",
"decision": {
"recordType": "us_brand_signal_rule_router",
"entityId": "us_brand_signal_rule_router:611bf0ca6ca78081",
"observedAt": null,
"freshness": { "status": "unknown", "asOf": null, "basis": "buyer_supplied_snapshot_no_source_fetch" },
"change": { "status": "not_measured", "previousEntityId": null, "basis": "stateless_single_run" },
"confidence": { "score": 65, "band": "medium" },
"recommendedAction": "REVIEW_ROUTING_PLAN_AND_DESTINATION_OWNERSHIP_BEFORE_EXECUTION",
"priority": "review",
"safeToAutomate": false,
"failureDiagnostics": null,
"billing": {
"billingEligible": true,
"billingIntent": "linked_push_result_found",
"eventName": "result-found",
"unit": "one_delivered_signal_routing_plan",
"settlementSource": "current_run_kvs_output"
}
},
"resultDigest": "sha256:458a1e603263ca04e84aa9736c9de953a0299c926b0152171fdb47c5200cecda"
}

The abbreviated decision example omits its closed evidence, full five-item confidence.gaps, and deterministic summary; the complete executable fixture is examples/output.json in the source package.

Frozen 1.0 Dataset result

An explicit 1.0 run retains the prior routing plan exactly:

{
"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.

Frozen 1.0 OUTPUT receipt

For an explicit 1.0 input, the default KVS key OUTPUT retains the prior confirmed-delivery receipt:

{
"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.

Current-run 1.1 OUTPUT receipt

For the public 1.1 contract, OUTPUT embeds the exact routing plan and binds it to the current hosted run. A normal paid receipt has this shape:

{
"status": "success",
"report": { "schemaVersion": "1.1", "resultDigest": "sha256:458a1e603263ca04e84aa9736c9de953a0299c926b0152171fdb47c5200cecda" },
"inputDigest": "sha256:611bf0ca6ca78081b769d43c87eacaaa5ba88c2c5f5309d04eecc7a263c8b7ef",
"runId": "rule-router-example-run",
"delivery": {
"datasetWrite": "confirmed",
"settlement": "paid",
"defaultDatasetBillingEvent": "absent",
"resultEvent": "result-found",
"customEventCountBefore": 0,
"customEventCountAfter": 1,
"customEventCountDelta": 1,
"aggregateChargedCount": 2,
"eventChargeLimitReached": false,
"chargeableWithinLimit": { "apify-actor-start": 0, "result-found": 0 },
"confirmedDatasetWrites": 1,
"confirmedResultEvents": 1,
"confirmedCharges": 1,
"chargedCount": 1
},
"run": {
"requestedCount": 6,
"uniqueCount": 6,
"duplicateCount": 0,
"successfulCount": 6,
"failedCount": 0,
"deliveredRowCount": 1,
"paidRowCount": 1,
"freeRowCount": 0,
"withheldRowCount": 0,
"anomalousChargeCount": 0,
"ambiguousDeliveryCount": 0,
"ambiguousSettlementCount": 0,
"partial": false,
"budgetStopped": false,
"fatalError": null,
"replaySafe": false,
"safeToAutomate": false
},
"terminal": { "primaryKvsWrite": "confirmed", "recoveryKvsWrite": "not_attempted", "exit": "requested" }
}

The abbreviated report above is only a navigation aid. The actual OUTPUT.report is the complete closed Dataset row, and its bytes must reconcile with the single Dataset item. examples/output-receipt-1.1.json contains the complete executable example.

Why replaySafe is false after delivery starts

This Actor has no cross-run ledger. A new run is a new purchase and may deliver the same deterministic plan again. Therefore:

  • replaySafe: true appears only on a terminal pre-delivery error where no Dataset push was attempted;
  • replaySafe: false appears after any push attempt, after a confirmed delivery, and on success;
  • an ambiguous push or settlement must be reconciled manually from that run's Dataset, OUTPUT, platform counters, and logs;
  • never start a blind retry after delivery_unknown, charge_counter_unavailable, aggregate_receipt_invalid, or another delivery error.

Delivery and settlement are separate facts

Actor.pushData can return even if the named event was not charged, and its return can be lost even if the Dataset operation reached the platform. The receipt therefore keeps two axes:

SituationdatasetWritesettlementBuyer interpretation
Push threw before a usable returnunknownunknownDataset delivery may or may not exist; do not retry blindly.
Push returned; counter stayed 0confirmedfreeOne plan is in the Dataset, but no result-found unit was confirmed.
Push returned; counter cannot be readconfirmedunknownDataset delivery is known; named-event settlement needs reconciliation.
Push returned; counter moved 0 -> 1confirmedpaidOne delivered plan and one named paid unit are confirmed.
Push returned; counter moved by more than oneconfirmedanomalousDelivery is known, but settlement is inconsistent and the run fails.

The Dataset decision block is deliberately settlement-neutral. Its billingEligible and billingIntent fields describe the attempted commercial unit, not payment confirmation. Only OUTPUT.delivery, OUTPUT.run, and the platform chargedEventCounts settle the current run.

API and MCP usage

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

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:

{
"actorId": "zinin/us-brand-signal-rule-router",
"input": {
"schemaVersion": "1.1",
"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 tierDiscountStartRouting planSuccessful total
FREE0%$0.00500$0.02000$0.02500
BRONZE5%$0.00475$0.01900$0.02375
SILVER10%$0.00450$0.01800$0.02250
GOLD15%$0.00425$0.01700$0.02125
PLATINUM18%$0.00410$0.01640$0.02050
DIAMOND20%$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.

For 1.1, the guard uses exact micro-USD arithmetic. It requires exactly the two approved event keys, one of the six complete tier pairs, a readable named result-found counter initially equal to zero, and a current spend that already includes the tier's start charge. A positive infinite buyer cap is accepted as genuinely uncapped. Strings, negative values, non-finite values other than positive infinity, extra zero-priced events, prior named events, missing start spend, and tier drift all fail before the paid push.

The cheapest live tier total is $0.02000 per successful run: $0.00400 start plus $0.01600 routing plan. A no-network computation uses only the Actor container. A live canary must still compare the actual platform usage receipt with the exact paid total and prove at least 3× direct-variable-cost coverage; this README does not invent that ratio before canary evidence exists.

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.

Signal Rule Router: evidence-to-action workflow

Decision layer

The 1.1 decision layer is an interpretation boundary, not an automated business decision.

  • entityId is stable for the submitted input digest.
  • observedAt and freshness asOf are null because this Actor never observes a source.
  • freshness is unknown; the only basis is a buyer-supplied snapshot.
  • change is not_measured; runs are stateless and no previous plan is loaded.
  • confidence is a fixed medium 65, reflecting deterministic rule evaluation but unverified signal truth, source provenance, rule suitability, route ownership, and destination delivery.
  • recommendedAction is always review before execution.
  • safeToAutomate is always false.
  • failureDiagnostics is null on a computed plan; terminal failures are represented in KVS OUTPUT, not rewritten into the delivered plan.

The Actor answers, “Which explicit route labels do these explicit ordered rules produce?” It does not answer whether the underlying event is true, whether the route is appropriate, whether a person owns that route, or whether an external system should act.

Privacy, data rights, and retention

This is a no-fetch processor, so there is no third-party crawling or source API license in the runtime. That does not grant rights over buyer input.

By submitting rows, the buyer is responsible for having the right to process and store every supplied brand label, source label, event, timestamp, score, and rule. Do not place personal data, secrets, access tokens, confidential notes, health data, precise consumer identifiers, or restricted source material in IDs or labels. A sourceName is copied as an unverified string; it is not evidence of a license or source check.

The Apify run stores the input in the run's default KVS. The Dataset stores the complete routing plan. KVS OUTPUT stores the complete plan again for current-run reconciliation. The Actor itself creates no durable cross-run database and does not fetch the recorded source labels. Buyers control retention through their Apify account and should delete inputs, Dataset items, OUTPUT records, and run logs according to their own policy. SHA-256 digests support integrity; they are not anonymization and do not make sensitive input safe.

What the Actor gives you

  • one closed deterministic routing plan rather than one row per signal;
  • every accepted signal ID represented exactly once in the plan;
  • firstMatch or ordered allMatches routing without code or regex execution;
  • unmatched IDs, per-route counts, warnings, canonical input digest, and full plan digest;
  • an evidence-only decision boundary in 1.1;
  • a current-run receipt that distinguishes Dataset delivery from paid, free, anomalous, or unknown settlement;
  • a frozen explicit 1.0 migration path.

What it does not give you

  • source fetching, crawling, enrichment, identity resolution, or fact verification;
  • a CRM login, webhook, message send, queue write, or destination side effect;
  • assurance that a route label belongs to a real person or team;
  • recommendation that any rule is suitable, fair, compliant, or effective;
  • deduplication across separate runs or replay protection across purchases;
  • a legal, compliance, investment, employment, medical, or safety conclusion.

Integration patterns

Store console

  1. Choose contract 1.1 unless an existing integration requires the frozen 1.0 shape.
  2. Paste complete normalized signals; do not omit required fields or use free-form extra fields.
  3. Order the rules deliberately. Rule order changes firstMatch semantics.
  4. Start with a buyer cap that covers the exact start plus one routing-plan event for the current tier.
  5. Inspect the single Dataset plan.
  6. Inspect OUTPUT and the platform counters before treating settlement as final.
  7. Review unmatched signals and every route owner before any downstream execution.

JavaScript client

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('zinin/us-brand-signal-rule-router').call(input, {
waitSecs: 90,
maxTotalChargeUsd: 0.025
});
const dataset = await client.dataset(run.defaultDatasetId).listItems();
const output = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('OUTPUT');
if (dataset.items.length !== 1 || output?.value?.runId !== run.id) {
throw new Error('current_run_reconciliation_failed');
}

$0.025 is the FREE-tier exact total shown in the table, not a universal recommendation. Adjust the bounded cap only from the current tier receipt. Do not retry if OUTPUT says delivery or settlement is unknown.

Python client

from apify_client import ApifyClient
import os
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("zinin/us-brand-signal-rule-router").call(
run_input=input_payload,
max_total_charge_usd=0.025,
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
output = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")
assert len(items) == 1
assert output["value"]["runId"] == run["id"]

MCP orchestration

An Apify MCP client can invoke the Actor with the same JSON object. The returned route IDs remain labels only. A surrounding agent must not translate them into messages, tickets, ads, suppressions, or alerts without separately verifying source rights, current evidence, route ownership, and the buyer's intended action.

Contract migration

ConcernExplicit 1.0Public 1.1
Plan fieldsfrozen eight-key planlegacy fields plus closed decision
Plan digestfrozen and byte-testedcovers the enhanced plan and decision
OUTPUTfrozen legacy success/failure receiptcurrent-run embedded plan and full reconciliation
Run IDabsenthosted Actor run ID required
Work counterspartial legacy delivery factsrequested, unique, duplicate, success, failure, delivery and settlement counters
Replayexplained only in docsexplicit replaySafe
Automation safetynot machine-readablealways false

Do not change schemaVersion silently in a pinned integration. The 1.0 fixtures remain executable regression artifacts. The Store default is 1.1 because new buyers need the decision and current-run reconciliation layer.

Failure handling

Pre-delivery failures write a bounded status: "error" receipt when KVS is available, fail the run, and keep replaySafe: true because no Dataset push was attempted. Examples include invalid input, missing hosted run identity, pricing drift, prior result counter, and a buyer cap below the exact next result unit.

Once the Dataset push is attempted, the run is never replay-safe. Delivery errors preserve the computed plan, the run ID, work counters, delivery facts, and terminal state. The runtime makes at most one primary KVS write and one bounded recovery write. An OUTPUT-write failure after confirmed delivery does not retry the paid push. An Actor-exit failure records the already confirmed Dataset and settlement facts before failing nonzero.

If both KVS writes fail, the platform run failure is authoritative and there may be no current OUTPUT. Inspect the run status and logs; do not infer success from a missing receipt and do not rerun blindly.

Data quality checklist

Before accepting the plan:

  • confirm every signalId, ruleId, and routeId is stable and scoped to your system;
  • confirm every row is genuinely US-scoped if that semantic matters beyond the literal country: "US" field;
  • verify brandName, sourceName, event type, severity, confidence, analysis status, and timestamp against your own evidence;
  • review ordered rules for shadowing in firstMatch mode;
  • review multi-route fan-out in allMatches mode;
  • resolve every unmatched signal or explicitly accept it;
  • validate destination ownership outside this Actor;
  • reconcile Dataset, KVS OUTPUT, platform run ID, and chargedEventCounts;
  • treat all SHA-256 values as integrity identifiers, not proof that the input was true.

Canary acceptance boundary

A release canary should use a small synthetic 1.1 input, one immutable candidate build, one no-retry run, and a bounded cap. Acceptance requires:

  • exact candidate build and current hosted run ID;
  • run status SUCCEEDED only on the success lattice;
  • exactly one Dataset plan and one OUTPUT.report with matching bytes and digest;
  • result counter exactly 0 -> 1 and platform counters exactly one start plus one result;
  • no priced default Dataset-item event;
  • one delivered and paid row, zero free/anomalous/ambiguous rows;
  • replaySafe: false, safeToAutomate: false, and no fatal error;
  • complete Dataset view fields and clean logs;
  • direct-variable-cost coverage of at least 3× at the cheapest tier.

Any ambiguous delivery, unknown settlement, schema rejection, KVS mismatch, or log failure stops promotion. There is no second canary POST and no blind retry.

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.

ActorHow it fits
Intent Signal AggregatorProduce hiring and news intent signals before deterministic routing.
Company Profile LookupAdd explicit company context before building normalized signal rows.
Shopify Store IntelligenceProduce public catalog and merchant observations for a routing workflow.
Funding Round TrackerSupply funding signals that can be mapped to analyst routes.
Patent Filing MonitorSupply 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.