Dataset Sync to Notion, Slack, Supabase & CRM — with Dedupe avatar

Dataset Sync to Notion, Slack, Supabase & CRM — with Dedupe

Pricing

from $3.50 / 1,000 row written to your destinations

Go to Apify Store
Dataset Sync to Notion, Slack, Supabase & CRM — with Dedupe

Dataset Sync to Notion, Slack, Supabase & CRM — with Dedupe

Send any Apify dataset to Notion, Slack, Supabase, HubSpot or any MCP-connected app — writing only the rows that aren't already there. Deterministic deduplication against the destination, explicit field mapping, no LLM and no token cost. Pay only for rows actually written.

Pricing

from $3.50 / 1,000 row written to your destinations

Rating

0.0

(0)

Developer

K O

K O

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Send any Apify dataset straight into the app your team actually works in — and write only the rows that aren't already there.

Scrapers leave you with a dataset. Getting that dataset into Notion, Supabase, HubSpot or Slack is the part that stays manual: export a CSV, open the destination, figure out what's already in there, paste the rest. Do it on a schedule and you either re-import duplicates or you hand-check every row.

This Actor does that last mile in one run, and it deduplicates against the destination itself — not just against its own history.

Why this one and not an AI uploader

This ActorLLM-agent uploaders
BehaviorDeterministic — same input, same writesNon-deterministic
Duplicate rowsSkipped by key, never writtenNo guarantee
CostFlat per synced rowPer token, scales with data size
Wrong writes to your CRMNot possible — explicit field mapPossible

There's no model in the loop. It reads what's at the destination, compares keys, and writes the difference.

How it works

  1. Connect your app (Notion, Slack, Supabase, HubSpot, …) under Integrations in Apify Console.
  2. Run this Actor in list-tools mode to see what that connector can do.
  3. Run it in sync mode with the tool name, your dataset ID, and a dedupe key.

Credentials never reach this Actor. It talks to the destination through Apify's MCP proxy, which holds the real tokens and enforces that the Actor can only call the tools it declared.

Quick start

Step 1 — discover the destination's tools

{
"destination": "<your connector>",
"mode": "list-tools"
}

The dataset comes back with every tool name, description and input schema. Pick the one that creates a record.

Step 2 — sync

{
"destination": "<your connector>",
"mode": "sync",
"datasetId": "<dataset from any Actor>",
"writeTool": "create_page",
"readTool": "query_database",
"readToolArgs": { "database_id": "abc123" },
"writeToolExtraArgs": { "database_id": "abc123" },
"dedupeKey": "licenseNumber",
"fieldMap": { "title": "companyName", "phone": "contact.phone" }
}

Set dryRun: true first — it reports exactly which rows it would write, so you can check your field mapping before anything lands in a live database.

Examples

Google Maps results → Notion CRM, no repeats

Point datasetId at any Google Maps scraper run, set dedupeKey to placeId, and schedule it. New places show up in Notion; ones you already have are skipped.

New leads → Supabase table

writeTool: "insert", readTool: "select", readToolArgs: { "table": "leads" }, dedupeKey: "email".

Only genuinely new items → Slack

writeTool: "send_message", writeToolExtraArgs: { "channel": "#leads" }, dedupeKey: "url". Because dedupe runs first, the channel only ever sees things nobody has posted before.

Input

FieldRequiredDescription
destinationyesThe MCP connector to write to
modesync (default) or list-tools
datasetIdfor syncSource Apify dataset — any Actor's
writeToolfor syncDestination tool called once per new row
dedupeKeyField identifying a record. Dot paths supported. Default id
readToolTool that lists existing records — enables true destination dedupe
readToolArgsJSON args for the read tool
fieldMapDestination arg name → source field path. Empty passes rows through
writeToolExtraArgsConstant args merged into every write
maxItemsCap on rows written per run. Default 1000
dryRunPlan the sync, write nothing
writeKeylessAlso write rows missing the dedupe key. Default off

Output

One row per record handled:

{ "synced": true, "key": "roc-123456", "args": { "title": "Acme Builders", "phone": "480-555-0100" } }

Failures are recorded rather than silently dropped, and one rejected row never aborts the rest of the run:

{ "synced": false, "key": "roc-123457", "error": "Destination tool \"create_page\" returned an error: ..." }

Dedupe, precisely

  • With readTool — reads current destination state each run. Safe even if records were added by someone else, or the Actor's own history was lost.
  • Without readTool — falls back to remembering keys it wrote in previous runs.
  • Keys are trimmed and case-folded, so "Acme LLC " and "acme llc" are one record.
  • Rows duplicated inside the source are collapsed too.
  • Rows with no key are skipped by default, because writing an unidentifiable row is how duplicates get created.

Pricing

$5 per 1,000 rows actually written to the destination — and nothing else.

There is no per-run fee. Duplicates, skipped rows, dry runs, and scheduled runs over a source that hasn't changed are all free. You pay for records that landed, or you pay nothing.

FAQ

Does this Actor see my Notion/Slack token? No. Apify's MCP proxy holds the credentials and attaches them to outbound calls.

Which apps work? Any service exposed as an MCP connector in your Apify account.

What if I don't know my destination's tool names? Run list-tools mode.

Can an AI agent call this? Yes — it's exposed through the Apify MCP server. list-tools then sync is a natural two-step for an agent.

What if the destination rejects a row? It's logged to the dataset with the error, and the run continues.