Skip to content

Connector lifecycle

The lifecycle from the SDK source runs in this order: package registration, factory implementation, factory registration, authorized runs, contract-test verification, operation.

Connector SDK inbound: integration package, provider factory, object bindings, sync run, work items
The lifecycle stages against the inbound-import pipeline. Each stage below names its file or endpoint.

Register the integration package (lib/integrations/packages/types.ts, managed at /automations/connectors/[packageKey]). For Field mapping UI support, set mappingTemplate: 'crm'. That is what wires the package to the shared object-mapping editor (components/integrations/package-object-mappings.tsx).

  • Package registered with mappingTemplate: 'crm'
  • Field-mapping UI renders for the package via the Admin API (/api/v1/integration-packages/[packageKey]/object-mappings)

Build the adapter behind the source contract (provider-types.ts): a factory returning a refreshed, tenant/connection-scoped client exposing exactly three operations: objects(), properties(objectKey), records(objectKey, properties, after). Skeleton in Examples.

  • Client is tenant- and connection-scoped with refresh (no cross-tenant leakage, no stale credentials)
  • objects(), properties(), records() match the contract in provider-types.ts
  • Record paging honors the after cursor (watermarks depend on it)

3. Register the factory in crm-sync/provider.ts

Section titled “3. Register the factory in crm-sync/provider.ts”

Registration is code-owned and fail-closed: unregistered providers do not run, period.

  • Factory registered in lib/integrations/crm-sync/provider.ts
  • Unknown-provider path verified fail-closed (no fallback import)
  • Adapter follows the registered-adapter convention (HubSpot: lib/integrations/hubspot/sync-provider.ts; ConnectWise PSA: provider under lib/integrations/connectwise/)

4. Run authorized: syncConnectorObjectMappings

Section titled “4. Run authorized: syncConnectorObjectMappings”

Invoke syncConnectorObjectMappings({ orgId, connectionId, packageKey }) from an authorized runner:

  • New scheduling goes through Inngest via function-catalog (register the new function there).
  • Do NOT revive connector-sync-runner. It stays dead; new work uses the catalog path.
  • Only advance the watermark when failed === 0. Partial success re-runs from the same watermark and never skips failed records.

Every adapter proves this sequence in order: create, update, retry, pause.

  • Create: new source records arrive as mapped records
  • Update: changed source records update (see upsertConnectorCrmRecord)
  • Retry: failed runs re-run from the held watermark without loss or duplication
  • Pause: pausing stops scheduling cleanly; resume continues correctly
  • Watch run outcomes and denial patterns as design feedback.
  • Track binding health per org, package, and connection (settings.object_mappings).
  • Changes go through the lifecycle again. Never edited live under tenants.
  • Retirement: remove from provider.ts, migrate or freeze bindings, revoke grants, preserve audit history. Exact retirement mechanics: not in pasted sources.
  • Never expose applyConnectorMappedRecord unauthenticated. Authorized runners only.
  • Never revive connector-sync-runner for new scheduling.
  • Never advance the watermark when failed !== 0.
  • Never present Salesforce scaffolds as implementations; never promise outbound HubSpot writes.