Skip to content

SocialOps

SocialOps is a unified inbox service for social messages, IM channels, developer events, and operational webhooks. The current MVP supports inbound aggregation, normalized threads, message storage, filtering, console review, internal notes, outbound reply queues, and per-message billing. P2 adds a provider capability registry and a shared webhook delivery adapter.

Status

Backend and console MVP are available. The first provider allowlist is:

ProviderStatusNotes
generic-webhookAvailableGeneric JSON event ingestion.
telegramAvailableNative Bot API ingestion and scheduled reply delivery.
githubAvailableNormalized webhook ingestion; outbound adapter is not enabled.
discordBetaWebhook ingestion and outbound webhook delivery. OAuth bot adapter is separate.
slackBetaWebhook ingestion and outbound incoming-webhook delivery. Workspace OAuth is separate.
teamsBetaWebhook ingestion and Teams-compatible incoming-webhook delivery. Graph adapter is separate.
whatsappPlannedOfficial Cloud API adapter is not enabled.
linePlannedLINE Messaging API adapter is not enabled.
instagramPlannedInstagram Graph messaging adapter is not enabled.

The provider registry is available through GET /v1/apps/socialops/providers and GET /console/socialops/providers. Outbound replies are stored as SocialOps actions; unsupported providers are marked failed with an audit error instead of being silently dropped.

Console

After creating a socialops service instance, open:

text
Console > SocialOps

The console can:

  • List SocialOps service instances.
  • Filter threads by status, priority, provider, and search query.
  • Inspect normalized thread messages without exposing raw provider payloads.
  • Bind Telegram Bot connections to SocialOps chat/channel targets.
  • Bind webhook-backed Discord, Slack, Teams, or generic channels using a custom-api-key Connected Account.
  • Update thread status, priority, and assignee.
  • Queue outbound replies for provider adapter delivery.
  • Add internal notes to preserve handling history.

Console management endpoints use the user JWT and service:read or service:manage permissions:

http
GET   /console/socialops/instances
GET   /console/socialops/providers
GET   /console/socialops/:alias/channels
POST  /console/socialops/:alias/channels
PATCH /console/socialops/:alias/channels/:channel_id
GET   /console/socialops/:alias/inbox
GET   /console/socialops/:alias/threads/:thread_id/messages
POST  /console/socialops/:alias/threads/:thread_id/notes
POST  /console/socialops/:alias/threads/:thread_id/replies
PATCH /console/socialops/:alias/threads/:thread_id

Create a Telegram channel binding:

json
{
  "provider": "telegram",
  "connected_account_id": "conn_xxx",
  "channel_name": "Support Telegram",
  "external_channel_id": "-1001234567890",
  "parse_mode": "HTML"
}

Create a webhook-backed Slack, Discord, Teams, or generic channel:

json
{
  "provider": "slack",
  "connected_account_id": "conn_custom_key",
  "channel_name": "Slack Support",
  "external_channel_id": "C123",
  "webhook_url": "https://hooks.slack.com/services/T/B/X"
}

The connected account must be an active custom-api-key account. The webhook URL is validated as HTTPS and is never returned in clear text by the channel list API. Provider-specific OAuth and native bot adapters remain separate from this webhook adapter.

The connected_account_id must reference an active telegram-bot Connected Account owned by the same user. Channel bindings can be toggled with:

json
{
  "status": "inactive"
}

Create an internal note:

json
{
  "text": "Checked provider dashboard and assigned to ops."
}

Notes are stored as internal SocialOps messages. They do not send anything to external providers.

Queue an outbound reply:

json
{
  "text": "Thanks, we are checking this now."
}

Replies are stored as outbound SocialOps messages and create a send_reply action with pending status. The scheduled delivery worker consumes pending actions, sends supported providers, and marks each action as completed or failed.

Endpoints

http
GET  /v1/apps/socialops/providers
POST /v1/apps/socialops/:alias/webhook/:provider
GET  /v1/apps/socialops/:alias/inbox
GET  /v1/apps/socialops/:alias/threads
GET  /v1/apps/socialops/:alias/threads/:thread_id/messages
POST /v1/apps/socialops/:alias/threads/:thread_id/replies

Required scopes:

text
socialops:write
socialops:read

Ingest an Event

bash
curl -X POST https://api.open4x.com/v1/apps/socialops/support/webhook/generic-webhook \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "evt_1001",
    "thread_id": "incident_42",
    "title": "Incident opened",
    "text": "API latency is high",
    "user": {
      "id": "monitor"
    },
    "labels": ["ops", "urgent"]
  }'

Response:

json
{
  "status": "accepted",
  "provider": "generic-webhook",
  "thread_id": "soth_...",
  "message_id": "somsg_..."
}

Query Inbox

bash
curl "https://api.open4x.com/v1/apps/socialops/support/inbox?status=open&priority=high&limit=50" \
  -H "X-API-Key: sk_xxx"

Supported filters:

QueryValues
statusopen, pending, resolved, archived
prioritylow, normal, high, urgent
providergeneric-webhook, telegram, github, discord, slack, teams, whatsapp, line, instagram
qSearches thread subject and AI summary.
page, limitStandard pagination; limit is capped at 100.

Queue a Reply

bash
curl -X POST https://api.open4x.com/v1/apps/socialops/support/threads/soth_xxx/replies \
  -H "X-API-Key: sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Thanks, we are checking this now."
  }'

Response:

json
{
  "success": true,
  "data": {
    "message": {
      "direction": "outbound",
      "message_type": "text",
      "text": "Thanks, we are checking this now."
    },
    "action": {
      "action_type": "send_reply",
      "status": "pending"
    }
  }
}

Reply Delivery

The scheduled worker scans send_reply actions and supports Telegram plus the webhook adapter for Discord, Slack, Teams, and generic webhook channels:

  1. The action is claimed as processing.
  2. The worker loads the thread, outbound message, and active SocialOps channel.
  3. The channel must reference an active provider connection. Telegram uses telegram-bot; webhook channels use custom-api-key.
  4. The worker charges the SocialOps reply delivery fee.
  5. Telegram sendMessage or the provider webhook is called with the thread target.
  6. On success, the action becomes completed and the outbound message stores the provider message id when returned.
  7. On provider failure, the charge is refunded and the action becomes failed.

If a channel, connected account, balance, or provider adapter is missing, the action is marked failed with an audit error.

Data Safety

Inbox responses do not expose external thread identifiers by default. Message responses also hide raw provider payloads by default. Raw payloads are retained for auditing and future provider-specific processing, but should not be shown in normal customer-facing UI.

Billing

Inbound SocialOps messages are charged per accepted webhook event. The MVP default rate is 0.0002 USD per inbound message. Reply delivery is charged when the scheduled worker actually sends Telegram or a webhook provider message; failed provider sends are refunded.