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:
| Network | Slug(s) | Notes |
|---|---|---|
linkedin | Personal feed, company page, and share; full OAuth + client. | |
| Meta | facebook, instagram, threads | Page / IG / Threads posting via the Meta Graph client. |
| X (Twitter) | twitter | v2 API over OAuth 2.0 PKCE; requires a paid X Basic tier (~$100/mo). |
| Bluesky | bluesky | AT Protocol. |
| Mastodon | mastodon | Instance-scoped. |
| TikTok | tiktok | Video posting. |
| YouTube | youtube | Video + 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— ascheduled_fortimestamp is set; the post appears on the calendar.published— sent immediately when the request carriespublish_now: true(publishing flips the row tofailedwith afailure_reasonif 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.