Skip to content
Streamkap
Esc
navigateopen⌘Jpreview
On this page

Salesforce

Stream Salesforce objects into Streamkap with a service account (client credentials), or by connecting with Salesforce over OAuth

The Salesforce source pulls objects — accounts, contacts, opportunities, and more — out of your Salesforce org and streams them into Kafka topics, one topic per object. Records land flat in your destination like any other Streamkap source, so every existing destination consumes them unchanged.

How It Works

  1. Authentication — Streamkap connects to your org one of two ways. With Service account (client credentials) — the default — you create an External Client App in Salesforce and give Streamkap its Consumer Key and Consumer Secret; Streamkap reads your org as the app’s run-as user. With OAuth (Connect with Salesforce) you authorize Streamkap in a Salesforce consent screen and it syncs with the access you grant. See Authentication options.
  2. Incremental sync — On the first run each selected object is read in full. After that, the connector polls on a schedule and fetches only records whose SystemModstamp moved since the last poll, tracking a per-object cursor.
  3. Deletes — A periodic sweep finds records deleted in Salesforce and emits a delete marker (__deleted = true) so downstream sinks flip the row to deleted. The sweep depends on the Recycle Bin; a slower daily reconciliation pass backs it up for deletes that age out of that window — see Deletes and tombstones.
  4. API allocation — Salesforce enforces a rolling 24-hour API request allocation for the whole org. The connector paces itself to leave headroom for your other integrations (see Behavior & Limits).

Each object you select produces a topic named source_<id>.salesforce.<Object> — for example source_<id>.salesforce.Account. Object names are case-sensitive API names, so the topic carries the object’s API name exactly.

Authentication options

Streamkap authenticates the Salesforce source one of two ways. The Authentication dropdown on the Auth tab offers both; you choose when you create the connector.

Service account (client credentials)

The default — the form opens on this option. You create an External Client App in Salesforce and give Streamkap its Consumer Key and Consumer Secret; Streamkap reads your org as a fixed run-as user through the OAuth client-credentials flow. Choose it when the connection should belong to a service identity you control rather than to a person’s login, which is usually what a production integration needs. It is the more involved path: you build the app in Salesforce first (Salesforce Setup), then enter its credentials in Streamkap.

It is also the only path that takes your My Domain URL directly, so it is the one to use if your org’s My Domain policy blocks the standard Salesforce login host.

OAuth (Connect with Salesforce)

The quicker path, with nothing to create in Salesforce. You pick your org’s environmentProduction or Developer Edition, or Sandbox — then click Connect with Salesforce, approve Streamkap’s access in a Salesforce consent window, and the connection is established. There are no keys to create and none to paste. Streamkap syncs with the access the authorizing user granted and keeps that authorization refreshed on its own; if it is ever revoked or expires, the source prompts you to reconnect (see Reconnecting an OAuth connection).

Prerequisites

  • A Salesforce org.
  • A Streamkap workspace with permission to create source connectors.
  • For a service account: permission to create an External Client App in Setup, and a run-as user in that org with read access to every object you want to sync.
  • For Connect with Salesforce: a Salesforce login that can grant Streamkap read access to the objects you want to sync.

Salesforce Setup

1. Create an External Client App

  1. In Salesforce Setup, use Quick Find to search for External Client Apps Manager, and select it.
  2. Create a new external client app and give it a name (for example Streamkap).

2. Enable OAuth and the client-credentials flow

  1. From the app’s actions dropdown, select Edit Settings.
  2. In the OAuth Settings section, select Enable OAuth. The section expands.
  3. Select the OAuth scope that grants API access (the api scope). Streamkap only reads — it never writes to your org.
  4. Select Enable Client Credentials Flow.
  5. Save.

3. Assign the run-as user

  1. On the app, select Edit Policies.
  2. Under Client Credentials Flow, set Run As to the user Streamkap will read your org as.
  3. Save.

4. Grant the run-as user read access to your objects

Give the run-as user read access to every object you plan to select in Streamkap — through its profile, or through a permission set you assign to it. Both work; a permission set is easier to audit because it names the objects in one place.

Read access is enough. Streamkap never creates, updates, or deletes records in your org.

If you skip an object here, the source still saves — but that object fails on its first poll, and Salesforce’s error does not distinguish “missing permission” from “no such object”. Streamkap’s Test connection catches this before you save. See An object can’t be seen.

5. Copy the Consumer Key and Consumer Secret

  1. Open the app’s Settings tab and expand OAuth Settings.
  2. Open Consumer Key and Secret and copy both values.
  3. Keep them handy for the Streamkap setup below — treat the Consumer Secret like a password.

6. Find your My Domain URL

  1. In Salesforce Setup, use Quick Find to search for My Domain (under Company Settings).
  2. Copy your org’s My Domain URL. It looks like https://acme.my.salesforce.com.

Streamkap Setup

Follow these steps to configure your new connector:

1. Create the Source

2. Connection Settings (Auth tab)

  • Name: A name for your connector (for example salesforce-prod).
  • Authentication: How Streamkap authenticates — Service account (client credentials) (the default) or OAuth (Connect with Salesforce). See Authentication options. The rest of the form follows your choice.

Service account (client credentials)

Enter the credentials from your Salesforce Setup:

  • Consumer Key: The Consumer Key from your External Client App.
  • Consumer Secret: The Consumer Secret shown beside it. It is stored encrypted at rest and never shown again.

OAuth (Connect with Salesforce)

Pick the Salesforce environmentProduction or Developer Edition (preselected) or Sandbox — then click Connect with Salesforce. A Salesforce window opens; sign in if you are prompted and approve Streamkap’s access. When it closes, the Auth tab shows a Connected chip — there is nothing to paste. Streamkap knows your org from the authorization, so you do not enter a My Domain URL.

3. Settings tab

  • My Domain URL (service account only): Your org’s My Domain URL, for example https://acme.my.salesforce.com. Not needed with Connect with Salesforce — Streamkap already has your org from the authorization.
  • Objects: The Salesforce objects to sync, picked from the eight standard objects. The default selection is Account, Contact, Opportunity and Lead. See Supported Objects, and Custom objects for syncing your own.
  • Backfill start date (optional): The earliest record modification time to sync, as an ISO-8601 date or datetime — 2026-01-01, or 2026-01-01T00:00:00Z. A value with no timezone is read as UTC. Leave it empty to sync all history. See Backfill start date.

The panel beside the form lists the Kafka topics your selection will produce — one topic per object.

Optionally click Test connection. With a service account this runs a read-only check against Salesforce — nothing is created or written — and reports one of:

  • Connection verified, with the Salesforce org the connection belongs to. Worth a glance: it confirms Streamkap is pointed at the org you meant.
  • Connection failed — the credentials were rejected, the app does not enable the client-credentials flow, or it names no run-as user. Salesforce answers all three the same way, so check each.
  • Some resources need attention — the credentials work, but the run-as user cannot read one or more of the objects you selected (or the object name is wrong). The result names each object, so you can fix the permission set without guessing.

Testing is optional. Streamkap runs the same checks again when you save, whether or not you tested.

4. Review and create

The last step of the wizard is Review. It lists everything you entered, with secrets masked. Click Create.

With a service account, Streamkap validates the credentials and probes every selected object against Salesforce before the source is created — a bad credential or an unreadable object is rejected here with an actionable message, before anything is saved.

Editing the Source

An existing Salesforce source has Status, Auth, Settings, Destinations and Config History tabs, plus a Logs link. There is no Schema tab: an API source has no table schema to include or exclude, and it does not expose a schema snapshot.

The Auth tab reflects the method the source was created with — a Reconnect Salesforce control for a Connect with Salesforce source, or the stored Consumer Secret for a service account.

Reconnecting an OAuth connection

A source created with Connect with Salesforce stays authorized on its own — Streamkap refreshes the authorization automatically, so a healthy OAuth source needs nothing from you.

If the authorization is revoked in Salesforce (Setup > Connected Apps OAuth Usage) or otherwise expires, syncing stops and the Auth tab shows a re-authenticate prompt. Pick the Salesforce environment the source connects to, click Reconnect Salesforce, and approve Streamkap’s access in the Salesforce window as you did at setup. Syncing resumes from the last cursor — no data is lost.

Rotating the Consumer Secret

The Consumer Secret is write-only. It is never displayed again, so the Auth tab shows it as stored rather than as a value. Leave it untouched and Streamkap keeps the credential it already holds; click Replace and type a new one to rotate it.

Saving a replacement secret takes effect immediately: it clears an authentication failure in one step, without waiting for the automatic retry.

Test connection works here too, and tests the stored credentials — you do not need to re-enter them just to check that they still work. This is the quickest way to confirm a Broken source is a credential problem rather than a permission one.

Adding objects

Add or remove objects on the Settings tab at any time. A newly added object is read in full on its first poll, then goes incremental like the others. Removing an object stops its topic; the data already delivered to your destination is untouched.

Sending Topics to a Destination

Salesforce topics reach a destination without you building a pipeline by hand. Streamkap creates and maintains the pipeline for you — the Pipelines list labels it Auto-managed.

You can start from whichever end you are already looking at:

  • From the source — open its Destinations tab, click Send topics, pick a destination.
  • From the Topics page — select the topics you want and choose Send to destination.
  • From the destination — open it and click Add topics.

To stop delivering a topic, remove it from the source’s Destinations tab — Detach all clears a destination in one go. Removing the last topic removes the destination from the source entirely.

Supported Objects

Select any of the eight standard objects:

Object Salesforce API name
Account Account
Contact Contact
Lead Lead
Opportunity Opportunity
Case Case
Campaign Campaign
Task Task
Event Event

Custom objects

Streamkap syncs Salesforce custom objects too. A custom object is identified by its API name, which always ends in __c — for example Warehouse__c, or acme__Invoice__c if it comes from a managed package. Anything that is neither a standard object nor a __c name is rejected when you save.

The API name is not always the label you see in the Salesforce UI. Find it in Setup under Object Manager, on the object’s detail page.

A custom object syncs exactly like a standard one: a full first read, then incremental on SystemModstamp, and the same delete sweep — a deleted custom-object record becomes a tombstone in your destination like any other. See Deletes and tombstones, whose Recycle Bin bound applies to custom objects too.

Behavior & Limits

Incremental sync

After the initial full read of each object, every poll fetches only records whose SystemModstamp moved since the last cursor position. A poll where nothing changed in Salesforce produces zero new records — this is expected, not a fault.

Backfill start date

By default the first sync of an object reads all of its history. When you don’t want years of records you will never query, set a Backfill start date on the Settings tab: the first sync starts from that instant instead, and records whose SystemModstamp is older are never fetched.

The value bounds the first sync of each object and nothing else. Once an object has synced, the connector resumes from its own cursor and the backfill start date no longer applies to it — raising it later hides nothing, and lowering it reaches no further back. An object you add on the Settings tab afterwards is new, so its first sync uses whatever the value is at that point.

Deletes and tombstones

Streamkap detects deletes two ways, and both cover every object you sync — the eight standard objects and custom objects alike.

The delete sweep. When a record is deleted in Salesforce, a periodic sweep (roughly every 6 hours) detects it and emits a record with __deleted = true, so your destination’s tombstone/delete handling flips the row to deleted. Expect deleted records to surface within one sweep interval. The sweep reads deletes out of Salesforce’s Recycle Bin, which retains them for about 15 days.

Reconciliation. A slower reconciliation pass — about once a day — backs up the sweep for deletes that aged out of the Recycle Bin before Streamkap could read them (for example, a delete that happened while the connector was down for longer than the retention window). It re-lists the live records for each object and tombstones any that have disappeared, so the delete still surfaces once the connector is running again.

Formula and roll-up summary fields

Salesforce does not bump a record’s SystemModstamp when the computed value of a formula or roll-up summary field changes because a record it references changed. The record has changed as far as your users are concerned, but Salesforce reports it as untouched.

Any incremental sync that keys on SystemModstamp — Streamkap’s included — is therefore blind to that change. This is inherent to the Salesforce API, not something Streamkap can work around: Salesforce simply never tells us.

What to do about it:

  • Sync the referenced object instead. A roll-up on an Account that sums its Opportunities does move when an Opportunity moves — so sync Opportunity and compute the roll-up in your warehouse, where it will be correct and current.
  • Re-snapshot when you need the computed values to be right. Removing an object from Objects and adding it back reads it in full again, refreshing every formula value.
  • Records that change for any other reason still carry their current formula values. The gap only affects records whose sole change was a formula recomputation.

Compound and binary fields

Salesforce exposes an address twice: once as a nested object (BillingAddress) and once as flat components (BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry). Streamkap syncs the flat components, and skips the nested object.

The components carry the same data, and they land cleanly in relational destinations that cannot store a nested object in a column. The same applies to geolocation fields, which also have flat components.

Binary (base64) fields are skipped for the same reason — they are blobs, not the flat scalars every destination expects in a column. Every other field on the object is synced, discovered from Salesforce rather than hardcoded, so your own columns come along without a Streamkap change.

New and custom fields

Because the field list is read from your org rather than hardcoded, a field you add to an object you already sync is picked up on its own — there is nothing to reconfigure in Streamkap, and no setting to turn on.

Streamkap re-reads an object’s field list periodically rather than on every poll, so a newly added field can take up to about an hour to start appearing. That is deliberate: re-reading the schema every poll would roughly double the connector’s share of your org’s API request allocation for a schema that changes monthly, not by the minute.

New fields are added to your destination table automatically when the destination evolves its schema, which is the default. If a destination is set not to evolve, its existing columns stay as they are and the new field arrives on the topic without being added to the table. See Schema Evolution.

A new field is only populated for records that change after you add it — Salesforce does not move SystemModstamp for the rest. See Incremental sync.

API request allocation

Salesforce enforces a rolling 24-hour API request allocation for the whole org — shared by Streamkap and every other integration you run. Streamkap paces its requests below what the org can serve, so a sync does not monopolize your allocation.

If the org’s allocation is exhausted anyway, the connector pauses ingestion rather than burning what is left on retries, and resumes at the start of the next UTC day. No data is lost — ingestion continues from where it paused. If you hit this regularly, reduce the number of selected objects, or reduce the load from other integrations sharing the org.

Connector status

Status Meaning
Pending The source is saved and Streamkap is still deploying it. It moves to Active on its own once the connector starts; there is nothing to do.
Active Polling normally. A trace message may note a temporary pause on the org’s API allocation (see above).
Paused / Stopped You paused or stopped the source. Resume to continue from the last cursor. Mind the 15-day Recycle Bin window if you leave it stopped.
Broken The connector needs attention. The status message says which case you are in: rejected service-account credentials — or a revoked Connect with Salesforce authorization — stop all syncing until you replace or reconnect them; an object the run-as user cannot read fails that object only, while the rest keep streaming, and recovers on its own once you grant access. See Troubleshooting.

Troubleshooting

Salesforce rejected the client credentials

Streamkap reports:

Salesforce rejected the client credentials — check the Consumer Key and Consumer Secret of your External Client App, that its OAuth settings enable the client-credentials flow, and that it names a run-as user.

Salesforce answers all three of those problems with the same error, so check each one:

Resolution:

  • Re-copy the Consumer Key and Consumer Secret from the app (Settings > OAuth Settings > Consumer Key and Secret) and make sure neither picked up a stray space.
  • Confirm the app’s OAuth settings have Enable Client Credentials Flow selected (Edit Settings > OAuth Settings). An app with OAuth enabled but the client-credentials flow not enabled fails here.
  • Confirm the app’s policies name a Run As user (Edit Policies > Client Credentials Flow > Run As). Salesforce refuses to issue a token for a client-credentials app with no run-as user.
  • On the source’s Auth tab, click Replace, paste the fresh values, and save. The source recovers immediately.

All syncing stops while the credentials are rejected — Streamkap does not retry a rejected credential on its own.

Broken: reconnect required (Connect with Salesforce)

The source was created with Connect with Salesforce, and its authorization is no longer valid — it was revoked in Salesforce or it expired. All syncing stops until you re-authorize.

Resolution:

  • Open the source’s Auth tab. When re-authentication is needed it shows a prompt with a Reconnect button.
  • Click Reconnect and approve Streamkap’s access in the Salesforce window, exactly as you did when you created the source.
  • Syncing resumes from the last cursor once the connection is re-established — no data is lost.
  • If the access was revoked deliberately, review it in Salesforce under Setup > Connected Apps OAuth Usage; reconnecting re-grants it.
Connect with Salesforce fails at the Salesforce login screen

The Salesforce consent window opens but the org’s own sign-in fails, and there is nothing of Streamkap’s on the screen to act on. The usual cause is the wrong environment: a sandbox org cannot authenticate through the production login host, and a production org cannot authenticate through the sandbox one.

Resolution:

  • Restart the connection and pick the environment that matches your org — Production or Developer Edition, or Sandbox for a sandbox.
  • If your production org’s My Domain policy blocks the standard production login host outright, OAuth cannot be offered for it — use the service account path, which takes your My Domain URL directly.
Salesforce cannot see the object

Streamkap reports:

Salesforce cannot see the object ‘<name>’ — it does not exist, or the External Client App’s run-as user has no read access to it. Grant that user read access (profile or permission set), or check the custom object’s API name (it ends in __c).

Salesforce deliberately reports “this object does not exist” and “you don’t have access to this object” identically. There is no way for Streamkap to tell you which one it is, so check both:

Resolution:

  • Check the API name. It is case-sensitive, and a custom object’s API name always ends in __c (Warehouse__c, not Warehouse). Find it in Setup under Object Manager. The object’s UI label is often not its API name.
  • Check the run-as user’s read access. Open the External Client App’s Run As user and confirm its profile or permission sets grant read on the object. Remember that the person who created the app is irrelevant — only the run-as user’s permissions count.
  • Grant the access, and the object recovers on its own on the next poll. You can also clear it immediately by re-saving the connector config, or remove the object from Objects if you don’t need it.

Only the named object stops. Every other object keeps streaming.

The My Domain URL is rejected

Streamkap validates the My Domain URL before saving, and reports what is wrong with it — for example that the host acme.lightning.force.com “is not a Salesforce My Domain host”.

The value must be your org’s API host, not the UI host you see in your browser:

Status Example
✅ Accepted https://acme.my.salesforce.com
✅ Accepted https://acme--dev.sandbox.my.salesforce.com (and the .develop. / .scratch. variants)
⚠️ Rejected https://acme.lightning.force.com — this is the Salesforce UI, never the API

Resolution: in Salesforce Setup, use Quick Find to search for My Domain (under Company Settings), and copy the URL from there rather than from your browser’s address bar. It must be a bare https host — no port, no path, no query string.

No new records on the second poll

This is expected. The source is incremental — after the first full read it only emits records whose SystemModstamp moved since the last poll. If nothing changed, a poll produces zero records. Edit a record in Salesforce and it appears on the next poll.

One case is not expected but also not a fault: a record whose only change was a formula or roll-up summary recomputation does not move SystemModstamp, so Salesforce never reports it as changed. See Formula and roll-up summary fields.

A field I added in Salesforce isn't in my destination

New fields are picked up automatically, so the usual causes are one of these:

  • Not enough time has passed. Streamkap re-reads an object’s field list periodically, so a new field can take up to about an hour to appear. See New and custom fields.
  • No record has changed since. A new field is only populated for records that change after you add it — Salesforce does not move SystemModstamp for the rest.
  • The destination isn’t evolving its schema. The field is on the topic but the destination is not adding the column. See Schema Evolution.
  • The field is compound or binary. Address and geolocation fields sync as their flat components, and base64 fields are skipped. See Compound and binary fields.

With a service account, also confirm the run-as user can read the new field — Streamkap syncs exactly what that user can see.

Older records are missing after the first sync

Check the Backfill start date on the Settings tab. When it is set, the first sync of each object skips records whose SystemModstamp is older than that instant.

Clearing or lowering the value does not bring them back — the bound applies to an object’s first sync only, and that object is now on its own cursor. Remove the object from Objects and add it back to read it again from the new bound. See Backfill start date.

Ingestion paused — API allocation exhausted

The org’s rolling 24-hour Salesforce API request allocation was used up — by Streamkap together with every other integration on the org. The connector pauses and resumes at the start of the next UTC day. No data is lost.

If it recurs:

  • Reduce the number of selected objects.
  • Reduce the API load from other integrations sharing the same org.
  • Check the org’s allocation in Setup (Company Information) against what your integrations actually consume.
A deleted record still shows in my destination

Deletes are detected by a periodic sweep (roughly every 6 hours), not on every poll, so a deleted record can take up to one sweep interval to surface as a tombstone (__deleted = true).

The sweep covers every object you sync — standard and custom alike — so the object’s kind is never the reason.

A delete that aged out of the ~15-day Recycle Bin (for example, one that happened while the connector was down longer than that) is missed by the sweep, but the daily reconciliation pass catches it once the connector is running again. One case where even that does not help:

  • The object is very large (roughly tens of thousands of records or more). Reconciliation does not run on very large objects, so for those the Recycle Bin window is the hard limit: a delete that aged out while the connector was down is gone for good. Re-snapshot the object to resync it.

See Also

  • Sources — managing source connectors, status, and config history.
  • Salesforce CDC — streaming change events with native Salesforce Change Data Capture.
  • HubSpot — the other CRM API source.