From 616bde80e3297649cfdd087b825d9d09064566a8 Mon Sep 17 00:00:00 2001 From: shivamlalakiya Date: Sun, 19 Jul 2026 12:32:11 -0500 Subject: [PATCH 1/2] Add Salesforce NPSP integration --- integrations/salesforce-npsp.md | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 integrations/salesforce-npsp.md diff --git a/integrations/salesforce-npsp.md b/integrations/salesforce-npsp.md new file mode 100644 index 00000000..86cdf4ec --- /dev/null +++ b/integrations/salesforce-npsp.md @@ -0,0 +1,89 @@ +--- +layout: integration +name: Salesforce NPSP +description: Ingest Salesforce Nonprofit Success Pack (NPSP) donor records, gift histories, and engagement metrics as Documents for RAG. +authors: + - name: Shivam Ashokbhai Lalakiya + socials: + github: shivamlalakiya +pypi: https://pypi.org/project/haystack-salesforce-npsp +repo: https://github.com/PhilanthroPy-Project/salesforce-npsp-integrations +type: Data Ingestion +report_issue: https://github.com/PhilanthroPy-Project/salesforce-npsp-integrations/issues +version: Haystack 2.0 +toc: true +--- + +### Table of Contents + +- [Overview](#overview) +- [Installation](#installation) +- [Usage](#usage) +- [License](#license) + +## Overview + +`haystack-salesforce-npsp` provides a Haystack 2.x component, +`SalesforceNPSPFetcher`, that ingests donor data from Salesforce +[Nonprofit Success Pack (NPSP)](https://www.salesforce.org/nonprofit/nonprofit-success-pack/) +organizations as Haystack `Document`s — no Airbyte and no CDK required. + +Unlike a generic Salesforce connector that returns raw JSON, this component is +**NPSP-aware**: it understands the `npo02__` and `npsp__` field prefixes and +produces human-readable donor profiles (lifetime giving, gift history, soft +credits, planned giving, engagement) that an LLM can reason over directly. An +optional `affinity_score_fn` injects an ML-derived donor propensity score into +each document's metadata at fetch time. + +## Installation + +```bash +pip install haystack-salesforce-npsp +``` + +Set your Salesforce credentials as environment variables: + +```bash +export SF_USERNAME="you@yourorg.org" +export SF_PASSWORD="your_password" +export SF_TOKEN="your_security_token" +``` + +## Usage + +Fetch donors on their own: + +```python +from haystack_salesforce_npsp import SalesforceNPSPFetcher + +fetcher = SalesforceNPSPFetcher( + soql_filter="npo02__TotalOppAmount__c > 5000", + limit=500, +) +documents = fetcher.run()["documents"] +# documents[0].content -> narrative donor profile +# documents[0].meta -> {"donor_id": ..., "total_gift_amount": ..., "source": "salesforce_npsp", ...} +``` + +In an indexing pipeline: + +```python +from haystack import Pipeline +from haystack.components.embedders import SentenceTransformersDocumentEmbedder +from haystack.components.writers import DocumentWriter +from haystack.document_stores.in_memory import InMemoryDocumentStore +from haystack_salesforce_npsp import SalesforceNPSPFetcher + +store = InMemoryDocumentStore() +p = Pipeline() +p.add_component("fetch", SalesforceNPSPFetcher(soql_filter="npo02__TotalOppAmount__c > 5000")) +p.add_component("embed", SentenceTransformersDocumentEmbedder()) +p.add_component("write", DocumentWriter(document_store=store)) +p.connect("fetch.documents", "embed.documents") +p.connect("embed.documents", "write.documents") +p.run({}) +``` + +## License + +`haystack-salesforce-npsp` is distributed under the terms of the MIT license. From d1a834a9d315ebdcee7eefd033ce79776e1be998 Mon Sep 17 00:00:00 2001 From: shivamlalakiya Date: Thu, 13 Aug 2026 13:48:57 -0500 Subject: [PATCH 2/2] Address review: add logo, clarify Salesforce auth flow Adds a logo tile and a short note explaining the username-password- security-token flow is the standard simple-salesforce SOAP auth, per review feedback from @kacperlukawski. --- integrations/salesforce-npsp.md | 6 ++++++ logos/salesforce-npsp.png | Bin 0 -> 58540 bytes 2 files changed, 6 insertions(+) create mode 100644 logos/salesforce-npsp.png diff --git a/integrations/salesforce-npsp.md b/integrations/salesforce-npsp.md index 86cdf4ec..bf513e95 100644 --- a/integrations/salesforce-npsp.md +++ b/integrations/salesforce-npsp.md @@ -10,6 +10,7 @@ pypi: https://pypi.org/project/haystack-salesforce-npsp repo: https://github.com/PhilanthroPy-Project/salesforce-npsp-integrations type: Data Ingestion report_issue: https://github.com/PhilanthroPy-Project/salesforce-npsp-integrations/issues +logo: /logos/salesforce-npsp.png version: Haystack 2.0 toc: true --- @@ -49,6 +50,11 @@ export SF_PASSWORD="your_password" export SF_TOKEN="your_security_token" ``` +This is the standard SOAP username-password-security-token flow supported by +[`simple-salesforce`](https://github.com/simple-salesforce/simple-salesforce), +suited to trusted server-side ingestion jobs like this one. OAuth 2.0 support +may be added in a future release. + ## Usage Fetch donors on their own: diff --git a/logos/salesforce-npsp.png b/logos/salesforce-npsp.png new file mode 100644 index 0000000000000000000000000000000000000000..2f5d0f8e4fa7a88df4fab66029f369ada5595032 GIT binary patch literal 58540 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