- Sells as: the
social-distribution product (a product-scoped API key). This capability has no separate product-face contract — its public product route reuses the capability contract below; see the Edge route table's Product face row.
11-network social syndication engine (X · LinkedIn · Facebook · Mastodon · Bluesky · Threads · Reddit · Instagram · Telegram · Pinterest · WhatsApp) with a per-org ENCRYPTED OAuth/credential store (AES-256-GCM at rest — the DB never holds a plaintext secret) and an idempotent, multi-worker-safe outbound queue with a dead-letter queue. Products bind over this contract so each doesn't re-roll the adapters, token store, and durable queue. Platform secrets + the vault key are resolved server-side (Infisical), never in body/DB/logs.
- Group: Comms & workflow
- Contract:
contracts/social-distribution/v1/openapi.yaml
- Console: Manage the
social-distribution product in the console →
- Runbook: operational checklist for
social-distribution — internal (Vagary Labs ops; not part of this public site): docs/runbooks/capability-operations.md#social-distribution
- Public base:
https://api.vagarylabs.com (the consolidated API gateway — one host, per-brand sibling api.<zone>)
- Auth: a product API key (
vgk_…) issued from the console — Authorization: Bearer vgk_…
- Product face (customer-keyed):
https://api.vagarylabs.com/product/v1/social/posts
Edge route table
The routes this capability actually serves on the public edge — live-synced from GET https://api.vagarylabs.com/product/v1/_meta/catalog (snapshot v1). The metric is the request-granularity billing counter; the scope is the key permission required.
Product face (customer-keyed)
| Method | Path | Metric | Scope |
|---|
POST | /product/v1/social/posts | social_posts | write |
Endpoints
| Method | Path | Summary |
|---|
POST | /v1/connections | Store an encrypted per-(platform, account) credential for the caller's org |
GET | /v1/connections | List connection metadata (NEVER the secret) for the caller's org |
DELETE | /v1/connections/{platform}/{account_id} | Delete a stored connection |
POST | /v1/posts | Idempotently enqueue an outbound post (optionally scheduled for a future time) |
GET | /v1/posts | List the caller's queued/scheduled/retrying posts (the read side of the scheduling surface) |
DELETE | /v1/posts/{entry_id} | Cancel a queued/scheduled post before it fires |
POST | /v1/posts/run | Worker tick — claim a batch and publish (first-party/ops trigger) |
GET | /v1/posts/stats | Per-org queue / history / dead-letter counts |
GET | /v1/platforms | The registered network set + per-platform dark/circuit state |
GET | /health | liveness |
GET | /metrics | Prometheus |
Schemas
ConnectRequest
| Field | Type | Description |
|---|
organization_id | string | product-tier end-customer tenant (I6); anti-spoof-verified against the token |
platform | string | |
account_id | string | allow multiple accounts per platform per org |
credentials | object | Per-network secret fields (bearer/access token, app secret, bot token, …) encrypted at rest with AES-256-GCM. MAY instead be an Infisical reference {"$ref":"infisical://<path>"} (a pointer, not a secret). The plaintext form is NEVER stored and NEVER returned. |
ConnectResult
| Field | Type | Description |
|---|
success | boolean | |
platform | string | |
account_id | string | |
PostRequest
| Field | Type | Description |
|---|
organization_id | string | product-tier end-customer tenant (I6) |
platform | string | |
article_id | string | source id — the (org |
account_id | string | |
headline | string | |
url | string | |
body | string | |
vertical_slug | string | |
image_url | string | |
hashtags | array | |
recipient | string | WhatsApp/Telegram targeted-send override |
scheduled_at | string | |
extra | object | per-network options (subreddit |
PostAccepted
| Field | Type | Description |
|---|
entry_id | string | |
status | string | queued (immediate) or scheduled (a future scheduled_at) |
platform | string | |
scheduled_at | ['string', 'null'] | the honoured schedule (null for immediate) |
PostListItem
One queue row as honest current queue-state (never a credential/payload).
| Field | Type | Description |
|---|
id | string | entry_id — pass to DELETE /v1/posts/{entry_id} to cancel |
article_id | string | |
platform | string | |
account_id | string | |
status | string | |
retry_count | integer | |
scheduled_at | ['string', 'null'] | next-eligible time (may be an internal lease/retry marker — see the path description) |
claimed_at | ['string', 'null'] | |
last_error | ['string', 'null'] | |
created_at | string | |
PostList
| Field | Type | Description |
|---|
posts | array | |
CancelResult
| Field | Type | Description |
|---|
success | boolean | |
cancelled | boolean | |
entry_id | string | |
Error
| Field | Type | Description |
|---|
error | string | |
Generated by scripts/gen-capability-docs.py from contracts/social-distribution/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page. The Edge route table section is synced from the live edge catalog snapshot (v1) — re-sync with python3 scripts/sync-edge-catalog.py.