# Shipping Policy Change Monitor - Free Threshold (`steadyworks/shipping-policy-change-monitor`) Actor

Track DTC shipping-promise changes daily — free-shipping thresholds, fees and delivery windows with evidence rows. Max $29/run for up to 193 rows — capped, lands clean; monthly total capped at $29. Quiet runs $0.

- **URL**: https://apify.com/steadyworks/shipping-policy-change-monitor.md
- **Developed by:** [steadyworks](https://apify.com/steadyworks) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $90.00 / 1,000 verified promise-change rows

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shipping Policy Change Monitor - Free Threshold

Track competitor shipping promises with a daily watch — paste your shop watchlist in, get one verified row per real change (free-shipping threshold, fee, delivery window, returns term) with a was-now pair and an evidence link. The Shipping Policy Change Monitor scrapes shipping-policy data for free, bills only on verified change ($0.15 per verified row, quiet runs $0), and stays capped at $29/month.

> Click **Try for free** — input opens prefilled. Start as-is, check rows, then raise cap.

### What it does / What you get

The Shipping Policy Change Monitor watches the shipping-policy, returns-policy, and cart pages you list, once per daily run, and reports only typed, evidence-backed changes — never a guess.

- **Free-shipping threshold tracking** — catches moves like `$50 → $75` with the before/after text on file.
- **Fee and delivery-window rows** — ship fees, delivery-window text, and returns-day terms, each as its own typed row.
- **Evidence on every row** — each change carries `evidenceUrl`, `checkedAt`, and a fetch-provenance note.
- **Quiet means quiet** — unchanged stores emit zero rows and bill $0; the run summary still shows what was watched.
- **Walls are skipped, never guessed** — bot-walled, login-walled, and JS-only pages stay quiet instead of producing a fabricated change.
- **Spend guards on both ends** — a per-run `maxSpendUsd` guard plus a $29/month accrual cap with counts-only suppression past the cap (baseline frozen, nothing lost).
- **Agent-ready output** — default-dataset rows plus a matching `OUTPUT` record in the key-value store for chaining.

### Quick start: scrape shipping policies in 5 steps

1. Click **Try for free** (input opens prefilled with a 3-shop demo watchlist — a `$0` synthetic first run).
2. Keep the demo URLs or replace them with 3–10 competitor domains you are allowed to watch (shipping, returns, and cart pages).
3. Leave `cadence: "daily"` and the caps as-is for the first run.
4. Click **Save & Start**, then open the **Dataset** tab when the run finishes.
5. First run lands quiet (0 rows, $0 — boot proven). Add the frozen demo replay or widen the watchlist once the row shape looks right.

> Click **Try for free** — input opens prefilled. Start as-is, check rows, then raise cap.

### Input: watchlist API contract

Minimal JSON (required-only — paste this to start):

```json
{
  "watchId": "shipping-watch-demo-01",
  "competitors": ["shop-a.example.com", "shop-b.example.com", "shop-c.example.com"],
  "competitorPolicyUrls": [
    "https://shop-a.example.com/shipping",
    "https://shop-a.example.com/returns",
    "https://shop-a.example.com/cart",
    "https://shop-b.example.com/shipping",
    "https://shop-b.example.com/returns",
    "https://shop-b.example.com/cart",
    "https://shop-c.example.com/shipping",
    "https://shop-c.example.com/returns",
    "https://shop-c.example.com/cart"
  ],
  "cadence": "daily"
}
```

Full JSON (all defaults — matches the Console prefill byte-for-byte):

```json
{
  "watchId": "shipping-watch-demo-01",
  "competitors": ["shop-a.example.com", "shop-b.example.com", "shop-c.example.com"],
  "competitorPolicyUrls": [
    "https://shop-a.example.com/shipping",
    "https://shop-a.example.com/returns",
    "https://shop-a.example.com/cart",
    "https://shop-b.example.com/shipping",
    "https://shop-b.example.com/returns",
    "https://shop-b.example.com/cart",
    "https://shop-c.example.com/shipping",
    "https://shop-c.example.com/returns",
    "https://shop-c.example.com/cart"
  ],
  "cadence": "daily",
  "computeCapUsd": 39,
  "maxSpendUsd": 29,
  "capMode": "capped",
  "synthetic": true
}
```

| field | type | required | default | units | limits |
|---|---|---|---|---|---|
| `watchId` | string | yes | — (prefill `shipping-watch-demo-01`) | — | lowercase letters, digits, dashes; max 64 chars; use a fresh value per watch |
| `competitors` | string\[] | yes | — | domains | 3–10 domains per run |
| `competitorPolicyUrls` | string\[] (url) | yes | — | URLs | 3–30 `http(s)` URLs: shipping, returns, and cart pages |
| `cadence` | string (enum) | yes | `daily` | — | only `"daily"` is accepted; anything else is rejected pre-run with zero spend |
| `computeCapUsd` | number | no | `39` | USD | 0–39; test-window compute bound, separate from the per-row meter |
| `maxSpendUsd` | number | no | `29` | USD | 0.15–29; per-run spend guard — a run that would bill past it stops fail-closed before any charge |
| `capMode` | string (enum) | no | `capped` | — | `capped` (default, today's promise verbatim) or `complete-input` (one manual run processes the whole watchlist; worst case quoted pre-charge, never above $6.00; schedules/tasks always capped) |
| `synthetic` | boolean | no | `true` | — | marks fixture-scale synthetic input |
| `seededBaseline` | object | no | — | — | fixture replay only: frozen per-store baseline; omit for the honest seed-and-silence boot (0 rows, $0) |
| `secondRunObservations` | array | no | — | — | fixture replay only: frozen second-run observations; omit for the honest boot |
| `checkedAt` | string | no | — | ISO-8601 date-time | optional carried run timestamp; omit for the carried default |

Job-titled one-line recipes: `DTC founder threshold watch` (3 shops, shipping pages only, `maxSpendUsd: 0.15`) · `agency multi-shop sweep` (10 domains, 30 URLs, `maxSpendUsd: 5`) · `holiday-cutoff watch` (carrier + big-box date pages, daily cadence) · `cap-guarded edge check` (2-row cut against the `$0.15` floor — stops before any charge) · `quiet-rerun proof` (byte-identical rerun, 0 rows, $0).

### Output: change data rows with evidence

Results land in the **default dataset** (one summary item per run; switch to the `promise-changes` view for one-row-per-change) plus the same summary as the **`OUTPUT` record** in the default key-value store for agent chaining. Buyer A never sees buyer B's rows — every run gets its own private dataset.

| field | type | description |
|---|---|---|
| `store` | string | watched domain the change was read on |
| `changeType` | string (enum) | `threshold` · `fee` · `delivery-window` · `returns` |
| `was` / `now` | string | before/after promise text, verbatim |
| `evidenceUrl` | string (url) | live page the pair was read from |
| `checkedAt` | string (ISO-8601) | when the pair was observed |
| `fetchPath` | string | `plain` static read or `browser-fallback` rendered-pass read |
| `notice` | string | human-readable row note |
| `billable` / `billableEvent` | boolean / string | `true` / `verified-promise-change-row` on priced rows |
| `unitPriceUsd` | number | `0.15` per priced row |
| `rowId` / `watchId` | string | stable row key / scope key |
| `billedRows` / `spendUsd` | integer / number | run totals for billing-compare |
| `suppressedRows` / `capTripped` | integer / boolean | counts-only rows past the $29 cap + cap flag |

Real example rows (shortened for viewing — same shops as the input above):

```json
[
  {
    "watchId": "shipping-watch-demo-01",
    "rowId": "shipping-watch-demo-01-shop-a-example-com-threshold",
    "store": "shop-a.example.com",
    "changeType": "threshold",
    "was": "Free shipping on orders over $50.",
    "now": "Free shipping on orders over $75.",
    "evidenceUrl": "https://shop-a.example.com/shipping",
    "checkedAt": "2026-09-28T08:00:00Z",
    "fetchPath": "plain",
    "billable": true,
    "billableEvent": "verified-promise-change-row",
    "unitPriceUsd": 0.15
  },
  {
    "watchId": "shipping-watch-demo-01",
    "rowId": "shipping-watch-demo-01-shop-c-example-com-returns",
    "store": "shop-c.example.com",
    "changeType": "returns",
    "was": "60-day free returns.",
    "now": "30-day free returns.",
    "evidenceUrl": "https://shop-c.example.com/returns",
    "checkedAt": "2026-09-28T08:00:00Z",
    "fetchPath": "plain",
    "billable": true,
    "billableEvent": "verified-promise-change-row",
    "unitPriceUsd": 0.15
  }
]
```

*Rows shortened for viewing — full items also carry `notice`, `billingNote`, and the run-level meter report (`billedRows`, `spendUsd`, `accruedUsd`, `suppressedRows`, `capTripped`). Unchanged stores are skipped with zero rows, never a guessed change.*

<details>
<summary>Full run-summary shape (dataset item + OUTPUT record)</summary>

```json
{
  "watchId": "shipping-watch-demo-01",
  "billedRows": 2,
  "rowsEmitted": 2,
  "spendUsd": 0.3,
  "suppressedRows": 0,
  "capTripped": false,
  "rows": ["<2 verified-promise-change rows, shape as above>"],
  "report": {
    "unitPriceUsd": 0.15,
    "billedRows": 2,
    "spendUsd": 0.3,
    "accruedUsd": 0.3,
    "storesWatched": 3,
    "quiet": false
  }
}
```

</details>

### How much will it cost?

`from $150.00 / 1,000 verified promise-change rows` (`$0.15` per row). The billable event is `verified-promise-change-row`: it fires once per typed was-now change that passes validation and publishes. Quiet runs, jitter, login-walled skips, and seed runs are **not** billed — empty and failed runs cost $0.

| plan | $/1k verified rows |
|---|---|
| Pay-per-event meter (all plans) | $150.00 |

Tier prices live on the **Pricing tab** — the Console price is authoritative. The repo manifest (`docs/launch/price-manifest.json` v1.1.0) is the spec; any mismatch blocks publish.

Worked math (all at `$0.15`/row):

- **First check (1 store, 3 pages):** 0 rows quiet → **$0**.
- **Small change day (2 verified rows):** 2 × $0.15 → **$0.30/run**.
- **Active month (10 changes):** 10 × $0.15 → **$1.50/mo**.
- **Heavy month (100 changes):** 100 × $0.15 → **$15.00/mo**.
- **Cap binds at ~193 rows:** past **$29/mo** the run suppresses billable rows counts-only, keeps watching, and freezes the baseline — nothing is lost, the next run re-flags and re-bills.

Cap/floor/quiet: per-run guard `maxSpendUsd` ($0.15–$29, default $29) stops the run fail-closed before any charge if it would cost more; `$29`/mo accrual ceiling enforced per watch + calendar month; floor/minimum `$0.15` (one row); quiet runs `$0`; test-window compute bound `$39` (separate from the per-row meter). Set Max total charge (`ACTOR_MAX_TOTAL_CHARGE_USD`) as an extra platform-side ceiling.

Max $29/run for up to 193 units — lands SUCCEEDED at the cap; you pay more only if you turn on \[Complete my input] (`capMode: "complete-input"`, one manual run) — worst case computed from your input and quoted in the first log line + OUTPUT before any charge, never above $6.00 (40 rows = 10 stores × 4 typed fields × $0.15). Quotes above $6.00 fall back to capped fail-closed; schedules and task runs always run capped; the monthly $29 room and your Max total charge pin still bind; lift trips land counts-only + SUCCEEDED (`lifted-cap-trip`).

`event:verified-promise-change-row | $/1k 150.00 flat (single meter — tier prices on the Pricing tab) | includes_usage:false | billed_on_empty:false | caps:[maxSpendUsd,monthly-29-scopeBook] | quiet:[actor-start,quiet-runs-$0]`

### Trial: free first check, no paid plan needed

The standard **$5 Apify trial credit ≈ 33 verified rows** ($5 ÷ $0.15) — enough to prove the full loop many times over. No paid plan is needed to try.

- **Free first check:** 1 store (1 domain, up to 3 policy pages), daily cadence — `$0`, proves boot plus a quiet read. Before the trial limit is reached, the run reports how many free checks remain and names the paid full-watch upgrade.
- **Manual checks stop being enough at ~5 stores re-checked daily** (about 30 min/day of hand-checking, and changes slip for days) — that is the break size where the paid watch pays for itself.
- **Paid upgrade:** full watch at `$0.15` per verified promise-change row; quiet runs `$0`; accrual capped at `$29`/mo.

> Click **Try for free** — input opens prefilled. Start as-is, check rows, then raise cap.

### Compatibility: which stores this shipping scraper reads

Works with any server-rendered DTC shipping-policy, returns-policy, or cart page carrying a readable promise (threshold, fee, delivery window, returns term). Verified live:

- **Apple** — $50 → $75 free-shipping threshold change, Oct 2026 (rendered-pass catch)
- **USPS** — 2025 → 2026 holiday delivery-window change, Oct 2026 (archived-to-live replay, one step below a live catch)
- **Glossier** — shipping policy reads cleanly, Oct 2026 (no change found — read proof, not a catch)
- **Cotopaxi** — shipping policy reads cleanly, Oct 2026 (no change found — read proof, not a catch)
- **Both directions in one run** — the USPS change was caught while Glossier and Cotopaxi stayed correctly quiet: a catch and a clean read side by side.

Not covered: bot-walled stores, login-walled pages, and pages that never show shipping text in static HTML (plain path) or outside the per-target rendered pass. These stay quiet — never a guessed change.

*Store names belong to their owners; no affiliation, endorsement, or sponsorship implied. Not affiliated with Apple, USPS, Glossier, or Cotopaxi.*

### What people use it for + What it does NOT do

- **DTC founder threshold watch** — know the morning a rival moves free shipping from $50 to $75.
- **Agency multi-shop sweep** — one daily run across a client's competitor set, evidence links ready to paste into the report.
- **Holiday-cutoff watch** — carrier date pages and big-box holiday overlays as the season windows open.
- **Fee and returns-term drift** — restocking fees, ship-fee edits, and 60-day → 30-day returns cuts.
- **Promo-threshold rotation** — dated offer pages that rotate tiers into Black Friday and the holidays.

What this Actor does **NOT** do:

- Does not edit, reorder, or touch your store or anyone else's — read-only, rows out only.
- Does not bypass logins, captchas, or bot walls — walled pages are skipped, never forced.
- Does not guess: no readable promise text means no row, never an inferred change.
- Does not keep memory between runs beyond the watch scope you supply — each run compares what you send it.

### Use with schedules / webhooks / API / MCP

**Schedules (daily watch):** Console → Schedules → New schedule → target this Actor with your watchlist input → repeat daily. Each run checks the list once and bills only on verified change; quiet days cost $0.

**Webhooks (alert only when rows > 0):** add a run-succeeded webhook and filter on the payload — forward only when `billedRows > 0`:

```json
{ "event": "ACTOR.RUN.SUCCEEDED", "forwardIf": "billedRows > 0", "then": "post dataset items to Slack/email" }
```

**API (curl):** start a run, then poll — `call-actor` waits ≤45s, so poll `get-actor-run` or use a webhook, never block:

```bash
curl -X POST "https://api.apify.com/v2/acts/steadyworks~shipping-policy-change-monitor/runs?token=$APIFY_TOKEN" -H "Content-Type: application/json" -d '{"watchId":"my-shop-watch","competitors":["shop-a.example.com"],"competitorPolicyUrls":["https://shop-a.example.com/shipping"],"cadence":"daily"}'
```

**Python one-liner:**

```python
run = client.actor("steadyworks/shipping-policy-change-monitor").call(run_input={"watchId": "my-shop-watch", "competitors": ["shop-a.example.com"], "competitorPolicyUrls": ["https://shop-a.example.com/shipping"], "cadence": "daily"})
```

**JavaScript one-liner:**

```js
const run = await client.actor("steadyworks/shipping-policy-change-monitor").call({ watchId: "my-shop-watch", competitors: ["shop-a.example.com"], competitorPolicyUrls: ["https://shop-a.example.com/shipping"], cadence: "daily" });
```

**MCP (dispatcher recipe):**

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/mcp-server", "call", "steadyworks/shipping-policy-change-monitor"]
    }
  }
}
```

Then call with the minimal input above, poll `get-actor-run` past 45s, and read rows from the default dataset (`promise-changes` view) or the `OUTPUT` key-value record. Chain per-row `evidenceUrl` into any downstream summarizer.

### Troubleshooting

| symptom | cause | fix |
|---|---|---|
| 0 rows on first run | honest seed-and-silence boot (no baseline supplied yet) | expected — proves boot at $0; supply `seededBaseline` + `secondRunObservations` for the frozen demo replay, or widen the watchlist |
| 0 rows on later runs | genuinely no change (correct-quiet) | check the run summary (`storesWatched`, `spendUsd: 0`); no action — you are billed $0 |
| Run stops before charging | `maxSpendUsd` pre-flight guard tripped (would-be cost exceeds the per-run cap) | 0 rows, 0 charge by design; raise `maxSpendUsd` (≤29) or narrow the watchlist |
| `capTripped: true`, counts-only rows | $29/mo accrual ceiling reached | watching continues, baseline frozen, nothing lost — next run re-flags and re-bills |
| Input rejected, no fetch | schema gate (fewer than 3 domains/URLs, bad `watchId`, non-`daily` cadence) | fix to 3–10 domains, 3–30 URLs, `cadence: "daily"`; rejections happen pre-run at $0 |
| Walled store silently absent | bot wall / login wall / JS-only page skipped per policy | expected — never a guessed row; check `fetchPath` notes; drop or replace the URL |

### FAQ + legality

**Does this change my store or anyone's data?** No — read-only. The Actor fetches public policy pages and writes rows to your own private dataset; it edits nothing, anywhere.

**How much will one watch cost?** See the worked math above: quiet days $0, each verified change $0.15, worst case $29/mo. A 2-change day is $0.30.

**What are the input limits?** 3–10 competitor domains and 3–30 policy URLs per run, `cadence` fixed to `daily`, per-run guard $0.15–$29 (default $29).

**What happens behind login walls or bot walls?** The page is skipped and stays quiet — never a guessed row, never a bypass attempt, never billed.

**Does it process personal data (GDPR)?** No. It reads public shipping/returns/cart policy text only — no accounts, no personal data collected, stored, or sold. Each run's dataset is private to that run's owner.

**Is this affiliated with the stores it reads?** No. Store names belong to their owners; no affiliation, endorsement, or sponsorship is implied. Monitor only pages you are allowed to watch, and respect each site's Terms of Use and robots directives.

### Other Actors you might need

No sibling actors from this publisher yet — this is the only listing. Wrong-fit pointers:

| need | where to look |
|---|---|
| One-off single-page fetch (no watch, no change rows) | Store search → any generic web-scraper actor |
| Full product-catalog scrape (prices, variants, images) | Store search → product/catalog scraper actors |
| Saved runnable configs (smoke, DTC watch, cap edge) | This Actor's **Example tasks** tab after listing |

### Changelog + support

[Changelog](./CHANGELOG.md) — 0.1 (2026-10-02): adoption baseline, daily DTC promise watch at $0.15/verified row, $29/mo cap, $0.15 floor, quiet runs $0. Questions: the Store listing's **Issues tab**.

# Changelog

This Actor's version history is a separate document: https://apify.com/steadyworks/shipping-policy-change-monitor/changelog.md

# Actor input Schema

## `cadence` (type: `string`):

Daily watch cadence. Daily is the only accepted value.

## `checkedAt` (type: `string`):

Optional run timestamp (ISO-8601). Omit to use the current time.

## `competitorPolicyUrls` (type: `array`):

Shipping-policy, returns and cart pages across 3-10 shops. Max 30 pages.

## `competitors` (type: `array`):

Watched shop domains, 3-10 shops.

## `computeCapUsd` (type: `number`):

Compute cap, 0-39 USD. Caps compute spend for the run.

## `maxSpendUsd` (type: `number`):

Per-run spend guard, 0.15-29 USD (default 29). A run that would bill past the cap stops instead - billed rows stand. A separate $29 monthly total cap also applies: past $29, extra changes are counted but not billed.

## `capMode` (type: `string`):

Completeness mode: capped (default) stays within the per-run spend guard plus the $29 monthly room. complete-input processes the entire watchlist in one manual run: the worst case is quoted before any charge, never above $6.00 (40 rows = 10 shops x 4 change types); above $6.00 it stays capped; schedules and task runs always run capped; monthly $29 room and Max total charge still apply; extra rows are counted but not billed.

## `secondRunObservations` (type: `array`):

Optional demo replay only: second-run observations \[{store, freeThreshold?, shipFees?, deliveryWindowText?, returnsDays?, policyHash?, evidenceUrl?, fetchedAt?}]. Omit for a first check (zero rows, $0).

## `seededBaseline` (type: `object`):

Optional demo replay only: starting per-shop baseline {<shop>: {freeThreshold, shipFees, deliveryWindowText, returnsDays, policyHash}}. Omit for a first check (zero rows, $0).

## `synthetic` (type: `boolean`):

Marks demo input. Always true for demo runs.

## `watchId` (type: `string`):

Watch key: lowercase letters, digits, dashes, max 64 chars. Use a fresh value per watch.

## Actor input object example

```json
{
  "cadence": "daily",
  "checkedAt": "2026-10-01T12:00:00Z",
  "competitorPolicyUrls": [
    "https://shop-a.example.com/shipping",
    "https://shop-a.example.com/returns",
    "https://shop-a.example.com/cart",
    "https://shop-b.example.com/shipping",
    "https://shop-b.example.com/returns",
    "https://shop-b.example.com/cart",
    "https://shop-c.example.com/shipping",
    "https://shop-c.example.com/returns",
    "https://shop-c.example.com/cart"
  ],
  "competitors": [
    "shop-a.example.com",
    "shop-b.example.com",
    "shop-c.example.com"
  ],
  "computeCapUsd": 39,
  "maxSpendUsd": 29,
  "capMode": "capped",
  "secondRunObservations": [
    {
      "evidenceUrl": "https://shop-a.example.com/shipping",
      "freeThreshold": "Free shipping on orders over $75.",
      "store": "shop-a.example.com"
    }
  ],
  "seededBaseline": {
    "shop-a.example.com": {
      "deliveryWindowText": "Delivery in 3-5 business days.",
      "freeThreshold": "Free shipping on orders over $50.",
      "policyHash": "a1b2c3",
      "returnsDays": "30-day returns.",
      "shipFees": "Standard $4.95."
    }
  },
  "synthetic": true,
  "watchId": "shipping-watch-demo-01"
}
```

# Actor output Schema

## `output-record` (type: `string`):

Run summary (rows, meter report, billed rows, spend, suppressed rows, cap-trip, notice) as the OUTPUT record in the default key-value store. Chaining starts here, then follows the evidence link per row.

## `run-summary` (type: `string`):

One item per run: run summary with nested verified promise-change rows (shop, change type, was, now, evidence link, checked time, notice) and the meter report. Switch to the promise-changes view for one-row-per-change.

# 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 = {
    "cadence": "daily",
    "competitorPolicyUrls": [
        "https://shop-a.example.com/shipping",
        "https://shop-a.example.com/returns",
        "https://shop-a.example.com/cart",
        "https://shop-b.example.com/shipping",
        "https://shop-b.example.com/returns",
        "https://shop-b.example.com/cart",
        "https://shop-c.example.com/shipping",
        "https://shop-c.example.com/returns",
        "https://shop-c.example.com/cart"
    ],
    "competitors": [
        "shop-a.example.com",
        "shop-b.example.com",
        "shop-c.example.com"
    ],
    "computeCapUsd": 39,
    "maxSpendUsd": 29,
    "capMode": "capped",
    "synthetic": true,
    "watchId": "shipping-watch-demo-01"
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyworks/shipping-policy-change-monitor").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 = {
    "cadence": "daily",
    "competitorPolicyUrls": [
        "https://shop-a.example.com/shipping",
        "https://shop-a.example.com/returns",
        "https://shop-a.example.com/cart",
        "https://shop-b.example.com/shipping",
        "https://shop-b.example.com/returns",
        "https://shop-b.example.com/cart",
        "https://shop-c.example.com/shipping",
        "https://shop-c.example.com/returns",
        "https://shop-c.example.com/cart",
    ],
    "competitors": [
        "shop-a.example.com",
        "shop-b.example.com",
        "shop-c.example.com",
    ],
    "computeCapUsd": 39,
    "maxSpendUsd": 29,
    "capMode": "capped",
    "synthetic": True,
    "watchId": "shipping-watch-demo-01",
}

# Run the Actor and wait for it to finish
run = client.actor("steadyworks/shipping-policy-change-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "cadence": "daily",
  "competitorPolicyUrls": [
    "https://shop-a.example.com/shipping",
    "https://shop-a.example.com/returns",
    "https://shop-a.example.com/cart",
    "https://shop-b.example.com/shipping",
    "https://shop-b.example.com/returns",
    "https://shop-b.example.com/cart",
    "https://shop-c.example.com/shipping",
    "https://shop-c.example.com/returns",
    "https://shop-c.example.com/cart"
  ],
  "competitors": [
    "shop-a.example.com",
    "shop-b.example.com",
    "shop-c.example.com"
  ],
  "computeCapUsd": 39,
  "maxSpendUsd": 29,
  "capMode": "capped",
  "synthetic": true,
  "watchId": "shipping-watch-demo-01"
}' |
apify call steadyworks/shipping-policy-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyworks/shipping-policy-change-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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