A native Attio app that syncs Instantly.ai cold-email campaign events into your Attio CRM — in real time, with no external server to host.
When Instantly fires a webhook (email sent, opened, clicked, replied, meeting booked, …), this app receives it inside Attio, upserts the matching Person by email, stamps campaign engagement attributes, logs replies as Notes, and advances (or creates) the associated Deal — without ever regressing a deal that has already progressed.
Instantly campaign event ──webhook──▶ Attio app handler ──▶ People (upsert + engagement attrs)
(sent/opened/clicked/ (src/webhooks/ Notes (reply bodies)
replied/meeting/…) instantly.webhook.ts) Deals (stage advance / create)
The webhook handler runs on Attio's own infrastructure as a .webhook.ts entry
point. There is no server to deploy, no relay to babysit, no second set of
credentials in flight — Attio receives Instantly's POST directly and writes to
the CRM with the app-scoped token it injects at runtime. Connecting Instantly in
the workspace UI auto-registers the webhook; disconnecting tears it down.
| Target | What happens |
|---|---|
| People | Upserted by email_addresses. Stamps instantly_status, instantly_campaign_*, instantly_current_step/variant, and per-event timestamps (instantly_opened_at, instantly_replied_at, …). Enriches name / phone from merged lead fields. |
| Notes | On replies — the reply subject + body + a deep link back to the Instantly unibox thread. |
| Deals | Strong signals (meeting booked/completed) create a deal if none exists; weaker signals (reply, interest) advance an existing deal. A monotonic stage rank guarantees an out-of-order event never moves a deal backwards. |
See docs/EVENT-MAPPING.md for the full event → outcome table.
npm install
cp .env.example .env # add an Attio API key (for the setup script only)
export $(grep -v '^#' .env | xargs)
python3 setup/create-attributes.py --apply # provision the instantly_* attributes
# edit src/config.ts → your deal-owner member id + your funnel stage names
npm run dev # local Attio dev runtimeThen connect Instantly in your Attio workspace settings. Full instructions in
SETUP.md; how to verify it end-to-end in docs/TESTING.md.
Everything specific to your workspace lives in src/config.ts:
DEAL_OWNER_MEMBER_ID— the workspace member who owns auto-created dealsDEAL_STAGES_LOW_TO_HIGH— your Deals funnel, in order (drives the no-regression rank)DEAL_BY_EVENT— which Instantly events create vs. advance deals, and to which stage
Nothing else in the codebase hardcodes a workspace value.
SETUP.md— install, provision attributes, configure, connect Instantlydocs/TESTING.md— verify your own environment (offline tests → live self-test)docs/EVENT-MAPPING.md— every Instantly event and what it writesdocs/ARCHITECTURE.md— how it works, and the design decisions behind it
- One-way: Instantly → Attio. It does not push Attio changes back to Instantly.
- People + Deals only (v1). No Companies/Workspaces objects yet.
- Requires the custom
instantly_*attributes fromsetup/create-attributes.py.
MIT — see LICENSE.