PPact
Administration

Integrations

The per-tenant integration connection layer — credentials, mapping, schedule, health — and which connectors sync live versus config-only.

Integrations

The integration connection layer ties a catalogue connector to an encrypted credential, a field mapping, a sync schedule, and a rolled-up health status. It lives under /v1/admin/integrations/connections (api/routes/integration_connections.py) and is real, enforced code — not a mock surface.

Admin only

Every connection route requires the admin module and an admin/owner role. A connection id is always resolved within the caller's tenant_id, so a leaked id can't be read or mutated cross-tenant.

What a connection manages

  • GET /connections — every connection for the tenant plus a health_rollup for the manager header.
  • POST /connections — connect (or reconnect) a connector. Secrets go into the encrypted credential store under the connector's credential kind, the kind's test-connection verifier runs immediately, and the connection status reflects the result (connected, configuring, or error).
  • PATCH /connections/{id}/mapping and /schedule — bidirectional field mapping and sync cadence.
  • POST /connections/{id}/test — re-run the verifier and flip status.
  • DELETE /connections/{id} — disconnect.

Credential storage reuses the existing encrypted credential store and its per-kind verifier — this module never re-implements encryption or secret handling.

"Sync now" is deliberately honest

POST /connections/{id}/sync does not fabricate work that didn't happen:

  • Read-only connectors (the pipeline-first CRM, ActiveCampaign, Mailchimp, Klaviyo and Kit) start a real run in the background. It pulls what changed since the last run and lands under Recent sync runs with its record count, how many records failed to write, and the first error. A second click while a run is in flight is refused (409) rather than starting a parallel run.
  • Other live connectors are synced by their own dedicated scheduled engine. The button does not run that backfill synchronously and there's no off-cycle trigger wired up yet, so it records an audit-trail entry (integration_connection.sync_now_scheduled) and tells you the next scheduled run will pick up changes — rather than writing a phantom success run with zero records.
  • Every other connector records an honest unsupported sync run: credentials and mapping are saved, but an automated sync adapter for that vendor isn't built yet.

config_only means credentials, not sync

A config_only connector stores credentials and field mapping and validates the connection, but does not yet run an automated data sync. Treat those connectors as "wired and validated, automated sync on the roadmap."

Which connectors sync live

The catalogue (core/integrations/registry.py) marks each connector's sync_status:

  • live — Salesforce (market-leading-crm), Stripe, and the Google and Microsoft 365 calendars run real, scheduled syncs.
  • live, read-only — the pipeline-first CRM connector (organizations, people, deals), ActiveCampaign (accounts, contacts, deals), and Mailchimp, Klaviyo and Kit (contacts). They pull what changed since the last run on the schedule you pick (realtime is polled every 5 minutes) and never write back. They match people already in Pact by email instead of duplicating them, never overwrite a value with a blank, skip records you deleted in Pact, and store email and phone encrypted. Unsubscribes stay in the source tool: a run counts them and records no consent. Custom field mapping is not applied yet.
  • config_only — 36 connectors, among them the generic sales-engagement and marketing-automation connectors, Webex, and the accounting, warehouse, and HR connectors. They store credentials and mapping but don't sync. Their marketplace tile, listing, and connect page all open with "Credential storage only", and the registry refuses to load a config_only connector whose tagline says anything else.
  • n/a — connectors where sync isn't the concept. These include AI keys, notification targets, the Resend and SendGrid send providers (your key sends the mail), and Zoom, Microsoft Teams, and Google Meet (your grant creates meeting links and captures recordings).

Custom inbound webhook connector

The custom connector receives events at POST /v1/webhooks/custom/{tenant_id} (api/routes/custom_webhook.py). It verifies an X-Signature header — HMAC-SHA256 over the raw body, accepted as sha256=<hex> or bare hex, compared in constant time — against the per-tenant signing_secret stored on the custom_webhook credential. Verified deliveries record an inbound sync run on the connection so they show up in the health badge and audit trail.