posterly-mcp-server 0.43.3 → 0.43.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -122,7 +122,7 @@ Add the same server definition to your Cursor MCP settings:
122
122
 
123
123
  ## Available tools
124
124
 
125
- `posterly-mcp-server@0.43.3` exposes 90 tools.
125
+ `posterly-mcp-server@0.43.4` exposes 90 tools.
126
126
 
127
127
  Public setup tools work before `POSTERLY_API_KEY` exists:
128
128
 
@@ -128,6 +128,15 @@ export interface DismissSuggestionResponse {
128
128
  ok: boolean;
129
129
  status: string;
130
130
  }
131
+ export type ApiPostApprovalStatus = 'none' | 'pending_client' | 'approved' | 'changes_requested' | 'rejected';
132
+ export interface ApiPostApproval {
133
+ status: ApiPostApprovalStatus;
134
+ asset_status: ApiPostApprovalStatus;
135
+ caption_status: ApiPostApprovalStatus;
136
+ waiting_on: 'client' | 'team' | null;
137
+ requested_at: string | null;
138
+ completed_at: string | null;
139
+ }
131
140
  export interface Post {
132
141
  id: number;
133
142
  content: string;
@@ -144,6 +153,9 @@ export interface Post {
144
153
  reel_cover_url?: string | null;
145
154
  reel_cover_method?: string | null;
146
155
  reel_thumb_offset?: number | null;
156
+ brand_id?: string | null;
157
+ content_plan_id?: string | null;
158
+ approval?: ApiPostApproval;
147
159
  }
148
160
  export interface InstagramPostSettings {
149
161
  __type?: 'instagram' | 'instagram-standalone';
@@ -1090,6 +1102,8 @@ export declare class PosterlyClient {
1090
1102
  limit?: number;
1091
1103
  offset?: number;
1092
1104
  workspace_id?: string;
1105
+ approval_status?: string;
1106
+ brand_id?: string;
1093
1107
  }): Promise<{
1094
1108
  posts: Post[];
1095
1109
  total: number;
@@ -257,6 +257,10 @@ export class PosterlyClient {
257
257
  searchParams.set('offset', String(params.offset));
258
258
  if (params?.workspace_id)
259
259
  searchParams.set('workspace_id', params.workspace_id);
260
+ if (params?.approval_status)
261
+ searchParams.set('approval_status', params.approval_status);
262
+ if (params?.brand_id)
263
+ searchParams.set('brand_id', params.brand_id);
260
264
  const qs = searchParams.toString();
261
265
  return this.request('GET', `/posts${qs ? `?${qs}` : ''}`);
262
266
  }
@@ -1 +1 @@
1
- export declare const POSTERLY_MCP_VERSION = "0.43.3";
1
+ export declare const POSTERLY_MCP_VERSION = "0.43.4";
@@ -5,4 +5,4 @@
5
5
  // tool set (minus the intentional pre-auth signup tools that only this stdio
6
6
  // package exposes). `npm run check:mcp-parity` enforces both the version match
7
7
  // and the tool-list match, and runs in the pre-commit hook.
8
- export const POSTERLY_MCP_VERSION = '0.43.3';
8
+ export const POSTERLY_MCP_VERSION = '0.43.4';
@@ -5,7 +5,7 @@ export declare const createWebhookTool: {
5
5
  description: string;
6
6
  inputSchema: z.ZodObject<{
7
7
  url: z.ZodString;
8
- events: z.ZodOptional<z.ZodArray<z.ZodEnum<["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced"]>, "many">>;
8
+ events: z.ZodOptional<z.ZodArray<z.ZodEnum<["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced", "approval.requested", "approval.approved", "approval.changes_requested", "approval.rejected", "approval.commented"]>, "many">>;
9
9
  workspace_id: z.ZodOptional<z.ZodString>;
10
10
  description: z.ZodOptional<z.ZodString>;
11
11
  is_active: z.ZodOptional<z.ZodBoolean>;
@@ -15,14 +15,14 @@ export declare const createWebhookTool: {
15
15
  confirm: true;
16
16
  description?: string | undefined;
17
17
  workspace_id?: string | undefined;
18
- events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
18
+ events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced" | "approval.requested" | "approval.approved" | "approval.changes_requested" | "approval.rejected" | "approval.commented")[] | undefined;
19
19
  is_active?: boolean | undefined;
20
20
  }, {
21
21
  url: string;
22
22
  confirm: true;
23
23
  description?: string | undefined;
24
24
  workspace_id?: string | undefined;
25
- events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
25
+ events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced" | "approval.requested" | "approval.approved" | "approval.changes_requested" | "approval.rejected" | "approval.commented")[] | undefined;
26
26
  is_active?: boolean | undefined;
27
27
  }>;
28
28
  execute(client: PosterlyClient, input: {
@@ -9,18 +9,24 @@ export declare const listPostsTool: {
9
9
  account_id: z.ZodOptional<z.ZodString>;
10
10
  limit: z.ZodOptional<z.ZodNumber>;
11
11
  workspace_id: z.ZodOptional<z.ZodString>;
12
+ approval_status: z.ZodOptional<z.ZodEnum<["none", "pending_client", "approved", "changes_requested", "rejected"]>>;
13
+ brand_id: z.ZodOptional<z.ZodString>;
12
14
  }, "strip", z.ZodTypeAny, {
13
15
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "threads" | "linkedin" | "youtube" | "pinterest" | "google_business" | "x" | "telegram" | "bluesky" | "discord" | "slack" | "mastodon" | "devto" | "hashnode" | "wordpress" | "lemmy" | "gmb" | "google-business" | "google_business_profile" | undefined;
14
16
  status?: string | undefined;
15
17
  workspace_id?: string | undefined;
16
18
  account_id?: string | undefined;
17
19
  limit?: number | undefined;
20
+ approval_status?: "none" | "pending_client" | "approved" | "changes_requested" | "rejected" | undefined;
21
+ brand_id?: string | undefined;
18
22
  }, {
19
23
  platform?: "instagram" | "instagram-standalone" | "facebook" | "tiktok" | "twitter" | "threads" | "linkedin" | "youtube" | "pinterest" | "google_business" | "x" | "telegram" | "bluesky" | "discord" | "slack" | "mastodon" | "devto" | "hashnode" | "wordpress" | "lemmy" | "gmb" | "google-business" | "google_business_profile" | undefined;
20
24
  status?: string | undefined;
21
25
  workspace_id?: string | undefined;
22
26
  account_id?: string | undefined;
23
27
  limit?: number | undefined;
28
+ approval_status?: "none" | "pending_client" | "approved" | "changes_requested" | "rejected" | undefined;
29
+ brand_id?: string | undefined;
24
30
  }>;
25
31
  execute(client: PosterlyClient, input: {
26
32
  status?: string;
@@ -28,5 +34,7 @@ export declare const listPostsTool: {
28
34
  account_id?: string;
29
35
  limit?: number;
30
36
  workspace_id?: string;
37
+ approval_status?: string;
38
+ brand_id?: string;
31
39
  }): Promise<string>;
32
40
  };
@@ -3,7 +3,7 @@ import { dashboardUrlForPostList, formatLocalDateTime, truncateText } from '../l
3
3
  import { SUPPORTED_PLATFORM_INPUTS, SUPPORTED_PLATFORM_IDS } from '../generated/platform-manifest.js';
4
4
  export const listPostsTool = {
5
5
  name: 'list_posts',
6
- description: 'List upcoming or recent posts. Filter by status (scheduled, published, failed, draft), platform, account_id, or workspace_id. If workspace_id is omitted, posts across every workspace the caller is a member of are returned.',
6
+ description: 'List upcoming or recent posts. Filter by status (scheduled, published, failed, draft), platform, account_id, workspace_id, approval_status, or brand_id. If workspace_id is omitted, posts across every workspace the caller is a member of are returned.',
7
7
  inputSchema: z.object({
8
8
  status: z
9
9
  .string()
@@ -27,6 +27,14 @@ export const listPostsTool = {
27
27
  .string()
28
28
  .optional()
29
29
  .describe('Filter to posts in a specific workspace (get IDs via whoami).'),
30
+ approval_status: z
31
+ .enum(['none', 'pending_client', 'approved', 'changes_requested', 'rejected'])
32
+ .optional()
33
+ .describe('Filter by client review approval status. pending_client means the post is waiting on the client.'),
34
+ brand_id: z
35
+ .string()
36
+ .optional()
37
+ .describe('Filter to posts assigned to a specific brand/client (the id from list_brands).'),
30
38
  }),
31
39
  async execute(client, input) {
32
40
  const { posts, total } = await client.listPosts({
@@ -39,7 +47,18 @@ export const listPostsTool = {
39
47
  const lines = posts.map((p) => {
40
48
  const date = formatLocalDateTime(p.scheduled_at);
41
49
  const caption = truncateText(p.content, 60);
42
- return `• [${p.status}] #${p.id}: ${caption} (${date})`;
50
+ const approvalBits = [];
51
+ if (p.approval && p.approval.status !== 'none') {
52
+ approvalBits.push(`approval: ${p.approval.status}`);
53
+ if (p.approval.waiting_on)
54
+ approvalBits.push(`waiting on: ${p.approval.waiting_on}`);
55
+ }
56
+ if (p.brand_id)
57
+ approvalBits.push(`brand: ${p.brand_id}`);
58
+ if (p.content_plan_id)
59
+ approvalBits.push(`plan: ${p.content_plan_id}`);
60
+ const approvalSuffix = approvalBits.length > 0 ? ` [${approvalBits.join(', ')}]` : '';
61
+ return `• [${p.status}] #${p.id}: ${caption} (${date})${approvalSuffix}`;
43
62
  });
44
63
  return [
45
64
  `Posts (${posts.length} of ${total}):`,
@@ -27,8 +27,8 @@ export declare const submitAgentFeedbackInputSchema: z.ZodObject<{
27
27
  source: "mcp" | "cli" | "rest" | "skill";
28
28
  tool: string;
29
29
  outcome: "success" | "error" | "abandoned";
30
- error_code?: string | undefined;
31
30
  client?: string | undefined;
31
+ error_code?: string | undefined;
32
32
  comment?: string | undefined;
33
33
  context?: {
34
34
  request_id?: string | undefined;
@@ -40,8 +40,8 @@ export declare const submitAgentFeedbackInputSchema: z.ZodObject<{
40
40
  source: "mcp" | "cli" | "rest" | "skill";
41
41
  tool: string;
42
42
  outcome: "success" | "error" | "abandoned";
43
- error_code?: string | undefined;
44
43
  client?: string | undefined;
44
+ error_code?: string | undefined;
45
45
  comment?: string | undefined;
46
46
  context?: {
47
47
  request_id?: string | undefined;
@@ -81,8 +81,8 @@ export declare const submitAgentFeedbackTool: {
81
81
  source: "mcp" | "cli" | "rest" | "skill";
82
82
  tool: string;
83
83
  outcome: "success" | "error" | "abandoned";
84
- error_code?: string | undefined;
85
84
  client?: string | undefined;
85
+ error_code?: string | undefined;
86
86
  comment?: string | undefined;
87
87
  context?: {
88
88
  request_id?: string | undefined;
@@ -94,8 +94,8 @@ export declare const submitAgentFeedbackTool: {
94
94
  source: "mcp" | "cli" | "rest" | "skill";
95
95
  tool: string;
96
96
  outcome: "success" | "error" | "abandoned";
97
- error_code?: string | undefined;
98
97
  client?: string | undefined;
98
+ error_code?: string | undefined;
99
99
  comment?: string | undefined;
100
100
  context?: {
101
101
  request_id?: string | undefined;
@@ -21,9 +21,9 @@ export declare const submitProductFeedbackInputSchema: z.ZodObject<{
21
21
  title: string;
22
22
  confirm: true;
23
23
  category: "bug" | "idea" | "feedback";
24
+ client?: string | undefined;
24
25
  description?: string | undefined;
25
26
  source?: "mcp" | "cli" | "rest" | "skill" | undefined;
26
- client?: string | undefined;
27
27
  context?: {
28
28
  request_id?: string | undefined;
29
29
  related_tool?: string | undefined;
@@ -32,9 +32,9 @@ export declare const submitProductFeedbackInputSchema: z.ZodObject<{
32
32
  title: string;
33
33
  confirm: true;
34
34
  category: "bug" | "idea" | "feedback";
35
+ client?: string | undefined;
35
36
  description?: string | undefined;
36
37
  source?: "mcp" | "cli" | "rest" | "skill" | undefined;
37
- client?: string | undefined;
38
38
  context?: {
39
39
  request_id?: string | undefined;
40
40
  related_tool?: string | undefined;
@@ -65,9 +65,9 @@ export declare const submitProductFeedbackTool: {
65
65
  title: string;
66
66
  confirm: true;
67
67
  category: "bug" | "idea" | "feedback";
68
+ client?: string | undefined;
68
69
  description?: string | undefined;
69
70
  source?: "mcp" | "cli" | "rest" | "skill" | undefined;
70
- client?: string | undefined;
71
71
  context?: {
72
72
  request_id?: string | undefined;
73
73
  related_tool?: string | undefined;
@@ -76,9 +76,9 @@ export declare const submitProductFeedbackTool: {
76
76
  title: string;
77
77
  confirm: true;
78
78
  category: "bug" | "idea" | "feedback";
79
+ client?: string | undefined;
79
80
  description?: string | undefined;
80
81
  source?: "mcp" | "cli" | "rest" | "skill" | undefined;
81
- client?: string | undefined;
82
82
  context?: {
83
83
  request_id?: string | undefined;
84
84
  related_tool?: string | undefined;
@@ -6,7 +6,7 @@ export declare const updateWebhookTool: {
6
6
  inputSchema: z.ZodObject<{
7
7
  webhook_id: z.ZodString;
8
8
  url: z.ZodOptional<z.ZodString>;
9
- events: z.ZodOptional<z.ZodArray<z.ZodEnum<["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced"]>, "many">>;
9
+ events: z.ZodOptional<z.ZodArray<z.ZodEnum<["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced", "approval.requested", "approval.approved", "approval.changes_requested", "approval.rejected", "approval.commented"]>, "many">>;
10
10
  workspace_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNull]>>;
11
11
  description: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNull]>>;
12
12
  is_active: z.ZodOptional<z.ZodBoolean>;
@@ -17,7 +17,7 @@ export declare const updateWebhookTool: {
17
17
  description?: string | null | undefined;
18
18
  workspace_id?: string | null | undefined;
19
19
  url?: string | undefined;
20
- events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
20
+ events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced" | "approval.requested" | "approval.approved" | "approval.changes_requested" | "approval.rejected" | "approval.commented")[] | undefined;
21
21
  is_active?: boolean | undefined;
22
22
  }, {
23
23
  confirm: true;
@@ -25,7 +25,7 @@ export declare const updateWebhookTool: {
25
25
  description?: string | null | undefined;
26
26
  workspace_id?: string | null | undefined;
27
27
  url?: string | undefined;
28
- events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced")[] | undefined;
28
+ events?: ("webhook.test" | "post.created" | "post.updated" | "post.deleted" | "post.publishing" | "post.published" | "post.failed" | "account.disconnected" | "analytics.synced" | "approval.requested" | "approval.approved" | "approval.changes_requested" | "approval.rejected" | "approval.commented")[] | undefined;
29
29
  is_active?: boolean | undefined;
30
30
  }>;
31
31
  execute(client: PosterlyClient, input: {
@@ -1,3 +1,3 @@
1
1
  import { z } from 'zod';
2
- export declare const WEBHOOK_EVENTS: readonly ["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced"];
3
- export declare const webhookEventSchema: z.ZodEnum<["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced"]>;
2
+ export declare const WEBHOOK_EVENTS: readonly ["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced", "approval.requested", "approval.approved", "approval.changes_requested", "approval.rejected", "approval.commented"];
3
+ export declare const webhookEventSchema: z.ZodEnum<["webhook.test", "post.created", "post.updated", "post.deleted", "post.publishing", "post.published", "post.failed", "account.disconnected", "analytics.synced", "approval.requested", "approval.approved", "approval.changes_requested", "approval.rejected", "approval.commented"]>;
@@ -9,5 +9,10 @@ export const WEBHOOK_EVENTS = [
9
9
  'post.failed',
10
10
  'account.disconnected',
11
11
  'analytics.synced',
12
+ 'approval.requested',
13
+ 'approval.approved',
14
+ 'approval.changes_requested',
15
+ 'approval.rejected',
16
+ 'approval.commented',
12
17
  ];
13
18
  export const webhookEventSchema = z.enum(WEBHOOK_EVENTS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posterly-mcp-server",
3
- "version": "0.43.3",
3
+ "version": "0.43.4",
4
4
  "mcpName": "io.github.awpthorp/posterly",
5
5
  "description": "MCP server for posterly: schedule and publish social media posts across 18 platforms from any MCP client (Claude, ChatGPT, Cursor, Windsurf, Cline, and more)",
6
6
  "license": "MIT",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.awpthorp/posterly",
4
4
  "title": "posterly",
5
5
  "description": "Validate, schedule, publish, and analyze social content across 18 platforms with posterly.",
6
- "version": "0.43.3",
6
+ "version": "0.43.4",
7
7
  "websiteUrl": "https://www.poster.ly/mcp",
8
8
  "repository": {
9
9
  "url": "https://github.com/awpthorp/posterly",
@@ -14,7 +14,7 @@
14
14
  {
15
15
  "registryType": "npm",
16
16
  "identifier": "posterly-mcp-server",
17
- "version": "0.43.3",
17
+ "version": "0.43.4",
18
18
  "transport": {
19
19
  "type": "stdio"
20
20
  },
@@ -138,6 +138,17 @@ export interface DismissSuggestionResponse {
138
138
  status: string;
139
139
  }
140
140
 
141
+ export type ApiPostApprovalStatus = 'none' | 'pending_client' | 'approved' | 'changes_requested' | 'rejected';
142
+
143
+ export interface ApiPostApproval {
144
+ status: ApiPostApprovalStatus;
145
+ asset_status: ApiPostApprovalStatus;
146
+ caption_status: ApiPostApprovalStatus;
147
+ waiting_on: 'client' | 'team' | null;
148
+ requested_at: string | null;
149
+ completed_at: string | null;
150
+ }
151
+
141
152
  export interface Post {
142
153
  id: number;
143
154
  content: string;
@@ -154,6 +165,9 @@ export interface Post {
154
165
  reel_cover_url?: string | null;
155
166
  reel_cover_method?: string | null;
156
167
  reel_thumb_offset?: number | null;
168
+ brand_id?: string | null;
169
+ content_plan_id?: string | null;
170
+ approval?: ApiPostApproval;
157
171
  }
158
172
 
159
173
  export interface InstagramPostSettings {
@@ -1354,6 +1368,8 @@ export class PosterlyClient {
1354
1368
  limit?: number;
1355
1369
  offset?: number;
1356
1370
  workspace_id?: string;
1371
+ approval_status?: string;
1372
+ brand_id?: string;
1357
1373
  }): Promise<{ posts: Post[]; total: number }> {
1358
1374
  const searchParams = new URLSearchParams();
1359
1375
  if (params?.status) searchParams.set('status', params.status);
@@ -1362,6 +1378,8 @@ export class PosterlyClient {
1362
1378
  if (params?.limit) searchParams.set('limit', String(params.limit));
1363
1379
  if (params?.offset) searchParams.set('offset', String(params.offset));
1364
1380
  if (params?.workspace_id) searchParams.set('workspace_id', params.workspace_id);
1381
+ if (params?.approval_status) searchParams.set('approval_status', params.approval_status);
1382
+ if (params?.brand_id) searchParams.set('brand_id', params.brand_id);
1365
1383
 
1366
1384
  const qs = searchParams.toString();
1367
1385
  return this.request('GET', `/posts${qs ? `?${qs}` : ''}`);
@@ -5,4 +5,4 @@
5
5
  // tool set (minus the intentional pre-auth signup tools that only this stdio
6
6
  // package exposes). `npm run check:mcp-parity` enforces both the version match
7
7
  // and the tool-list match, and runs in the pre-commit hook.
8
- export const POSTERLY_MCP_VERSION = '0.43.3';
8
+ export const POSTERLY_MCP_VERSION = '0.43.4';
@@ -6,7 +6,7 @@ import { SUPPORTED_PLATFORM_INPUTS, SUPPORTED_PLATFORM_IDS } from '../generated/
6
6
  export const listPostsTool = {
7
7
  name: 'list_posts',
8
8
  description:
9
- 'List upcoming or recent posts. Filter by status (scheduled, published, failed, draft), platform, account_id, or workspace_id. If workspace_id is omitted, posts across every workspace the caller is a member of are returned.',
9
+ 'List upcoming or recent posts. Filter by status (scheduled, published, failed, draft), platform, account_id, workspace_id, approval_status, or brand_id. If workspace_id is omitted, posts across every workspace the caller is a member of are returned.',
10
10
  inputSchema: z.object({
11
11
  status: z
12
12
  .string()
@@ -30,6 +30,14 @@ export const listPostsTool = {
30
30
  .string()
31
31
  .optional()
32
32
  .describe('Filter to posts in a specific workspace (get IDs via whoami).'),
33
+ approval_status: z
34
+ .enum(['none', 'pending_client', 'approved', 'changes_requested', 'rejected'])
35
+ .optional()
36
+ .describe('Filter by client review approval status. pending_client means the post is waiting on the client.'),
37
+ brand_id: z
38
+ .string()
39
+ .optional()
40
+ .describe('Filter to posts assigned to a specific brand/client (the id from list_brands).'),
33
41
  }),
34
42
 
35
43
  async execute(
@@ -40,6 +48,8 @@ export const listPostsTool = {
40
48
  account_id?: string;
41
49
  limit?: number;
42
50
  workspace_id?: string;
51
+ approval_status?: string;
52
+ brand_id?: string;
43
53
  }
44
54
  ) {
45
55
  const { posts, total } = await client.listPosts({
@@ -54,7 +64,15 @@ export const listPostsTool = {
54
64
  const lines = posts.map((p) => {
55
65
  const date = formatLocalDateTime(p.scheduled_at);
56
66
  const caption = truncateText(p.content, 60);
57
- return `• [${p.status}] #${p.id}: ${caption} (${date})`;
67
+ const approvalBits: string[] = [];
68
+ if (p.approval && p.approval.status !== 'none') {
69
+ approvalBits.push(`approval: ${p.approval.status}`);
70
+ if (p.approval.waiting_on) approvalBits.push(`waiting on: ${p.approval.waiting_on}`);
71
+ }
72
+ if (p.brand_id) approvalBits.push(`brand: ${p.brand_id}`);
73
+ if (p.content_plan_id) approvalBits.push(`plan: ${p.content_plan_id}`);
74
+ const approvalSuffix = approvalBits.length > 0 ? ` [${approvalBits.join(', ')}]` : '';
75
+ return `• [${p.status}] #${p.id}: ${caption} (${date})${approvalSuffix}`;
58
76
  });
59
77
 
60
78
  return [
@@ -10,6 +10,11 @@ export const WEBHOOK_EVENTS = [
10
10
  'post.failed',
11
11
  'account.disconnected',
12
12
  'analytics.synced',
13
+ 'approval.requested',
14
+ 'approval.approved',
15
+ 'approval.changes_requested',
16
+ 'approval.rejected',
17
+ 'approval.commented',
13
18
  ] as const;
14
19
 
15
20
  export const webhookEventSchema = z.enum(WEBHOOK_EVENTS);