x-developer 2.3.0

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.
@@ -0,0 +1,1163 @@
1
+ # Xquik TypeScript Type Definitions
2
+
3
+ Copy-pasteable TypeScript types for all Xquik API objects.
4
+
5
+ ## Contents
6
+
7
+ - [Account](#account)
8
+ - [API Keys](#api-keys)
9
+ - [Credits](#credits)
10
+ - [Monitors](#monitors)
11
+ - [Events](#events)
12
+ - [Webhooks](#webhooks)
13
+ - [Draws](#draws)
14
+ - [Extractions](#extractions)
15
+ - [X API](#x-api)
16
+ - [Trends](#trends)
17
+ - [Automations](#automations)
18
+ - [Support](#support)
19
+ - [Error](#error)
20
+ - [Request Bodies](#request-bodies)
21
+ - [MCP Output Schemas](#mcp-output-schemas)
22
+
23
+ ```typescript
24
+ // ─── Account ─────────────────────────────────────────────
25
+
26
+ interface Account {
27
+ plan: "active" | "inactive";
28
+ pricingVersion: number;
29
+ monitorsAllowed: number;
30
+ monitorsUsed: number;
31
+ currentPeriod?: {
32
+ start: string;
33
+ end: string;
34
+ usagePercent: number;
35
+ };
36
+ }
37
+
38
+ // ─── Credits ────────────────────────────────────────────
39
+
40
+ interface CreditBalance {
41
+ balance: number; // Current credit balance
42
+ lifetimePurchased: number; // Total credits purchased
43
+ lifetimeUsed: number; // Total credits consumed
44
+ autoTopUp: boolean; // Whether auto top-up is enabled
45
+ }
46
+
47
+ interface CreditTopUpResponse {
48
+ url: string; // Checkout URL
49
+ }
50
+
51
+ // ─── API Keys ────────────────────────────────────────────
52
+
53
+ interface ApiKeyCreated {
54
+ id: string;
55
+ fullKey: string;
56
+ prefix: string;
57
+ name: string;
58
+ createdAt: string;
59
+ }
60
+
61
+ interface ApiKey {
62
+ id: string;
63
+ name: string;
64
+ prefix: string;
65
+ isActive: boolean;
66
+ createdAt: string;
67
+ lastUsedAt?: string;
68
+ }
69
+
70
+ // ─── Monitors ────────────────────────────────────────────
71
+
72
+ interface Monitor {
73
+ id: string;
74
+ username: string;
75
+ xUserId: string;
76
+ eventTypes: EventType[];
77
+ isActive: boolean;
78
+ createdAt: string;
79
+ }
80
+
81
+ type EventType =
82
+ | "tweet.new"
83
+ | "tweet.quote"
84
+ | "tweet.reply"
85
+ | "tweet.retweet"
86
+ | "follower.gained"
87
+ | "follower.lost";
88
+
89
+ // ─── Events ──────────────────────────────────────────────
90
+
91
+ interface Event {
92
+ id: string;
93
+ type: EventType;
94
+ monitorId: string;
95
+ username: string;
96
+ occurredAt: string;
97
+ data: EventData;
98
+ xEventId?: string;
99
+ }
100
+
101
+ // Tweet events (tweet.new, tweet.reply, tweet.quote, tweet.retweet)
102
+ interface TweetEventData {
103
+ tweetId: string;
104
+ text: string;
105
+ metrics: {
106
+ likes: number;
107
+ retweets: number;
108
+ replies: number;
109
+ };
110
+ // tweet.quote only
111
+ quotedTweetId?: string;
112
+ quotedUsername?: string;
113
+ // tweet.reply only
114
+ inReplyToTweetId?: string;
115
+ inReplyToUsername?: string;
116
+ // tweet.retweet only
117
+ retweetedTweetId?: string;
118
+ retweetedUsername?: string;
119
+ }
120
+
121
+ // Follower events (follower.gained, follower.lost)
122
+ interface FollowerEventData {
123
+ followerId: string;
124
+ followerUsername: string;
125
+ followerName: string;
126
+ followerFollowersCount: number;
127
+ followerVerified: boolean;
128
+ }
129
+
130
+ type EventData = TweetEventData | FollowerEventData;
131
+
132
+ interface EventList {
133
+ events: Event[];
134
+ hasMore: boolean;
135
+ nextCursor?: string;
136
+ }
137
+
138
+ // ─── Webhooks ────────────────────────────────────────────
139
+
140
+ interface WebhookCreated {
141
+ id: string;
142
+ url: string;
143
+ eventTypes: EventType[];
144
+ secret: string;
145
+ createdAt: string;
146
+ }
147
+
148
+ interface Webhook {
149
+ id: string;
150
+ url: string;
151
+ eventTypes: EventType[];
152
+ isActive: boolean;
153
+ createdAt: string;
154
+ }
155
+
156
+ interface Delivery {
157
+ id: string;
158
+ streamEventId: string;
159
+ status: "pending" | "delivered" | "failed" | "exhausted";
160
+ attempts: number;
161
+ lastStatusCode?: number;
162
+ lastError?: string;
163
+ createdAt: string;
164
+ deliveredAt?: string;
165
+ }
166
+
167
+ interface WebhookPayload {
168
+ eventType: EventType;
169
+ username: string;
170
+ data: EventData;
171
+ }
172
+
173
+ // ─── Draws ───────────────────────────────────────────────
174
+
175
+ interface Draw {
176
+ id: string;
177
+ tweetId: string;
178
+ tweetUrl: string;
179
+ tweetText: string;
180
+ tweetAuthorUsername: string;
181
+ tweetLikeCount: number;
182
+ tweetRetweetCount: number;
183
+ tweetReplyCount: number;
184
+ tweetQuoteCount: number;
185
+ status: "pending" | "running" | "completed" | "failed";
186
+ totalEntries: number;
187
+ validEntries: number;
188
+ createdAt: string;
189
+ drawnAt?: string;
190
+ }
191
+
192
+ interface DrawListItem {
193
+ id: string;
194
+ tweetUrl: string;
195
+ status: "pending" | "running" | "completed" | "failed";
196
+ totalEntries: number;
197
+ validEntries: number;
198
+ createdAt: string;
199
+ drawnAt?: string;
200
+ }
201
+
202
+ interface DrawWinner {
203
+ position: number;
204
+ authorUsername: string;
205
+ tweetId: string;
206
+ isBackup: boolean;
207
+ }
208
+
209
+ interface DrawList {
210
+ draws: DrawListItem[];
211
+ hasMore: boolean;
212
+ nextCursor?: string;
213
+ }
214
+
215
+ interface CreateDrawRequest {
216
+ tweetUrl: string;
217
+ winnerCount?: number;
218
+ backupCount?: number;
219
+ uniqueAuthorsOnly?: boolean;
220
+ mustRetweet?: boolean;
221
+ mustFollowUsername?: string;
222
+ filterMinFollowers?: number;
223
+ filterAccountAgeDays?: number;
224
+ filterLanguage?: string;
225
+ requiredKeywords?: string[];
226
+ requiredHashtags?: string[];
227
+ requiredMentions?: string[];
228
+ }
229
+
230
+ // ─── Extractions ─────────────────────────────────────────
231
+
232
+ type ExtractionToolType =
233
+ | "article_extractor"
234
+ | "community_extractor"
235
+ | "community_moderator_explorer"
236
+ | "community_post_extractor"
237
+ | "community_search"
238
+ | "follower_explorer"
239
+ | "following_explorer"
240
+ | "list_follower_explorer"
241
+ | "list_member_extractor"
242
+ | "list_post_extractor"
243
+ | "mention_extractor"
244
+ | "people_search"
245
+ | "post_extractor"
246
+ | "quote_extractor"
247
+ | "reply_extractor"
248
+ | "repost_extractor"
249
+ | "space_explorer"
250
+ | "thread_extractor"
251
+ | "tweet_search_extractor"
252
+ | "verified_follower_explorer";
253
+
254
+ interface ExtractionJob {
255
+ id: string;
256
+ toolType: ExtractionToolType;
257
+ status: "pending" | "running" | "completed" | "failed";
258
+ totalResults: number;
259
+ targetTweetId?: string;
260
+ targetUsername?: string;
261
+ targetUserId?: string;
262
+ targetCommunityId?: string;
263
+ targetListId?: string;
264
+ targetSpaceId?: string;
265
+ searchQuery?: string;
266
+ resultsLimit?: number; // Max results to extract. Stops early instead of fetching all. Omit for all.
267
+ errorMessage?: string;
268
+ createdAt: string;
269
+ completedAt?: string;
270
+ }
271
+
272
+ interface ExtractionResult {
273
+ id: string;
274
+ xUserId: string;
275
+ xUsername?: string;
276
+ xDisplayName?: string;
277
+ xFollowersCount?: number;
278
+ xVerified?: boolean;
279
+ xProfileImageUrl?: string;
280
+ tweetId?: string;
281
+ tweetText?: string;
282
+ tweetCreatedAt?: string;
283
+ createdAt: string;
284
+ }
285
+
286
+ interface ExtractionList {
287
+ extractions: ExtractionJob[];
288
+ hasMore: boolean;
289
+ nextCursor?: string;
290
+ }
291
+
292
+ interface ExtractionEstimate {
293
+ allowed: boolean;
294
+ source: "replyCount" | "retweetCount" | "quoteCount" | "followers" | "unknown";
295
+ estimatedResults: number;
296
+ usagePercent: number;
297
+ projectedPercent: number;
298
+ error?: string;
299
+ }
300
+
301
+ interface CreateExtractionRequest {
302
+ toolType: ExtractionToolType;
303
+ targetTweetId?: string;
304
+ targetUsername?: string;
305
+ targetCommunityId?: string;
306
+ targetListId?: string;
307
+ targetSpaceId?: string;
308
+ searchQuery?: string;
309
+ resultsLimit?: number; // Max results to extract. Stops early instead of fetching all. Omit for all.
310
+ // Tweet search filters (tweet_search_extractor only)
311
+ fromUser?: string;
312
+ toUser?: string;
313
+ mentioning?: string;
314
+ language?: string;
315
+ sinceDate?: string; // YYYY-MM-DD
316
+ untilDate?: string; // YYYY-MM-DD
317
+ mediaType?: 'images' | 'videos' | 'gifs' | 'media';
318
+ minFaves?: number;
319
+ minRetweets?: number;
320
+ minReplies?: number;
321
+ verifiedOnly?: boolean;
322
+ replies?: 'include' | 'exclude' | 'only';
323
+ retweets?: 'include' | 'exclude' | 'only';
324
+ exactPhrase?: string;
325
+ excludeWords?: string;
326
+ advancedQuery?: string;
327
+ }
328
+
329
+ // ─── X API ───────────────────────────────────────────────
330
+
331
+ interface TweetMediaItem {
332
+ mediaUrl: string;
333
+ type: string; // "photo" | "video" | "animated_gif"
334
+ url: string;
335
+ }
336
+
337
+ interface Tweet {
338
+ id: string;
339
+ text: string;
340
+ createdAt?: string;
341
+ retweetCount: number;
342
+ replyCount: number;
343
+ likeCount: number;
344
+ quoteCount: number;
345
+ viewCount: number;
346
+ bookmarkCount: number;
347
+ media?: TweetMediaItem[];
348
+ }
349
+
350
+ interface TweetAuthor {
351
+ id: string;
352
+ username: string;
353
+ followers: number;
354
+ verified: boolean;
355
+ profilePicture?: string;
356
+ }
357
+
358
+ interface TweetSearchResult {
359
+ id: string;
360
+ text: string;
361
+ createdAt: string;
362
+ likeCount: number; // Omitted if unavailable
363
+ retweetCount: number; // Omitted if unavailable
364
+ replyCount: number; // Omitted if unavailable
365
+ media?: TweetMediaItem[];
366
+ author: {
367
+ id: string;
368
+ username: string;
369
+ name: string;
370
+ verified: boolean;
371
+ };
372
+ }
373
+
374
+ interface UserProfile {
375
+ id: string;
376
+ username: string;
377
+ name: string;
378
+ description?: string;
379
+ followers?: number;
380
+ following?: number;
381
+ verified?: boolean;
382
+ profilePicture?: string;
383
+ location?: string;
384
+ createdAt?: string;
385
+ statusesCount?: number;
386
+ }
387
+
388
+ interface FollowerCheck {
389
+ sourceUsername: string;
390
+ targetUsername: string;
391
+ isFollowing: boolean;
392
+ isFollowedBy: boolean;
393
+ }
394
+
395
+ // ─── User Activity ──────────────────────────────────────
396
+
397
+ interface UserTweetsResponse {
398
+ tweets: Tweet[];
399
+ hasMore: boolean;
400
+ nextCursor?: string;
401
+ }
402
+
403
+ interface UserLikesResponse {
404
+ tweets: Tweet[];
405
+ hasMore: boolean;
406
+ nextCursor?: string;
407
+ }
408
+
409
+ interface UserMediaResponse {
410
+ tweets: Tweet[];
411
+ hasMore: boolean;
412
+ nextCursor?: string;
413
+ }
414
+
415
+ interface TweetFavoritersResponse {
416
+ users: UserProfile[];
417
+ hasMore: boolean;
418
+ nextCursor?: string;
419
+ }
420
+
421
+ interface FollowersYouKnowResponse {
422
+ users: UserProfile[];
423
+ hasMore: boolean;
424
+ nextCursor?: string;
425
+ }
426
+
427
+ // ─── Bookmarks & Timeline ───────────────────────────────
428
+
429
+ interface BookmarksResponse {
430
+ tweets: Tweet[];
431
+ hasMore: boolean;
432
+ nextCursor?: string;
433
+ }
434
+
435
+ interface BookmarkFolder {
436
+ id: string;
437
+ name: string;
438
+ }
439
+
440
+ interface BookmarkFoldersResponse {
441
+ folders: BookmarkFolder[];
442
+ }
443
+
444
+ interface NotificationsResponse {
445
+ notifications: Notification[];
446
+ hasMore: boolean;
447
+ nextCursor?: string;
448
+ }
449
+
450
+ interface TimelineResponse {
451
+ tweets: Tweet[];
452
+ hasMore: boolean;
453
+ nextCursor?: string;
454
+ }
455
+
456
+ interface DmHistoryResponse {
457
+ messages: DmMessage[];
458
+ hasMore: boolean;
459
+ nextCursor?: string;
460
+ }
461
+
462
+ interface DmMessage {
463
+ id: string;
464
+ text: string;
465
+ senderId: string;
466
+ createdAt: string;
467
+ media?: TweetMediaItem[];
468
+ }
469
+
470
+ // ─── X Articles ─────────────────────────────────────────
471
+
472
+ interface Article {
473
+ title: string;
474
+ coverImage?: string;
475
+ bodyHtml: string;
476
+ likeCount: number;
477
+ retweetCount: number;
478
+ replyCount: number;
479
+ viewCount: number;
480
+ bookmarkCount: number;
481
+ author: {
482
+ id: string;
483
+ username: string;
484
+ name: string;
485
+ };
486
+ }
487
+
488
+ // ─── Radar ───────────────────────────────────────────────
489
+
490
+ type RadarSource =
491
+ | "github"
492
+ | "google_trends"
493
+ | "hacker_news"
494
+ | "polymarket"
495
+ | "reddit"
496
+ | "trustmrr"
497
+ | "wikipedia";
498
+
499
+ type RadarCategory =
500
+ | "general"
501
+ | "tech"
502
+ | "dev"
503
+ | "science"
504
+ | "culture"
505
+ | "politics"
506
+ | "business"
507
+ | "entertainment";
508
+
509
+ interface RadarItem {
510
+ id: string;
511
+ title: string;
512
+ description?: string;
513
+ url?: string;
514
+ imageUrl?: string;
515
+ source: RadarSource;
516
+ sourceId: string;
517
+ category: RadarCategory;
518
+ region: string;
519
+ language: string;
520
+ score: number;
521
+ metadata: Record<string, unknown>;
522
+ publishedAt: string;
523
+ createdAt: string;
524
+ }
525
+
526
+ // ─── Download Media ─────────────────────────────────────
527
+
528
+ interface DownloadMediaRequest {
529
+ tweetInput?: string; // Tweet URL or numeric tweet ID (single mode)
530
+ tweetIds?: string[]; // Array of tweet URLs or IDs (bulk mode, max 50). Exactly 1 of tweetInput or tweetIds required.
531
+ }
532
+
533
+ interface DownloadMediaSingleResponse {
534
+ tweetId: string; // Resolved tweet ID
535
+ galleryUrl: string; // Shareable gallery page URL
536
+ cacheHit: boolean; // true if served from cache (no usage consumed)
537
+ }
538
+
539
+ interface DownloadMediaBulkResponse {
540
+ galleryUrl: string; // Combined gallery page URL
541
+ totalTweets: number; // Number of tweets processed
542
+ totalMedia: number; // Total media items downloaded
543
+ }
544
+
545
+ // ─── Trends ──────────────────────────────────────────────
546
+
547
+ interface Trend {
548
+ name: string;
549
+ description?: string;
550
+ rank?: number;
551
+ query?: string;
552
+ }
553
+
554
+ interface TrendList {
555
+ trends: Trend[];
556
+ total: number;
557
+ woeid: number;
558
+ }
559
+
560
+ // ─── Automations ────────────────────────────────────────
561
+
562
+ type TriggerType = "monitor_event" | "schedule" | "search" | "webhook_inbound";
563
+
564
+ type StepType = "action" | "condition" | "extraction";
565
+
566
+ type ActionType =
567
+ | "create_tweet"
568
+ | "follow"
569
+ | "like"
570
+ | "reply_tweet"
571
+ | "retweet"
572
+ | "send_dm"
573
+ | "send_email"
574
+ | "send_telegram"
575
+ | "unfollow";
576
+
577
+ interface AutomationFlow {
578
+ id: string;
579
+ name: string;
580
+ slug: string;
581
+ triggerType: TriggerType;
582
+ triggerConfig: Record<string, unknown>;
583
+ isActive: boolean;
584
+ runCount: string;
585
+ lastRunAt: string | null;
586
+ minIntervalSeconds: number;
587
+ pausedReason: string | null;
588
+ templateSlug: string | null;
589
+ xAccountId: string | null;
590
+ createdAt: string;
591
+ updatedAt: string;
592
+ }
593
+
594
+ interface AutomationStep {
595
+ id: string;
596
+ flowId: string;
597
+ stepType: StepType;
598
+ actionType: ActionType | null;
599
+ extractionType: string | null;
600
+ branch: "main" | "if_true" | "if_false";
601
+ config: Record<string, unknown>;
602
+ position: number;
603
+ positionX: number | null;
604
+ positionY: number | null;
605
+ parentStepId: string | null;
606
+ outputName: string | null;
607
+ createdAt: string;
608
+ }
609
+
610
+ interface AutomationRun {
611
+ id: string;
612
+ status: string;
613
+ startedAt: string;
614
+ completedAt: string | null;
615
+ errorMessage: string | null;
616
+ triggeredBy: string;
617
+ }
618
+
619
+ interface AutomationDetail extends AutomationFlow {
620
+ steps: AutomationStep[];
621
+ recentRuns: AutomationRun[];
622
+ }
623
+
624
+ interface CreateAutomationRequest {
625
+ name: string;
626
+ triggerType: TriggerType;
627
+ triggerConfig: Record<string, unknown>;
628
+ templateSlug?: string;
629
+ }
630
+
631
+ interface UpdateAutomationRequest {
632
+ expectedUpdatedAt: string;
633
+ name?: string;
634
+ triggerType?: TriggerType;
635
+ triggerConfig?: Record<string, unknown>;
636
+ isActive?: boolean;
637
+ triggerPositionX?: number | null;
638
+ triggerPositionY?: number | null;
639
+ }
640
+
641
+ interface AddStepRequest {
642
+ stepType: StepType;
643
+ branch: "main" | "if_true" | "if_false";
644
+ config: Record<string, unknown>;
645
+ position?: number;
646
+ parentStepId?: string;
647
+ actionType?: ActionType;
648
+ extractionType?: string;
649
+ outputName?: string;
650
+ }
651
+
652
+ // ─── Support ────────────────────────────────────────────
653
+
654
+ interface SupportTicket {
655
+ id: string;
656
+ subject: string;
657
+ status: string;
658
+ createdAt: string;
659
+ updatedAt: string;
660
+ }
661
+
662
+ interface SupportMessage {
663
+ id: string;
664
+ body: string;
665
+ sender: string;
666
+ createdAt: string;
667
+ }
668
+
669
+ interface CreateTicketRequest {
670
+ subject: string;
671
+ body: string;
672
+ }
673
+
674
+ // ─── Error ───────────────────────────────────────────────
675
+
676
+ interface ApiError {
677
+ error: string;
678
+ limit?: number;
679
+ }
680
+
681
+ // ─── Request Bodies ──────────────────────────────────────
682
+
683
+ interface CreateMonitorRequest {
684
+ username: string;
685
+ eventTypes: EventType[];
686
+ }
687
+
688
+ interface UpdateMonitorRequest {
689
+ eventTypes?: EventType[];
690
+ isActive?: boolean;
691
+ }
692
+
693
+ interface CreateWebhookRequest {
694
+ url: string;
695
+ eventTypes: EventType[];
696
+ }
697
+
698
+ interface UpdateWebhookRequest {
699
+ url?: string;
700
+ eventTypes?: EventType[];
701
+ isActive?: boolean;
702
+ }
703
+
704
+ interface CreateApiKeyRequest {
705
+ name?: string;
706
+ }
707
+
708
+ // --- Tweet Style Cache ---
709
+
710
+ interface TweetStyleCache {
711
+ xUsername: string;
712
+ tweetCount: number;
713
+ isOwnAccount: boolean;
714
+ fetchedAt: string; // ISO 8601
715
+ tweets: CachedTweet[];
716
+ }
717
+
718
+ interface CachedTweet {
719
+ id: string;
720
+ text: string;
721
+ authorUsername: string;
722
+ createdAt: string; // ISO 8601
723
+ media?: TweetMediaItem[];
724
+ }
725
+
726
+ interface TweetStyleSummary {
727
+ xUsername: string;
728
+ tweetCount: number;
729
+ isOwnAccount: boolean;
730
+ fetchedAt: string;
731
+ }
732
+
733
+ interface StyleComparison {
734
+ style1: TweetStyleCache;
735
+ style2: TweetStyleCache;
736
+ }
737
+
738
+ interface StylePerformance {
739
+ xUsername: string;
740
+ tweetCount: number;
741
+ tweets: PerformanceTweet[];
742
+ }
743
+
744
+ interface PerformanceTweet {
745
+ id: string;
746
+ text: string;
747
+ likeCount: number;
748
+ retweetCount: number;
749
+ replyCount: number;
750
+ quoteCount: number;
751
+ viewCount: number;
752
+ bookmarkCount: number;
753
+ }
754
+
755
+ // --- Tweet Drafts ---
756
+
757
+ interface TweetDraft {
758
+ id: string;
759
+ text: string;
760
+ topic?: string;
761
+ goal?: "engagement" | "followers" | "authority" | "conversation";
762
+ createdAt: string; // ISO 8601
763
+ updatedAt: string; // ISO 8601
764
+ }
765
+
766
+ interface TweetDraftList {
767
+ drafts: TweetDraft[];
768
+ afterCursor: string | null;
769
+ hasMore: boolean;
770
+ }
771
+
772
+ // --- Account Identity ---
773
+
774
+ interface XIdentityResponse {
775
+ success: boolean;
776
+ xUsername: string;
777
+ }
778
+ ```
779
+
780
+ ## REST API vs MCP Field Naming
781
+
782
+ The REST API and MCP server use different field names for the same data. Map these when switching between interfaces:
783
+
784
+ | Type | REST API Field | MCP Field |
785
+ |------|---------------|-----------|
786
+ | **Monitor** | `username` | `xUsername` |
787
+ | **Event** | `type` | `eventType` |
788
+ | **Event** | `data` | `eventData` |
789
+ | **Event** | `monitorId` | `monitoredAccountId` |
790
+ | **UserProfile** | `followers` | `followersCount` |
791
+ | **UserProfile** | `following` | `followingCount` |
792
+ | **FollowerCheck** | `isFollowing` / `isFollowedBy` | `following` / `followedBy` |
793
+
794
+ **MCP `get-user-info` returns a subset** of the full `UserProfile` type. Fields not returned by MCP: `verified`, `location`, `createdAt`, `statusesCount`. Use the REST API `GET /x/users/{username}` for the complete profile.
795
+
796
+ ## MCP Output Schemas
797
+
798
+ MCP tools return structured data with these shapes. Field names differ from the REST API (see mapping table above).
799
+
800
+ ```typescript
801
+ // ─── MCP: get-user-info ─────────────────────────────────
802
+
803
+ interface McpUserInfo {
804
+ username: string; // X username (without @)
805
+ name: string; // Display name
806
+ description: string; // User bio text
807
+ followersCount: number; // Number of followers
808
+ followingCount: number; // Number of accounts followed
809
+ profilePicture: string; // Profile picture URL
810
+ // Not returned: verified, location, createdAt, statusesCount
811
+ // Use REST GET /x/users/{username} for the full profile
812
+ }
813
+
814
+ // ─── MCP: search-tweets ─────────────────────────────────
815
+
816
+ interface McpSearchResult {
817
+ tweets: {
818
+ id: string; // Tweet ID (use with lookup-tweet for full metrics)
819
+ text: string; // Full tweet text
820
+ authorUsername: string; // X username of the tweet author
821
+ authorName: string; // Display name of the tweet author
822
+ createdAt: string; // ISO 8601 timestamp when tweet was posted
823
+ media?: { mediaUrl: string; type: string; url: string }[]; // Attached photos/videos
824
+ // No engagement metrics. Use lookup-tweet for those
825
+ }[];
826
+ }
827
+
828
+ // ─── MCP: lookup-tweet ──────────────────────────────────
829
+
830
+ interface McpTweetLookup {
831
+ tweet: {
832
+ id: string; // Tweet ID
833
+ text: string; // Tweet text
834
+ likeCount: number; // Number of likes
835
+ retweetCount: number; // Number of retweets
836
+ replyCount: number; // Number of replies
837
+ quoteCount: number; // Number of quote tweets
838
+ viewCount: number; // Number of views
839
+ bookmarkCount: number; // Number of bookmarks
840
+ media?: { mediaUrl: string; type: string; url: string }[]; // Attached photos/videos
841
+ };
842
+ author?: { // Tweet author details
843
+ id: string; // Author user ID
844
+ username: string; // Author X username
845
+ followers: number; // Author follower count
846
+ verified: boolean; // Whether the author is verified
847
+ };
848
+ }
849
+
850
+ // ─── MCP: check-follow ─────────────────────────────────
851
+
852
+ interface McpFollowCheck {
853
+ following: boolean; // Whether the source follows the target
854
+ followedBy: boolean; // Whether the target follows the source
855
+ }
856
+
857
+ // ─── MCP: get-events ────────────────────────────────────
858
+
859
+ interface McpEventList {
860
+ events: {
861
+ id: string; // Event ID (use with get-event for full details)
862
+ xUsername: string; // Username of the monitored account
863
+ eventType: string; // Event type (tweet.new, tweet.reply, etc.)
864
+ eventData: unknown; // Full event payload (tweet text, author, metrics)
865
+ monitoredAccountId: string; // ID of the monitored account
866
+ createdAt: string; // ISO 8601 when event was recorded
867
+ occurredAt: string; // ISO 8601 when event occurred on X
868
+ }[];
869
+ hasMore: boolean; // Whether more results are available
870
+ nextCursor?: string; // Pass as afterCursor to fetch the next page
871
+ }
872
+
873
+ // ─── MCP: list-monitors ─────────────────────────────────
874
+
875
+ interface McpMonitorList {
876
+ monitors: {
877
+ id: string; // Monitor ID (use with remove-monitor, get-events monitorId filter)
878
+ xUsername: string; // Monitored X username
879
+ eventTypes: string[]; // Subscribed event types
880
+ isActive: boolean; // Whether the monitor is currently active
881
+ createdAt: string; // ISO 8601 timestamp
882
+ }[];
883
+ }
884
+
885
+ // ─── MCP: add-webhook ───────────────────────────────────
886
+
887
+ interface McpWebhookCreated {
888
+ id: string; // Webhook ID
889
+ url: string; // HTTPS endpoint URL
890
+ eventTypes: string[]; // Event types delivered to this webhook
891
+ isActive: boolean; // Whether the webhook is active
892
+ createdAt: string; // ISO 8601 timestamp
893
+ secret: string; // HMAC signing secret for verifying webhook payloads. Store securely.
894
+ }
895
+
896
+ // ─── MCP: test-webhook ──────────────────────────────────
897
+
898
+ interface McpWebhookTest {
899
+ success: boolean;
900
+ statusCode: number;
901
+ error?: string;
902
+ }
903
+
904
+ // ─── MCP: run-extraction ────────────────────────────────
905
+
906
+ interface McpExtractionJob {
907
+ id: string; // Extraction job ID (use with get-extraction for results)
908
+ toolType: string; // Extraction tool type used
909
+ status: string; // Job status
910
+ totalResults: number; // Number of results extracted
911
+ }
912
+
913
+ // ─── MCP: estimate-extraction ───────────────────────────
914
+
915
+ interface McpExtractionEstimate {
916
+ allowed?: boolean; // Whether the extraction is allowed within budget
917
+ estimatedResults?: number; // Estimated number of results
918
+ projectedPercent?: number; // Projected usage percent after extraction
919
+ usagePercent?: number; // Current usage percent of monthly quota
920
+ source?: string; // Data source used for estimation
921
+ error?: string; // Error message if estimation failed
922
+ }
923
+
924
+ // ─── MCP: run-draw ──────────────────────────────────────
925
+
926
+ interface McpDrawResult {
927
+ id: string; // Draw ID (use with get-draw for full details)
928
+ tweetId: string; // Giveaway tweet ID
929
+ totalEntries: number; // Total reply count before filtering
930
+ validEntries: number; // Valid entries after filtering
931
+ winners: {
932
+ position: number; // Winner position (1-based)
933
+ authorUsername: string; // X username of the winner
934
+ tweetId: string; // Tweet ID of the winning reply
935
+ isBackup: boolean; // Whether this is a backup winner
936
+ }[];
937
+ }
938
+
939
+ // ─── MCP: get-draw ──────────────────────────────────────
940
+
941
+ interface McpDrawDetails {
942
+ draw: {
943
+ id: string; // Draw ID
944
+ status: string; // Draw status (completed, failed)
945
+ createdAt: string; // ISO 8601 timestamp
946
+ drawnAt?: string; // ISO 8601 timestamp when winners were drawn
947
+ totalEntries: number; // Total reply count before filtering
948
+ validEntries: number; // Entries remaining after filters applied
949
+ tweetId: string; // Giveaway tweet ID
950
+ tweetUrl: string; // Full URL of the giveaway tweet
951
+ tweetText: string; // Giveaway tweet text
952
+ tweetAuthorUsername: string; // Username of the giveaway tweet author
953
+ tweetLikeCount: number; // Tweet like count at draw time
954
+ tweetRetweetCount: number; // Tweet retweet count at draw time
955
+ tweetReplyCount: number; // Tweet reply count at draw time
956
+ tweetQuoteCount: number; // Tweet quote count at draw time
957
+ };
958
+ winners: {
959
+ position: number; // Winner position (1-based)
960
+ authorUsername: string; // X username of the winner
961
+ tweetId: string; // Tweet ID of the winning reply
962
+ isBackup: boolean; // Whether this is a backup winner
963
+ }[];
964
+ }
965
+
966
+ // ─── MCP: get-account ───────────────────────────────────
967
+
968
+ interface McpAccount {
969
+ plan: string; // Current plan name (free or subscriber)
970
+ monitorsAllowed: number; // Maximum monitors allowed on current plan
971
+ monitorsUsed: number; // Number of active monitors
972
+ currentPeriod?: { // Current billing period (present only with active subscription)
973
+ start: string; // ISO 8601 period start date
974
+ end: string; // ISO 8601 period end date
975
+ usagePercent: number; // Percent of monthly quota consumed
976
+ };
977
+ }
978
+
979
+ // ─── MCP: get-trends ────────────────────────────────────
980
+
981
+ interface McpTrends {
982
+ woeid: number;
983
+ total: number;
984
+ trends: {
985
+ name: string; // Trend name or hashtag
986
+ rank?: number; // Trend rank position
987
+ description?: string; // Trend description or context
988
+ query?: string; // Search query to find tweets for this trend
989
+ }[];
990
+ }
991
+
992
+ // ─── MCP: subscribe ────────────────────────────────────
993
+
994
+ interface McpSubscribe {
995
+ status: "already_subscribed" | "checkout_created" | "payment_issue";
996
+ url: string; // Checkout or Customer Portal URL. Open in browser.
997
+ message: string; // Human-readable status message
998
+ }
999
+
1000
+ // ─── MCP: compose-tweet ────────────────────────────────
1001
+
1002
+ interface McpComposeTweet {
1003
+ algorithmInsights: {
1004
+ name: string; // Signal name from PhoenixScores
1005
+ polarity: "positive" | "negative"; // Whether this signal helps or hurts ranking
1006
+ description: string; // What this signal measures
1007
+ }[];
1008
+ contentRules: {
1009
+ rule: string; // Actionable content rule
1010
+ description: string; // Why this rule matters based on algorithm architecture
1011
+ }[];
1012
+ engagementMultipliers: {
1013
+ action: string; // Engagement action (e.g. reply chain, quote tweet)
1014
+ multiplier: string; // Relative value compared to a like (e.g. "27x a like")
1015
+ source: string; // Data source for this multiplier
1016
+ }[];
1017
+ engagementVelocity: string; // How early engagement velocity affects distribution
1018
+ followUpQuestions: string[]; // Questions for the AI to ask the user before composing
1019
+ scorerWeights: {
1020
+ signal: string; // Signal name in the scoring model
1021
+ weight: number; // Weight applied to predicted probability
1022
+ context: string; // Practical meaning of this weight
1023
+ }[];
1024
+ topPenalties: string[]; // Most severe negative signals to avoid
1025
+ source: string; // Attribution to algorithm source code
1026
+ }
1027
+
1028
+ // ─── MCP: refine-tweet ─────────────────────────────────
1029
+
1030
+ interface McpRefineTweet {
1031
+ compositionGuidance: string[]; // Targeted guidance based on user preferences
1032
+ examplePatterns: {
1033
+ pattern: string; // Tweet structure template
1034
+ description: string; // What this pattern achieves
1035
+ }[];
1036
+ }
1037
+
1038
+ // ─── MCP: score-tweet ──────────────────────────────────
1039
+
1040
+ interface McpScoreTweet {
1041
+ totalChecks: number; // Total number of checks performed
1042
+ passedCount: number; // Number of checks that passed
1043
+ topSuggestion: string; // Highest-impact improvement suggestion
1044
+ checklist: {
1045
+ factor: string; // What was checked
1046
+ passed: boolean; // Whether the check passed
1047
+ suggestion?: string; // Improvement suggestion (present only if failed)
1048
+ }[];
1049
+ }
1050
+
1051
+ // ─── X Accounts (Connected) ──────────────────────────
1052
+
1053
+ interface ConnectedXAccount {
1054
+ id: string; // Unique account ID
1055
+ username: string; // X username
1056
+ displayName?: string; // Display name on X
1057
+ isActive: boolean; // Whether the connection is active
1058
+ createdAt: string; // ISO 8601 timestamp
1059
+ }
1060
+
1061
+ interface ConnectXAccountRequest {
1062
+ username: string; // X username (@ auto-stripped)
1063
+ email: string; // Email associated with X account
1064
+ password: string; // Password (encrypted at rest)
1065
+ totp_secret?: string; // TOTP base32 secret for 2FA accounts
1066
+ proxy_country?: string; // Preferred proxy region (e.g. "US")
1067
+ }
1068
+
1069
+ interface ReauthXAccountRequest {
1070
+ password: string; // Current password
1071
+ totp_secret?: string; // TOTP secret if 2FA enabled
1072
+ }
1073
+
1074
+ // ─── X Write ──────────────────────────────────────────
1075
+
1076
+ interface CreateTweetRequest {
1077
+ account: string; // Connected X username or account ID
1078
+ text: string; // Tweet text (280 chars, or 25,000 if is_note_tweet)
1079
+ reply_to_tweet_id?: string; // Tweet ID to reply to
1080
+ attachment_url?: string; // URL to attach as card
1081
+ community_id?: string; // Community ID to post into
1082
+ is_note_tweet?: boolean; // Long-form note tweet (up to 25,000 chars)
1083
+ media_ids?: string[]; // Media IDs from POST /x/media (max 4 images or 1 video)
1084
+ }
1085
+
1086
+ interface CreateTweetResponse {
1087
+ tweetId: string; // ID of the newly created tweet
1088
+ success: boolean; // Always true on success
1089
+ }
1090
+
1091
+ interface WriteActionRequest {
1092
+ account: string; // Connected X username or account ID
1093
+ }
1094
+
1095
+ interface SendDmRequest {
1096
+ account: string; // Connected X username or account ID
1097
+ text: string; // Message text
1098
+ media_ids?: string[]; // Media IDs to attach
1099
+ reply_to_message_id?: string; // Message ID to reply to
1100
+ }
1101
+
1102
+ interface UpdateProfileRequest {
1103
+ account: string; // Connected X username or account ID
1104
+ name?: string; // Display name
1105
+ description?: string; // Bio
1106
+ location?: string; // Location
1107
+ url?: string; // Website URL
1108
+ }
1109
+
1110
+ // ─── Integrations ─────────────────────────────────────
1111
+
1112
+ // Integration event types differ from monitor event types:
1113
+ // includes system events (draw/extraction) but NOT follower events
1114
+ type IntegrationEventType =
1115
+ | "tweet.new"
1116
+ | "tweet.quote"
1117
+ | "tweet.reply"
1118
+ | "tweet.retweet"
1119
+ | "draw.completed"
1120
+ | "extraction.completed"
1121
+ | "extraction.failed";
1122
+
1123
+ interface Integration {
1124
+ id: string; // Unique integration ID
1125
+ type: string; // Integration type ("telegram")
1126
+ name: string; // Human-readable name
1127
+ config: Record<string, unknown>; // Type-specific config (Telegram: { chatId })
1128
+ eventTypes: IntegrationEventType[]; // Subscribed event types
1129
+ isActive: boolean; // Whether the integration is active
1130
+ createdAt: string; // ISO 8601 timestamp
1131
+ updatedAt: string; // ISO 8601 timestamp
1132
+ }
1133
+
1134
+ interface CreateIntegrationRequest {
1135
+ type: string; // "telegram"
1136
+ name: string; // Human-readable name
1137
+ config: { chatId: string }; // Telegram config
1138
+ eventTypes: IntegrationEventType[]; // Event types to subscribe to
1139
+ }
1140
+
1141
+ interface UpdateIntegrationRequest {
1142
+ name?: string; // New name
1143
+ eventTypes?: string[]; // New event types
1144
+ isActive?: boolean; // Activate/deactivate
1145
+ silentPush?: boolean; // Silent notifications
1146
+ scopeAllMonitors?: boolean; // Scope to all monitors
1147
+ filters?: Record<string, unknown>; // Filters
1148
+ messageTemplate?: Record<string, unknown>; // Custom message template
1149
+ }
1150
+
1151
+ interface IntegrationDelivery {
1152
+ id: string; // Delivery ID
1153
+ integrationId: string; // Integration ID
1154
+ sourceType: string; // "monitor_event" | "extraction" | "draw"
1155
+ sourceId: string; // Source record ID
1156
+ eventType: string; // Event type
1157
+ status: string; // "pending" | "delivered" | "failed" | "exhausted"
1158
+ lastError?: string; // Last error message
1159
+ attempts: number; // Delivery attempt count
1160
+ deliveredAt?: string; // ISO 8601 timestamp
1161
+ createdAt: string; // ISO 8601 timestamp
1162
+ }
1163
+ ```