Ingest CRM records from Salesforce sObjects and SOQL queries into Semantica’s KG pipeline.
Extract Accounts, Contacts, Opportunities, and custom objects from Salesforce into Semantica with username/password/security-token, JWT bearer, or session-based authentication.
from semantica.ingest import SalesforceIngestorimport osingestor = SalesforceIngestor( username=os.getenv("SALESFORCE_USERNAME"), password=os.getenv("SALESFORCE_PASSWORD"), security_token=os.getenv("SALESFORCE_SECURITY_TOKEN"), domain=os.getenv("SALESFORCE_DOMAIN", "login"), # "test" for sandbox)data = ingestor.ingest_sobject("Account", fields=["Id", "Name", "Industry"], limit=1000)print(f"Retrieved {data.row_count} of {data.total_size} matching records")print(f"Columns: {data.columns}")
Use environment variables (or a .env file with python-dotenv) to keep credentials out of source code. SalesforceIngestor() with no arguments reads from SALESFORCE_* environment variables automatically.
The standard server-side flow. The security token is appended to the
password during Salesforce SOAP login. Generate or reset it under
Settings → My Personal Information → Reset My Security Token.
import osfrom semantica.ingest import SalesforceIngestoringestor = SalesforceIngestor( username=os.getenv("SALESFORCE_USERNAME"), consumer_key=os.getenv("SALESFORCE_CONSUMER_KEY"), privatekey_file=os.getenv("SALESFORCE_PRIVATE_KEY_FILE"), domain="login", # or "test" for sandbox)
The JWT bearer flow authenticates with a signed token — no password
is transmitted. Ideal for server-to-server integrations and CI/CD
pipelines. Requires a Salesforce connected app configured with
Use digital signatures and the pre-authorised user listed under
Manage → Profiles / Permission Sets.If you prefer to pass the key material as a string instead of a file
path, use SALESFORCE_PRIVATE_KEY (the PEM contents) in place of
SALESFORCE_PRIVATE_KEY_FILE.
Use this when your environment already manages the OAuth token
lifecycle (e.g. a connected app obtaining tokens via the web-server
or device flow). Pass the access token as session_id and the full
instance URL (e.g. https://myorg.my.salesforce.com) as
instance_url.
data = ingestor.ingest_sobject( "Account", fields=["Id", "Name", "Industry", "AnnualRevenue", "BillingCity"], where="Type = 'Customer' AND AnnualRevenue > 1000000", order_by="Name ASC", limit=5000,)print(f"Retrieved {data.row_count} of {data.total_size} matching records")
data.row_count is the number of records in data.data (i.e. what was actually returned after any limit). data.total_size is Salesforce’s totalSize — the number of records matching the query before the limit. Compare them to know whether you got all results.
When fields is omitted, all selectable fields are fetched via describe()
(one extra API call). Compound address and geolocation fields (type=address,
type=location) are automatically excluded — select their components
(BillingStreet, BillingCity, Location__Latitude__s, …) individually if
you need them.
Pass any valid SOQL query verbatim — pagination is handled automatically:
data = ingestor.ingest_query(""" SELECT Id, Name, StageName, Amount, CloseDate, Account.Name, Owner.Name FROM Opportunity WHERE IsClosed = false ORDER BY CloseDate ASC""")print(f"Open opportunities: {data.row_count}")
The query is passed to the Salesforce REST API unchanged. The caller is
responsible for SOQL correctness and safety.
ingest_query does not validate or sanitise the SOQL string. Use
ingest_sobject (which validates sObject names, field names, and WHERE/ORDER
BY fragments) when building queries from application-controlled inputs.
# List all accessible sObjectssobject_names = ingestor.list_sobjects()print(sobject_names[:10]) # ["Account", "Case", "Contact", ...]# Inspect fields for a specific sObjectschema = ingestor.get_sobject_schema("Account")for field in schema["fields"]: print(f"{field['name']}: {field['type']} (nillable={field['nillable']})")
Prefer the context manager for long-running jobs — it opens one connection on
entry and closes it on exit, so every ingestion call inside the with block
reuses the same authenticated session:
with SalesforceIngestor( username=os.getenv("SALESFORCE_USERNAME"), password=os.getenv("SALESFORCE_PASSWORD"), security_token=os.getenv("SALESFORCE_SECURITY_TOKEN"),) as sf: accounts = sf.ingest_sobject("Account", limit=10000) contacts = sf.ingest_sobject("Contact", limit=10000) sobjects = sf.list_sobjects()