# Business Snapshot Audit & Diff (`immemorial_sarinda/business-snapshot-audit-diff`) Actor

Audit supplied business JSON snapshots for quality issues and exact-ID changes. Set Run options: 512 MB, 60 seconds, restart Off, maximum charge USD 0.11. USD 0.10 per completion receipt; no scraping.

- **URL**: https://apify.com/immemorial_sarinda/business-snapshot-audit-diff.md
- **Developed by:** [Picknotes](https://apify.com/immemorial_sarinda) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.10 / completed report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Business Snapshot Audit & Diff

TLDR: Audit one or compare two supplied business JSON snapshots. No scraping or inferred closure. Start with the unchanged fictional demo, which may cost USD 0.10 per report completion receipt.

### What you get

Turn one or two authorized business JSON exports into a deterministic audit/change report. Review malformed records, duplicate IDs, observed rating/review-count changes and supplied closure-field changes. The Actor does not collect data, verify live listings, enrich records, or infer closure from absence.

The full JSON report is saved as OUTPUT in the run's default key-value store. A two-snapshot report includes an embedded diffCsv string. The default dataset contains at most one small completion receipt with schema/version, report SHA-256 and bounded counts; it does not contain the full report. A completed audit may contain issues or no usable matches.

### First run

- In Run options, use 512 MB memory, 60 seconds timeout and Restart on error Off. Enable a maximum total charge of USD 0.11; leave No limit Off. This version requires an explicit per-run cap greater than USD 0.10 and no more than USD 1.00. Missing, unlimited or out-of-range caps are rejected. Restoring example input can reset Run options, so check them again before starting.
- API callers: pass memory=512, timeout=60, restartOnError=false and maxTotalChargeUsd=0.11 as run query options, not as fields inside the input JSON. Use a fresh run. The Actor is configured for Limited permissions and standby Off.
- Choose the fixed fictional sample: demoFixture = synthetic-demo-v1. Keep its four supplied snapshot/time values exactly unchanged. nonConfidentialData must be present as a boolean; false is allowed only for this known sample. This demo can cost USD 0.10 per report.
- For your own data, choose demoFixture = own-data and explicitly set nonConfidentialData = true. Submit only authorized, non-confidential, non-personal business records. This acknowledgement does not detect personal information or establish source rights.
- Supply beforeJson as a JSON-array string and beforeObservedAt with an explicit timezone. For comparison, supply afterJson and afterObservedAt together, using a strictly later observation time. A single snapshot produces an audit without a diff.
- Editing the sample, omitting its after snapshot, or changing its times while demo mode is selected is rejected, even if the acknowledgement is true. Switch to own-data and explicitly acknowledge before submitting other data. Raw API input without demoFixture uses the own-data consent requirement.
- Open the run's key-value store OUTPUT for the report. Download that JSON and extract diffCsv if you need the comparison as CSV. The dataset item is the receipt.

### Scope and limits

- Seven retained input fields: placeId, title, totalScore, reviewsCount, permanentlyClosed, temporarilyClosed and scrapedAt. Other fields are stripped from the report, but Apify has already received the raw input.
- IDs match exactly and case-sensitively. Every occurrence of a duplicated ID is excluded from comparison. Unknown values stay unknown. A missing after record is labelled not_observed_in_after and does not prove closure. Supplied closure flags and timestamps are not independent verification.
- Each snapshot: at most 2 MiB UTF-8 and 10,000 rows. The complete input envelope is capped at 8 MiB. Additional nesting, token, row, string and value limits apply.
- The serialized report has a separate 24 MiB ceiling. Valid-size inputs can still exceed it. There is no partial, truncated or chunked report.
- Hosted input accepts JSON strings, not URLs, uploads, datasets or CSV. No fuzzy matching, scraping, recurring monitoring, demographic scoring, or LLM interpretation is performed.

### Price and failures

The configured price is USD 0.10 for one saved report completion receipt, charged through the single apify-default-dataset-item event. At most one receipt is appended per run, after OUTPUT is saved and its readback matches. There is no Actor-start event or customer platform-usage add-on in this pricing configuration. The fictional demo uses the same completion event and is not promised free.

Invalid input or a failure before receipt dispatch does not cause this code to append a receipt. An accepted receipt can still be charged if its acknowledgement is lost, later verification fails, or the run subsequently fails or is stopped. A FAILED, ABORTED or TIMED-OUT status does not guarantee zero charge or an automatic refund. A receipt is not an invoice or proof of settlement. Owner development runs use the owner's platform credits; separate storage/export operations can have normal platform costs.

### Data, access and retention

Apify stores raw INPUT before this code applies its field allowlist. OUTPUT can retain business IDs, titles, row references and issues; the receipt's hash/counts are not anonymization. Application logs use fixed categories, while platform logs and storage behavior are controlled by Apify.

Retention depends on your plan, settings and storage naming. This Actor does not configure access, name stores, delete data, or promise a fixed deletion date. Review [Apify storage retention](https://docs.apify.com/storage#data-retention) and your actual account settings before submitting data. Access also depends on account/resource permissions, collaborators and shared or signed links. Review [general resource access](https://docs.apify.com/account/collaboration/general-resource-access), and keep report and capability links private.

### Questions and troubleshooting

If the fixed demo is rejected, restore its exact snapshot/time values or switch to own-data with the explicit acknowledgement. For own-data validation errors, check the paired after fields, timestamps, JSON-array strings and size limits. A completed report with quality issues is a valid audit outcome.

Use the Actor's Issues tab for product questions. Share only non-confidential details you intend the developer to see: including a run link in an issue can grant the developer access to that run, input, logs and default storages. There is no promised response-time or uptime SLA, independent data-accuracy guarantee, automatic refund, or supported confidential-data workflow.

# Actor input Schema

## `demoFixture` (type: `string`):

Demo accepts only the exact bundled before/after sample and times. Any edit requires own-data mode and explicit acknowledgment. Demo uses the normal paid completion receipt and may cost USD 0.10; it is not free.

## `beforeJson` (type: `string`):

Paste a JSON array of business-level records. Maximum 2 MiB UTF-8, 10000 rows; further structural limits apply. No URLs or file uploads.

## `beforeObservedAt` (type: `string`):

ISO 8601 timestamp with explicit timezone. Supply both after fields together; after must be later.

## `afterJson` (type: `string`):

Paste a JSON array of business-level records. Maximum 2 MiB UTF-8, 10000 rows; further structural limits apply. No URLs or file uploads.

## `afterObservedAt` (type: `string`):

ISO 8601 timestamp with explicit timezone. Supply both after fields together; after must be later.

## `nonConfidentialData` (type: `boolean`):

Required true for your own data. False is allowed only for the unchanged bundled fictional demo selected above. No personal/confidential data or secrets; Apify stores raw INPUT before processing under its account retention/access settings.

## Actor input object example

```json
{
  "demoFixture": "synthetic-demo-v1",
  "beforeJson": "[\n  {\"placeId\":\"SYNTH_CAFE_001\",\"title\":\"Example Cedar Cafe\",\"totalScore\":4.1,\"reviewsCount\":100,\"permanentlyClosed\":false,\"temporarilyClosed\":false,\"scrapedAt\":\"2026-10-01T10:00:00Z\",\"phone\":\"SYNTHETIC-CONTACT-STRIPPED\",\"reviews\":[{\"name\":\"SYNTHETIC-REVIEWER-STRIPPED\"}]},\n  {\"placeId\":\"SYNTH_SHOP_002\",\"title\":\"Example Juniper Shop\",\"totalScore\":4.6,\"reviewsCount\":40,\"permanentlyClosed\":false,\"temporarilyClosed\":false},\n  {\"placeId\":\"SYNTH_MUSEUM_003\",\"title\":\"Example Maple Museum\",\"totalScore\":4.8,\"reviewsCount\":200,\"permanentlyClosed\":false,\"temporarilyClosed\":false},\n  {\"placeId\":\"SYNTH_DUP_004\",\"title\":\"Example Duplicate A\",\"totalScore\":3.8,\"reviewsCount\":50},\n  {\"placeId\":\"SYNTH_DUP_004\",\"title\":\"Example Duplicate B\",\"totalScore\":3.9,\"reviewsCount\":51},\n  {\"title\":\"Example Missing ID\",\"totalScore\":4.0},\n  {\"placeId\":\"SYNTH_BAD_005\",\"title\":\"Example Invalid Rating\",\"totalScore\":\"five\",\"reviewsCount\":true}\n]\n",
  "beforeObservedAt": "2026-10-01T10:00:00Z",
  "afterJson": "[\n  {\"placeId\":\"SYNTH_CAFE_001\",\"title\":\"Example Cedar Cafe\",\"totalScore\":4.3,\"reviewsCount\":108,\"permanentlyClosed\":false,\"temporarilyClosed\":false,\"scrapedAt\":\"2026-10-08T10:00:00Z\"},\n  {\"placeId\":\"SYNTH_SHOP_002\",\"title\":\"Example Juniper Shop\",\"totalScore\":4.6,\"reviewsCount\":39,\"permanentlyClosed\":true,\"temporarilyClosed\":false},\n  {\"placeId\":\"SYNTH_NEW_006\",\"title\":\"=SYNTHETIC_FORMULA_TEST()\",\"totalScore\":4.0,\"reviewsCount\":5,\"permanentlyClosed\":false,\"temporarilyClosed\":false},\n  {\"placeId\":\"SYNTH_DUP_004\",\"title\":\"Example Duplicate A\",\"totalScore\":4.0,\"reviewsCount\":52},\n  {\"placeId\":\"SYNTH_BAD_005\",\"title\":\"Example Invalid Rating\",\"totalScore\":4.0,\"reviewsCount\":3}\n]\n",
  "afterObservedAt": "2026-10-08T10:00:00Z",
  "nonConfidentialData": false
}
```

# Actor output Schema

## `report` (type: `string`):

No description

# 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 = {
    "demoFixture": "synthetic-demo-v1",
    "beforeJson": `[
  {"placeId":"SYNTH_CAFE_001","title":"Example Cedar Cafe","totalScore":4.1,"reviewsCount":100,"permanentlyClosed":false,"temporarilyClosed":false,"scrapedAt":"2026-10-01T10:00:00Z","phone":"SYNTHETIC-CONTACT-STRIPPED","reviews":[{"name":"SYNTHETIC-REVIEWER-STRIPPED"}]},
  {"placeId":"SYNTH_SHOP_002","title":"Example Juniper Shop","totalScore":4.6,"reviewsCount":40,"permanentlyClosed":false,"temporarilyClosed":false},
  {"placeId":"SYNTH_MUSEUM_003","title":"Example Maple Museum","totalScore":4.8,"reviewsCount":200,"permanentlyClosed":false,"temporarilyClosed":false},
  {"placeId":"SYNTH_DUP_004","title":"Example Duplicate A","totalScore":3.8,"reviewsCount":50},
  {"placeId":"SYNTH_DUP_004","title":"Example Duplicate B","totalScore":3.9,"reviewsCount":51},
  {"title":"Example Missing ID","totalScore":4.0},
  {"placeId":"SYNTH_BAD_005","title":"Example Invalid Rating","totalScore":"five","reviewsCount":true}
]`,
    "beforeObservedAt": "2026-10-01T10:00:00Z",
    "afterJson": `[
  {"placeId":"SYNTH_CAFE_001","title":"Example Cedar Cafe","totalScore":4.3,"reviewsCount":108,"permanentlyClosed":false,"temporarilyClosed":false,"scrapedAt":"2026-10-08T10:00:00Z"},
  {"placeId":"SYNTH_SHOP_002","title":"Example Juniper Shop","totalScore":4.6,"reviewsCount":39,"permanentlyClosed":true,"temporarilyClosed":false},
  {"placeId":"SYNTH_NEW_006","title":"=SYNTHETIC_FORMULA_TEST()","totalScore":4.0,"reviewsCount":5,"permanentlyClosed":false,"temporarilyClosed":false},
  {"placeId":"SYNTH_DUP_004","title":"Example Duplicate A","totalScore":4.0,"reviewsCount":52},
  {"placeId":"SYNTH_BAD_005","title":"Example Invalid Rating","totalScore":4.0,"reviewsCount":3}
]`,
    "afterObservedAt": "2026-10-08T10:00:00Z"
};

// Run the Actor and wait for it to finish
const run = await client.actor("immemorial_sarinda/business-snapshot-audit-diff").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 = {
    "demoFixture": "synthetic-demo-v1",
    "beforeJson": """[
  {\"placeId\":\"SYNTH_CAFE_001\",\"title\":\"Example Cedar Cafe\",\"totalScore\":4.1,\"reviewsCount\":100,\"permanentlyClosed\":false,\"temporarilyClosed\":false,\"scrapedAt\":\"2026-10-01T10:00:00Z\",\"phone\":\"SYNTHETIC-CONTACT-STRIPPED\",\"reviews\":[{\"name\":\"SYNTHETIC-REVIEWER-STRIPPED\"}]},
  {\"placeId\":\"SYNTH_SHOP_002\",\"title\":\"Example Juniper Shop\",\"totalScore\":4.6,\"reviewsCount\":40,\"permanentlyClosed\":false,\"temporarilyClosed\":false},
  {\"placeId\":\"SYNTH_MUSEUM_003\",\"title\":\"Example Maple Museum\",\"totalScore\":4.8,\"reviewsCount\":200,\"permanentlyClosed\":false,\"temporarilyClosed\":false},
  {\"placeId\":\"SYNTH_DUP_004\",\"title\":\"Example Duplicate A\",\"totalScore\":3.8,\"reviewsCount\":50},
  {\"placeId\":\"SYNTH_DUP_004\",\"title\":\"Example Duplicate B\",\"totalScore\":3.9,\"reviewsCount\":51},
  {\"title\":\"Example Missing ID\",\"totalScore\":4.0},
  {\"placeId\":\"SYNTH_BAD_005\",\"title\":\"Example Invalid Rating\",\"totalScore\":\"five\",\"reviewsCount\":true}
]
""",
    "beforeObservedAt": "2026-10-01T10:00:00Z",
    "afterJson": """[
  {\"placeId\":\"SYNTH_CAFE_001\",\"title\":\"Example Cedar Cafe\",\"totalScore\":4.3,\"reviewsCount\":108,\"permanentlyClosed\":false,\"temporarilyClosed\":false,\"scrapedAt\":\"2026-10-08T10:00:00Z\"},
  {\"placeId\":\"SYNTH_SHOP_002\",\"title\":\"Example Juniper Shop\",\"totalScore\":4.6,\"reviewsCount\":39,\"permanentlyClosed\":true,\"temporarilyClosed\":false},
  {\"placeId\":\"SYNTH_NEW_006\",\"title\":\"=SYNTHETIC_FORMULA_TEST()\",\"totalScore\":4.0,\"reviewsCount\":5,\"permanentlyClosed\":false,\"temporarilyClosed\":false},
  {\"placeId\":\"SYNTH_DUP_004\",\"title\":\"Example Duplicate A\",\"totalScore\":4.0,\"reviewsCount\":52},
  {\"placeId\":\"SYNTH_BAD_005\",\"title\":\"Example Invalid Rating\",\"totalScore\":4.0,\"reviewsCount\":3}
]
""",
    "afterObservedAt": "2026-10-08T10:00:00Z",
}

# Run the Actor and wait for it to finish
run = client.actor("immemorial_sarinda/business-snapshot-audit-diff").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 '{
  "demoFixture": "synthetic-demo-v1",
  "beforeJson": "[\\n  {\\"placeId\\":\\"SYNTH_CAFE_001\\",\\"title\\":\\"Example Cedar Cafe\\",\\"totalScore\\":4.1,\\"reviewsCount\\":100,\\"permanentlyClosed\\":false,\\"temporarilyClosed\\":false,\\"scrapedAt\\":\\"2026-10-01T10:00:00Z\\",\\"phone\\":\\"SYNTHETIC-CONTACT-STRIPPED\\",\\"reviews\\":[{\\"name\\":\\"SYNTHETIC-REVIEWER-STRIPPED\\"}]},\\n  {\\"placeId\\":\\"SYNTH_SHOP_002\\",\\"title\\":\\"Example Juniper Shop\\",\\"totalScore\\":4.6,\\"reviewsCount\\":40,\\"permanentlyClosed\\":false,\\"temporarilyClosed\\":false},\\n  {\\"placeId\\":\\"SYNTH_MUSEUM_003\\",\\"title\\":\\"Example Maple Museum\\",\\"totalScore\\":4.8,\\"reviewsCount\\":200,\\"permanentlyClosed\\":false,\\"temporarilyClosed\\":false},\\n  {\\"placeId\\":\\"SYNTH_DUP_004\\",\\"title\\":\\"Example Duplicate A\\",\\"totalScore\\":3.8,\\"reviewsCount\\":50},\\n  {\\"placeId\\":\\"SYNTH_DUP_004\\",\\"title\\":\\"Example Duplicate B\\",\\"totalScore\\":3.9,\\"reviewsCount\\":51},\\n  {\\"title\\":\\"Example Missing ID\\",\\"totalScore\\":4.0},\\n  {\\"placeId\\":\\"SYNTH_BAD_005\\",\\"title\\":\\"Example Invalid Rating\\",\\"totalScore\\":\\"five\\",\\"reviewsCount\\":true}\\n]\\n",
  "beforeObservedAt": "2026-10-01T10:00:00Z",
  "afterJson": "[\\n  {\\"placeId\\":\\"SYNTH_CAFE_001\\",\\"title\\":\\"Example Cedar Cafe\\",\\"totalScore\\":4.3,\\"reviewsCount\\":108,\\"permanentlyClosed\\":false,\\"temporarilyClosed\\":false,\\"scrapedAt\\":\\"2026-10-08T10:00:00Z\\"},\\n  {\\"placeId\\":\\"SYNTH_SHOP_002\\",\\"title\\":\\"Example Juniper Shop\\",\\"totalScore\\":4.6,\\"reviewsCount\\":39,\\"permanentlyClosed\\":true,\\"temporarilyClosed\\":false},\\n  {\\"placeId\\":\\"SYNTH_NEW_006\\",\\"title\\":\\"=SYNTHETIC_FORMULA_TEST()\\",\\"totalScore\\":4.0,\\"reviewsCount\\":5,\\"permanentlyClosed\\":false,\\"temporarilyClosed\\":false},\\n  {\\"placeId\\":\\"SYNTH_DUP_004\\",\\"title\\":\\"Example Duplicate A\\",\\"totalScore\\":4.0,\\"reviewsCount\\":52},\\n  {\\"placeId\\":\\"SYNTH_BAD_005\\",\\"title\\":\\"Example Invalid Rating\\",\\"totalScore\\":4.0,\\"reviewsCount\\":3}\\n]\\n",
  "afterObservedAt": "2026-10-08T10:00:00Z"
}' |
apify call immemorial_sarinda/business-snapshot-audit-diff --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,immemorial_sarinda/business-snapshot-audit-diff"
        }
    }
}
```

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/olQnYL3v7Mdc2sHob/builds/eF917OUOHy37fbrb8/openapi.json
