Shop It Docs
Developer ResourcesCommunication

Communication Admin API Reference

Integration reference for Communication admin endpoints.

Communication Admin API Reference

Audience: Admin/frontend developers, API consumers Scope: Admin Communication endpoint contracts.


Admin APIs

Realtime Side Effect

Admin write endpoints for channel posts and discussion messages now emit realtime delta events after DB commit. For exact room names, socket events, and payload contracts, see Communication Realtime Implementation.

Access Policy vs Membership

Communication now separates:

  • Access policy: whether the user can read channel content right now
  • Membership: whether the user explicitly joined the broadcast channel for notifications

Rules:

  • OPEN channels are readable without subscription entitlement.
  • EXTERNAL_GATED channels require current entitlement through the feature/access provider.
  • Membership does not grant content access by itself.
  • Admin broadcast post push notifications go only to joined members, not to every user who could theoretically read the channel.
  • If a joined gated user loses entitlement, content access is blocked immediately, but membership may remain active for a 7-day notification grace window.

Broadcast Notification Audience

For new admin-created broadcast posts:

  • notify active joined members only
  • do not notify non-members
  • do not notify users who explicitly left
  • for gated channels:
    • currently entitled joined users are notified
    • previously joined users inside their 7-day grace window are also notified
    • previously joined users after grace expiry are not notified

Push content is generic:

  • title: channel title
  • body: New update available
  • payload data includes channelId, postId, and notificationType = "channel_broadcast_post"

Discussion Access Inheritance

Discussion always depends on parent channel access first.

If channel access is denied, then discussion access is denied too. That applies to:

  • fetching discussion metadata
  • reading discussion messages
  • posting discussion messages
  • joining discussion realtime rooms

An expired gated member in notification grace may still receive broadcast post push, but discussion access stays blocked until entitlement is restored.

Create Channel

Endpoint

POST /api/admin/channels

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_CREATE

Idempotency

  • Header required: Idempotency-Key: <unique-key>
  • Same key + same payload => replay same response
  • Same key + different payload => 409 Conflict
  • Different key => treated as a new create request

Raw Request Body (Free Channel / OPEN)

{
	"kind": "BROADCAST",
	"access_policy": "OPEN",
	"visibility": "PUBLIC",
	"title": "Daily Market Updates",
	"description": "Daily market briefs and macro highlights."
}

Real-life example

  • A public announcement channel where any user can read market updates without subscription checks.

Raw Request Body (Premium Channel / EXTERNAL_GATED)

{
	"kind": "BROADCAST",
	"access_policy": "EXTERNAL_GATED",
	"visibility": "PRIVATE",
	"title": "VIP Signals",
	"description": "Members-only signals and premium charts.",
	"access_policy_config": {
		"first_subscribe_history_policy": "NO_PAST",
		"resubscribe_backfill_days": 7,
		"preserve_prior_entitled_history": true,
		"required_feature_key": "chat.broadcast"
	}
}

Real-life example

  • A paid members-only channel. Read access is decided by external entitlement logic (subscription wrapper/provider).
  • Users may still need to explicitly join the channel if they want push notifications for new broadcast posts.

Request Field Reference

FieldWhat it representsTypeRequiredExample
kindChannel typestringYes"BROADCAST"
access_policyAccess modestringYes"OPEN"
visibilityDiscovery visibilitystringYes"PUBLIC"
titleChannel display namestringYes"Daily Market Updates"
descriptionOptional channel summarystringNo"Daily market briefs and macro highlights."
access_policy_configPremium access-history policy configobjectNo{...}
access_policy_config.first_subscribe_history_policyFirst subscribe history rulestringNo"NO_PAST"
access_policy_config.resubscribe_backfill_daysBackfill days on re-subscribeintegerNo7
access_policy_config.preserve_prior_entitled_historyKeep previously entitled windows visiblebooleanNotrue
access_policy_config.required_feature_keySubscription feature key required for gated channel readsstringFor EXTERNAL_GATED"chat.broadcast"

Allowed Enum Values

  • kind: BROADCAST, PREMIUM_VIEW_ONLY
  • access_policy: OPEN, EXTERNAL_GATED
  • visibility: PUBLIC, PRIVATE
  • first_subscribe_history_policy: NO_PAST, ALLOW_PAST

Frontend Integration Notes

  • Generate a new Idempotency-Key per user action (create click).
  • Reuse the same key only for retrying that same request.
  • Do not reuse the same key for a different payload.

Gated Channel Requirement (EXTERNAL_GATED)

POST /api/admin/channels stores the required Subscription feature directly in access_policy_config.required_feature_key.

Rules:

  • required_feature_key is required for EXTERNAL_GATED.
  • required_feature_key must be a known Subscription feature key.
  • Communication reads the user’s enabled plan features and checks that key directly.
  • No separate channel_access_mapping table is used.

List Channels

Endpoint

GET /api/admin/channels?status=&kind=&sort=&order=&cursor=&limit=

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_READ

Raw request body

{}

Query params

ParamTypeRequiredExampleNotes
statusstringNoactiveactive, archived, soft_deleted
kindstringNoBROADCASTBROADCAST, PREMIUM_VIEW_ONLY
sortstringNocreatedAtcreatedAt, updatedAt
orderstringNodescasc, desc
cursorstringNoeyJjcmVhdGVkQXQiOiI...Opaque pagination cursor
limitnumberNo20Default 20, max 100

Response shape

  • GET /api/admin/channels returns list fields only: id, title, kind, accessPolicy, visibility, status, createdAt, updatedAt
  • Lifecycle/admin metadata is provided by: GET /api/admin/channels/:id
  • Cursor is sort-aware: the same cursor must be used with the same sort and order values.

Example response

{
	"message": "Channels fetched successfully",
	"data": {
		"items": [
			{
				"id": 3,
				"kind": "PREMIUM_VIEW_ONLY",
				"accessPolicy": "EXTERNAL_GATED",
				"status": "active",
				"visibility": "PRIVATE",
				"title": "VIP Signals",
				"createdAt": "2026-02-23T08:24:51.135Z",
				"updatedAt": "2026-02-23T08:24:51.135Z"
			},
			{
				"id": 1,
				"kind": "BROADCAST",
				"accessPolicy": "OPEN",
				"status": "active",
				"visibility": "PUBLIC",
				"title": "Daily Market Updates",
				"createdAt": "2026-02-23T08:13:44.644Z",
				"updatedAt": "2026-02-23T08:13:44.644Z"
			}
		],
		"cursor": {},
		"limit": 20,
		"has_more": false,
		"count": 2
	}
}

Get Channel Detail

Endpoint

GET /api/admin/channels/{id}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_READ

Path params

ParamTypeRequiredExampleNotes
idnumberYes1Channel ID

Raw request body

{}

Important terms in detail response

FieldWhat it means in simple terms
createdByAdminIdWhich admin originally created this channel
statusLifecycle state of the channel: active, archived, or soft_deleted
archivedAt / archivedByAdminIdWhen and by which admin the channel was archived
deletedAt / deletedByAdminIdWhen and by which admin the channel was soft-deleted
purgeAfterPlanned time for permanent cleanup (if retention cleanup is configured)
accessPolicyConfigExtra entitlement/history rules used for channel access behavior
accessPolicyConfig.firstSubscribeHistoryPolicyOn first subscription, whether user can see older posts (NO_PAST / ALLOW_PAST)
accessPolicyConfig.resubscribeBackfillDaysIf user re-subscribes, how many previous days of posts become visible
accessPolicyConfig.preservePriorEntitledHistoryIf true, user keeps access to posts from periods they were entitled before

Important integration note

  • Request key style depends on endpoint: POST /api/admin/channels uses snake_case keys like access_policy_config. PATCH /api/admin/channels/:id uses metadata keys like kind, visibility, title, description.
  • Response payloads use camelCase keys (example: accessPolicyConfig).

Example response

{
	"message": "Channel fetched successfully",
	"data": {
		"id": 1,
		"kind": "BROADCAST",
		"accessPolicy": "OPEN",
		"status": "active",
		"visibility": "PUBLIC",
		"title": "Daily Market Updates",
		"description": "Daily market briefs and macro highlights.",
		"createdByAdminId": "192c6636-b361-4a4d-9a4d-efb00e694e9b",
		"archivedAt": null,
		"archivedByAdminId": null,
		"deletedAt": null,
		"deletedByAdminId": null,
		"purgeAfter": null,
		"createdAt": "2026-02-23T08:13:44.644Z",
		"updatedAt": "2026-02-23T08:13:44.644Z",
		"accessPolicyConfig": {
			"channelId": 1,
			"firstSubscribeHistoryPolicy": "NO_PAST",
			"resubscribeBackfillDays": 7,
			"preservePriorEntitledHistory": true,
			"updatedByAdminId": "192c6636-b361-4a4d-9a4d-efb00e694e9b",
			"updatedAt": "2026-02-23T08:13:44.644Z"
		}
	}
}

Update Channel Metadata

Endpoint

PATCH /api/admin/channels/{id}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
idnumberYes1Channel ID

What this API accepts

FieldTypeRequiredAllowed valuesNotes
kindstringNoBROADCAST, PREMIUM_VIEW_ONLYOptional channel type change
visibilitystringNoPUBLIC, PRIVATEOptional visibility change
titlestringNoAny non-empty stringTrimmed before save
descriptionstring | nullNoAny string or nullSend null to clear

Validation rules

  • At least one metadata field is required.
  • Empty/blank title is rejected.
  • If channel status is soft_deleted, update is rejected (422); restore first.
  • This endpoint does not update access_policy or lifecycle status.

Raw Request Body (Update title + description)

{
	"title": "Daily Market Updates v2",
	"description": "Updated summary from admin"
}

Raw Request Body (Change kind + visibility)

{
	"kind": "PREMIUM_VIEW_ONLY",
	"visibility": "PRIVATE"
}

Raw Request Body (Clear description)

{
	"description": null
}

Response

  • Returns full channel detail payload (same shape as GET /api/admin/channels/:id).

Common error scenarios

  • 422: empty patch body or invalid field combination.
  • 422: soft-deleted channel (must call restore endpoint first).
  • 404: channel not found.

Update Channel Access Policy

Endpoint

PATCH /api/admin/channels/{id}/access-policy

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID

What this API accepts

FieldTypeRequiredAllowed values / rangeNotes
first_subscribe_history_policystringNoNO_PAST, ALLOW_PASTFirst-time subscribe history rule
resubscribe_backfill_daysnumberNoInteger 0..3650Days of history shown when re-subscribed
preserve_prior_entitled_historybooleanNotrue, falseKeep history from previously entitled windows
required_feature_keystringNoe.g. chat.broadcastRequired when channel access policy is EXTERNAL_GATED

Validation rules

  • At least one policy field is required (422 if body has none).
  • resubscribe_backfill_days must be an integer and within 0..3650.
  • If channel access policy is EXTERNAL_GATED, required_feature_key must be set.
  • Returns full channel detail payload (same shape as GET /api/admin/channels/:id).

Raw Request Body (All fields)

{
	"first_subscribe_history_policy": "ALLOW_PAST",
	"resubscribe_backfill_days": 14,
	"preserve_prior_entitled_history": true
}

Raw Request Body (Single field update)

{
	"resubscribe_backfill_days": 30
}

Common error scenarios

  • 400: invalid id path param (non-numeric).
  • 422: empty body (no updatable policy field sent).
  • 422: invalid enum/range/type in body.
  • 404: channel not found.

Update Channel Status

Endpoint

PATCH /api/admin/channels/{id}/status

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID

What this API accepts

FieldTypeRequiredAllowed valuesNotes
statusstringYesactive, archived, soft_deletedTarget lifecycle status
purge_afterstring (ISO datetime)Noe.g. 2026-03-31T00:00:00.000ZAllowed only when status=soft_deleted

Lifecycle behavior

  • archived: sets archive metadata and clears delete metadata.
  • active: clears archive/delete metadata and clears purgeAfter.
  • soft_deleted: sets delete metadata; can optionally set purgeAfter.
  • If channel is already soft_deleted, this endpoint cannot move it back to active/archive. Use restore endpoint instead.

Validation rules

  • purge_after is rejected unless status is soft_deleted (422).
  • Soft-deleted channel must be revived via restore endpoint (422 on direct status change).

Raw Request Body (Archive)

{
	"status": "archived"
}

Raw Request Body (Reactivate)

{
	"status": "active"
}

Raw Request Body (Soft delete with purge schedule)

{
	"status": "soft_deleted",
	"purge_after": "2026-03-31T00:00:00.000Z"
}

Response

  • Returns full channel detail payload (same shape as GET /api/admin/channels/:id).

Common error scenarios

  • 400: invalid id path param (non-numeric).
  • 422: purge_after provided with non-soft_deleted status.
  • 422: channel already soft-deleted and requested status change is not soft_deleted.
  • 404: channel not found.

Restore Channel

Endpoint

POST /api/admin/channels/{id}/restore

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID (must currently be soft_deleted)

Raw request body

{}

Behavior

  • Restores a soft-deleted channel back to active.
  • Clears deletion lifecycle fields: deletedAt, deletedByAdminId, purgeAfter.
  • Returns full channel detail payload (same shape as GET /api/admin/channels/:id).

Common error scenarios

  • 400: invalid id path param (non-numeric).
  • 422: channel is not in soft_deleted status.
  • 404: channel not found.

Create Channel Post

Endpoint

POST /api/admin/channels/{id}/posts

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_CREATE

Idempotency

  • Header required: Idempotency-Key: <unique-key>
  • Same key + same payload => replay same response
  • Same key + different payload => 409 Conflict

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID (must be active)

What this API accepts

FieldTypeRequiredAllowed values / rangeNotes
typestringYesTEXT, LINK, CHART, IMAGE, FILEPost type
body_textstring | nullNonon-empty string or nullRequired for TEXT
link_urlstring | nullNoURL string or nullRequired for LINK
chart_payload_jsonobject | nullNoJSON object or nullRequired for CHART
attachmentsobject[]Nomax 20 itemsRequired for IMAGE / FILE; each item is structured upload metadata
published_atstringNoISO datetimeDefaults to now
is_pinnedbooleanNotrue, falseDefaults to false

Type rules

  • TEXT: must include body_text; cannot include link_url, chart_payload_json, or attachments.
  • LINK: must include link_url; can include optional body_text; cannot include chart_payload_json or attachments.
  • CHART: must include chart_payload_json object; can include optional body_text; cannot include link_url or attachments.
  • IMAGE / FILE: must include at least one attachments key; can include optional body_text; cannot include link_url or chart_payload_json.

Attachment object fields

  • storage_key (required): upload storage key returned by Upload API
  • file_name (optional): original file name
  • mime_type (optional): MIME type
  • size_bytes (optional): file size in bytes

Raw Request Body (TEXT)

{
	"type": "TEXT",
	"body_text": "Morning update: BTC reclaimed key resistance.",
	"is_pinned": false
}

Raw Request Body (IMAGE)

{
	"type": "IMAGE",
	"body_text": "Chart snapshot",
	"attachments": [
		{
			"storage_key": "uploads/communication/channels/3/posts/img-001.png",
			"file_name": "market-setup.png",
			"mime_type": "image/png",
			"size_bytes": 183024
		}
	]
}

Raw Request Body (CHART)

{
	"type": "CHART",
	"body_text": "BTC breakout setup",
	"chart_payload_json": {
		"symbol": "BTCUSDT",
		"timeframe": "4H",
		"levels": [95200, 97800]
	}
}

Response

  • Returns created post detail with attachments as structured metadata (id, storageKey, fileName, mimeType, sizeBytes, displayOrder).

Common error scenarios

  • 400: missing Idempotency-Key header.
  • 400: invalid id path param (non-numeric).
  • 409: same idempotency key used with different payload.
  • 422: invalid field combination by post type.
  • 422: channel is not active.
  • 404: channel not found.

Pin / Unpin Channel Post

Endpoint

POST /api/admin/channels/{id}/posts/{postId}/pin

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID
postIdnumberYes101Post ID in the same channel

Raw Request Body (Pin)

{
	"is_pinned": true
}

Raw Request Body (Unpin)

{
	"is_pinned": false
}

Behavior

  • is_pinned=true sets isPinned=true and pinnedAt=<now>.
  • is_pinned=false sets isPinned=false and pinnedAt=null.
  • Returns full post detail payload.

Common error scenarios

  • 400: invalid numeric path params.
  • 404: post not found for provided id + postId.
  • 422: cannot pin/unpin a post that is already soft-deleted.

List Channel Posts (Admin)

Endpoint

GET /api/admin/channels/{id}/posts?after_id=&before_id=&include_deleted=&limit=

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_READ

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID

Query params

ParamTypeRequiredExampleNotes
after_idstringNo10Fetch posts where id > after_id
before_idstringNo30Fetch posts where id < before_id
include_deletedbooleanNotrueDefault false; include tombstones
limitnumberNo20Default 20, max 100

Cursor behavior

  • Use only one of after_id or before_id.
  • after_id mode returns ascending post-id pages.
  • before_id mode returns descending post-id pages.
  • Channel posts are ordered by posts.id (insert order), not by publishedAt.
  • published_at / publishedAt remains metadata, not the pagination cursor key.
  • If has_more=false, cursor is empty ({}) by design.

Example request

GET /api/admin/channels/3/posts?before_id=4&limit=2

Example response

{
	"message": "Channel posts fetched successfully",
	"data": {
		"items": [
				{
					"id": 6,
					"channelId": 3,
					"publishedAt": "2026-02-25T06:17:19.312Z",
				"createdByAdminId": "019c8a2e-ad60-75ae-8543-953d64e93489",
				"type": "TEXT",
				"bodyText": "Post 3 in channel 3",
				"linkUrl": null,
				"chartPayloadJson": null,
				"isPinned": false,
				"pinnedAt": null,
				"isDeleted": false,
				"deletedAt": null,
				"deletedByAdminId": null,
				"attachments": [],
				"createdAt": "2026-02-25T06:17:19.312Z",
				"updatedAt": "2026-02-25T06:17:19.312Z"
			},
				{
					"id": 5,
					"channelId": 3,
					"publishedAt": "2026-02-25T06:17:08.216Z",
				"createdByAdminId": "019c8a2e-ad60-75ae-8543-953d64e93489",
				"type": "TEXT",
				"bodyText": "Post 2 in channel 3",
				"linkUrl": null,
				"chartPayloadJson": null,
				"isPinned": false,
				"pinnedAt": null,
				"isDeleted": false,
				"deletedAt": null,
				"deletedByAdminId": null,
				"attachments": [],
				"createdAt": "2026-02-25T06:17:08.216Z",
				"updatedAt": "2026-02-25T06:17:08.216Z"
			}
		],
		"cursor": {
			"next_after_id": "3",
			"next_before_id": "2"
		},
		"limit": 2,
		"has_more": true,
		"count": 2
	}
}

Common error scenarios

  • 400: invalid channel id.
  • 422: both after_id and before_id supplied.
  • 422: invalid id cursor format.
  • 404: channel not found.

Get Channel Post Detail (Admin)

Endpoint

GET /api/admin/posts/{postId}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_READ

Path params

ParamTypeRequiredExampleNotes
postIdnumberYes101Post ID

Behavior

  • Returns full admin post detail.
  • If post is soft-deleted, payload remains tombstone-redacted.

Common error scenarios

  • 400: invalid postId.
  • 404: post not found.

Update Channel Post

Endpoint

PATCH /api/admin/posts/{postId}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
postIdnumberYes101Post ID

What this API accepts

FieldTypeRequiredNotes
typestringNoTEXT, LINK, CHART, IMAGE, FILE
body_textstring | nullNoOptional text body
link_urlstring | nullNoOptional link target
chart_payload_jsonobject | nullNoOptional chart payload
attachmentsobject[]NoStructured attachment metadata (same shape as create)
published_atstringNoISO datetime
is_pinnedbooleanNoPin state

Validation rules

  • At least one field is required.
  • Final merged payload must satisfy type rules (same as create post).
  • Soft-deleted posts cannot be updated (restore first).

Raw Request Body (Update text + pin)

{
	"body_text": "Updated admin copy",
	"is_pinned": true
}

Common error scenarios

  • 400: invalid postId.
  • 422: empty patch body.
  • 422: invalid type/field combination after merge.
  • 422: post is deleted (must restore first).
  • 404: post not found.

Delete Channel Post (Soft Delete)

Endpoint

DELETE /api/admin/posts/{postId}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_DELETE

Path params

ParamTypeRequiredExampleNotes
postIdnumberYes101Post ID

Raw request body

{}

Behavior

  • Marks post as deleted (isDeleted=true, deletedAt, deletedByAdminId).
  • Post remains as tombstone for feed continuity.
  • Response is redacted for deleted posts (bodyText, linkUrl, chartPayloadJson become null; attachments becomes []).
  • Repeating delete on an already deleted post returns current deleted state.

Common error scenarios

  • 400: invalid postId path param.
  • 404: post not found.

Restore Channel Post

Endpoint

POST /api/admin/posts/{postId}/restore

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
postIdnumberYes101Post ID

Raw request body

{}

Behavior

  • Restores a soft-deleted post (isDeleted=false).
  • Clears deletedAt and deletedByAdminId.
  • If post is already active, returns current post state.

Common error scenarios

  • 400: invalid postId.
  • 404: post not found.

Create Visibility Rule

Endpoint

POST /api/admin/channels/{id}/visibility-rules

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Path params

ParamTypeRequiredExampleNotes
idnumberYes3Channel ID

Raw Request Body (ALLOWLIST)

{
	"rule_type": "ALLOWLIST",
	"rule_json": {
		"user_ids": [
			"019c8a2e-ad60-75ae-8543-953d64e93489",
			"019c8a2e-ad60-75ae-8543-953d64e93490"
		]
	},
	"is_active": true
}

Raw Request Body (DENYLIST / block list)

{
	"rule_type": "DENYLIST",
	"rule_json": {
		"user_ids": [
			"019c8a2e-ad60-75ae-8543-953d64e93491"
		]
	},
	"is_active": true
}

Raw Request Body (SEGMENT by subscription)

{
	"rule_type": "SEGMENT",
	"rule_json": {
		"module_ids": ["019d1166-6a5c-75d3-866b-bde058d31862"],
		"tier_ids": ["019d117a-2f61-74e8-aca8-b71e02dd22e9"],
		"subscription_statuses": ["active", "trial"]
	},
	"is_active": true
}

Notes

  • ALLOWLIST shows the post only to the listed users.
  • DENYLIST hides the post from the listed users while allowing everyone else who already passes channel/history checks.
  • ALLOWLIST and DENYLIST only support rule_json.user_ids.
  • SEGMENT supports: module_ids, plan_ids, tier_ids, subscription_statuses.
  • Segment rules are matched against the user’s active/trial subscription context.

Common error scenarios

  • 400: invalid channel id.
  • 422: invalid rule_json shape for selected rule_type.
  • 404: channel not found.

List Visibility Rules

Endpoint

GET /api/admin/channels/{id}/visibility-rules?is_active=&cursor=&limit=

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_READ

Query params

ParamTypeRequiredExampleNotes
is_activebooleanNotrueFilter by active state
cursorstringNoeyJjcmVhdGVkQXQiOiI...Opaque cursor
limitnumberNo20Default 20, max 100

Update Visibility Rule

Endpoint

PATCH /api/admin/visibility-rules/{ruleId}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Raw Request Body

{
	"is_active": false
}

or

{
	"rule_type": "DENYLIST",
	"rule_json": {
		"user_ids": ["019c8a2e-ad60-75ae-8543-953d64e93491"]
	}
}

Notes

  • At least one field is required.
  • If rule_type or rule_json changes, rule version increments.

Delete Visibility Rule

Endpoint

DELETE /api/admin/visibility-rules/{ruleId}

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Notes

  • Deleting a rule also removes post assignments via cascade.
  • Existing post visibility snapshot remains deterministic for already snapped posts.

Replace Post Visibility Rules

Endpoint

PUT /api/admin/posts/{postId}/visibility-rules

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_UPDATE

Raw Request Body

{
	"visibility_rule_ids": [11, 12]
}

Request key

  • Use the snake_case field name visibility_rule_ids.

Notes

  • This endpoint fully replaces assignments.
  • Send [] to clear all post visibility rules.
  • Assigned rules must belong to the same channel as the post and must be active.
  • This endpoint updates visibility_snapshot_json for deterministic mobile reads.

Get Post Visibility Rules

Endpoint

GET /api/admin/posts/{postId}/visibility-rules

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_READ

Response

  • Returns: postId, channelId, rules[]

Mobile Enforcement Note

The following endpoints now enforce post visibility snapshot rules in addition to channel access decisions:

  • GET /api/mobile/channels/{id}/posts
  • GET /api/mobile/posts/{postId}

Admin Discussion APIs

Create Channel Discussion

Endpoint

POST /api/admin/channels/{id}/discussion

Auth

  • Authorization: Bearer <admin-jwt>
  • Requires admin permission: Communications_CREATE

Raw request body

{
	"title": "VIP Signals Discussion",
	"required_feature_key": "chat.discussion"
}

Notes

  • Creates the single discussion attached to the channel.
  • If title is omitted, the API derives a default title from the channel.
  • A channel can have only one discussion.
  • If required_feature_key is set, users must have that feature to access discussion.

Get Channel Discussion

Endpoint

GET /api/admin/channels/{id}/discussion

Update Channel Discussion

Endpoint

PATCH /api/admin/channels/{id}/discussion

Raw request body

{
	"title": "VIP Signals Live Discussion",
	"is_enabled": true,
	"required_feature_key": "chat.discussion"
}

Notes

  • is_enabled=false disables user access to the discussion.
  • Omitting required_feature_key keeps the existing value.

List Discussion Messages

Endpoint

GET /api/admin/channels/{id}/discussion/messages?before_id=&limit=&include_deleted=

Query params

ParamTypeRequiredNotes
before_idstringNoFetch older messages
include_deletedbooleanNoInclude soft-deleted messages
limitnumberNoDefault 20, max 100

Create Admin Discussion Message

Endpoint

POST /api/admin/channels/{id}/discussion/messages

Raw request body

{
	"body": "Focus on close above resistance before entering."
}

Update Discussion Message as Admin

Endpoint

PATCH /api/admin/discussion-messages/{id}

Raw request body

{
	"body": "Updated guidance: wait for close above resistance."
}

Delete / Restore Discussion Message as Admin

Endpoints

DELETE /api/admin/discussion-messages/{id}
POST /api/admin/discussion-messages/{id}/restore

Admin Discussion Moderation APIs

Mute / Unmute / Ban / Unban User

Endpoints

POST /api/admin/channels/{id}/discussion/mute
POST /api/admin/channels/{id}/discussion/unmute
POST /api/admin/channels/{id}/discussion/ban
POST /api/admin/channels/{id}/discussion/unban

Raw request body

{
	"user_id": "019ce168-6ca4-74bb-894a-18e5fc3a3817",
	"reason": "Spam during market open.",
	"muted_until": "2026-12-31T00:00:00.000Z"
}

Notes:

  • muted_until is used only for mute.
  • Banned users cannot read or post.
  • Muted users can read but cannot post/update/delete their own messages.

Update Slow Mode

Endpoint

PATCH /api/admin/channels/{id}/discussion/slow-mode

Raw request body

{
	"enabled": true,
	"interval_seconds": 30,
	"reason": "High traffic during market open."
}

Notes:

  • Slow mode throttles user message creation.
  • Admin posting is not rate-limited by slow mode.

Product Note

Communication now uses:

  • channels for official admin broadcast
  • one optional discussion per channel for conversation

It does not currently expose:

  • standalone forums
  • topics
  • abuse report APIs
  • moderation timeline explorer APIs

On this page

Communication Admin API ReferenceAdmin APIsRealtime Side EffectAccess Policy vs MembershipBroadcast Notification AudienceDiscussion Access InheritanceCreate ChannelRaw Request Body (Free Channel / OPEN)Raw Request Body (Premium Channel / EXTERNAL_GATED)Request Field ReferenceAllowed Enum ValuesFrontend Integration NotesGated Channel Requirement (EXTERNAL_GATED)List ChannelsGet Channel DetailUpdate Channel MetadataRaw Request Body (Update title + description)Raw Request Body (Change kind + visibility)Raw Request Body (Clear description)Update Channel Access PolicyRaw Request Body (All fields)Raw Request Body (Single field update)Update Channel StatusRaw Request Body (Archive)Raw Request Body (Reactivate)Raw Request Body (Soft delete with purge schedule)Restore ChannelCreate Channel PostRaw Request Body (TEXT)Raw Request Body (IMAGE)Raw Request Body (CHART)Pin / Unpin Channel PostRaw Request Body (Pin)Raw Request Body (Unpin)List Channel Posts (Admin)Example requestExample responseGet Channel Post Detail (Admin)Update Channel PostRaw Request Body (Update text + pin)Delete Channel Post (Soft Delete)Restore Channel PostCreate Visibility RuleList Visibility RulesUpdate Visibility RuleDelete Visibility RuleReplace Post Visibility RulesGet Post Visibility RulesMobile Enforcement NoteAdmin Discussion APIsCreate Channel DiscussionGet Channel DiscussionUpdate Channel DiscussionList Discussion MessagesCreate Admin Discussion MessageUpdate Discussion Message as AdminDelete / Restore Discussion Message as AdminAdmin Discussion Moderation APIsMute / Unmute / Ban / Unban UserUpdate Slow ModeProduct Note