PPactDocs
Social

Social overview

Publish, schedule, monitor, and report on organic social across nine networks from one tenant-isolated workspace — the composer, calendar, inbox, listening, analytics, and compliance surfaces built on /v1/social.

Pact Social

Pact Social is the organic social-media surface of the platform: connect a workspace's LinkedIn, Meta, X, and other network accounts once, then draft, schedule, publish, monitor replies, listen for brand mentions, and report on performance — all inside the same multi-tenant, RBAC-enforced app that owns your CRM and marketing data. Every route lives under the /v1/social prefix and derives tenant_id from the auth context, so one workspace never sees another's accounts, posts, or engagements.

This surface is live

The composer, calendar, inbox, listening, analytics, and compliance flows are backed by real, tenant-isolated endpoints and Postgres tables (tenant_social_accounts, social_posts, social_engagements, social_mentions, tenant_listening_queries, social_listening_matches, social_scheduled_reports, and more). The one exception is the content Library, which currently persists to the browser — see below.

The surfaces

Supported networks

The provider registry (core/integrations/social/registry.py) ships factories for nine networks:

NetworkSlug(s)Notes
LinkedInlinkedinPersonal feed, company page, and share; full OAuth + client.
Metafacebook, instagram, threadsPage / IG / Threads posting via the Meta Graph client.
X (Twitter)twitterv2 API over OAuth 2.0 PKCE; requires a paid X Basic tier (~$100/mo).
BlueskyblueskyAT Protocol.
MastodonmastodonInstance-scoped.
TikToktiktokVideo posting.
YouTubeyoutubeVideo + description.

Each provider implements the same SocialProvider contract (core/integrations/social/base.py): authorize_url, complete_oauth, refresh_token, post, list_engagements, list_mentions, reply, analytics, and delete. A network only becomes connectable once an admin supplies its app credentials through the BYOK credentials wizard — the provider factory resolves them per-tenant at request time, so nothing is hardcoded.

How posting works

POST /v1/social/posts creates a post in one of three states, mirrored by the constants in core/integrations/social/store.py:

  • draft — saved, not sent.
  • scheduled — a scheduled_for timestamp is set; the post appears on the calendar.
  • published — sent immediately when the request carries publish_now: true (publishing flips the row to failed with a failure_reason if the provider call errors).

Publishing a draft or a scheduled post is an explicit call to POST /v1/social/posts/{public_id}/publish.

Scheduled auto-publish is not wired yet

Scheduling stores a post with status scheduled and surfaces it on the calendar, but there is currently no background worker that publishes due posts at their scheduled_for time. Until that lands, treat a scheduled post as a planned draft and publish it with the publish endpoint (or the Publish action in the UI). Scheduled analytics reports are a separate, working mechanism — see Social analytics.

Roles and audit

Any workspace member can create posts; connecting or disconnecting an account is restricted to admin/owner (the same policy as the credential store). Every meaningful action writes an audit event — social.account.connected, social.post.published, social.engagement.received, social.listening.alert.fired, and peers — and secrets never enter those payloads: only ids, kinds, names, and the connected account's display name.