From a5124a2a71cc805ec312e5f5b579886017b60c3b Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:33:18 -0600 Subject: [PATCH 01/32] Simplify README introduction Removed redundant text from the introduction section. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index af503e4..57e2451 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # MyXstack -This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that detects mentions, pulls thread context, and routes reasoning through Grok via the xMCP server. Follow the phases below to get from zero to a working "tag and watch" prototype. - +This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that detects mentions, pulls thread context, and routes reasoning through Grok via the xMCP server. Follow ## Phase 1: Gather prerequisites & accounts (1–2 hours) ### X developer account & app From 27f60fd870a97c11a9d12ead94affd7fe4858071 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:37:27 -0600 Subject: [PATCH 02/32] Update README for clarity on agent functionality --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 57e2451..3d49d7e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # MyXstack -This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that detects mentions, pulls thread context, and routes reasoning through Grok via the xMCP server. Follow +This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server. + ## Phase 1: Gather prerequisites & accounts (1–2 hours) ### X developer account & app From e2e0bec1eb6388bb5ba81edb03514216cef73de6 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:50:40 -0600 Subject: [PATCH 03/32] Fix duplicate instructions in README Removed duplicate steps for creating and storing the xAI / Grok API key. --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3d49d7e..23ca054 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,8 @@ This repository hosts a lightweight, step-by-step guide for setting up an autono 3. Note the bot user ID (you can fetch this via the API later). ### xAI / Grok API key -1. Ensure you have an X Premium+ subscription for API access. -2. Visit , open the API keys section, and create a key that starts with `xai-`. -3. Store the key securely. +. Visit , open the API keys section, and create a key that starts with `xai-`. +. Store the key securely. ### Local tooling - Install Python 3.9+ (3.10–3.13 recommended). From f7e781fc8c561202c718c81aa19ca38dd73a9c10 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:03:03 +0000 Subject: [PATCH 04/32] Initial plan From 6e1a607df06a3536f27664fb830cc8a7c0532896 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:05:50 +0000 Subject: [PATCH 05/32] Fix: reply to mention post instead of thread root Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> --- src/examples.ts | 4 ++-- src/services/agent.ts | 3 ++- src/services/grok.ts | 17 +++++++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/examples.ts b/src/examples.ts index aaf1598..3da6efe 100644 --- a/src/examples.ts +++ b/src/examples.ts @@ -33,7 +33,7 @@ async function example1_fetchAndAnalyzeMention() { console.log(`\nThread has ${thread.replies.length + 1} posts`); // Analyze with Grok - const analysis = await grok.analyzeAndDecide(mention.post.text, thread); + const analysis = await grok.analyzeAndDecide(mention.post.text, thread, mention.post.id); console.log(`\nGrok's Decision:`); console.log(` Action: ${analysis.action.type}`); @@ -139,7 +139,7 @@ async function example5_batchProcessMentions() { const thread = await xClient.fetchThread(conversationId); if (thread) { - const analysis = await grok.analyzeAndDecide(mention.post.text, thread); + const analysis = await grok.analyzeAndDecide(mention.post.text, thread, mention.post.id); console.log(` → Action: ${analysis.action.type} (${(analysis.confidence * 100).toFixed(0)}% confidence)`); // In a real scenario, you might execute the action here diff --git a/src/services/agent.ts b/src/services/agent.ts index ab40033..326fb38 100644 --- a/src/services/agent.ts +++ b/src/services/agent.ts @@ -129,7 +129,8 @@ export class AutonomousAgent { console.log('\nšŸ¤– Analyzing with Grok AI...'); const analysis = await this.grokService.analyzeAndDecide( mention.post.text, - thread + thread, + mention.post.id ); console.log(` Action: ${analysis.action.type.toUpperCase()}`); diff --git a/src/services/grok.ts b/src/services/grok.ts index 0fd6b2c..d71ffdc 100644 --- a/src/services/grok.ts +++ b/src/services/grok.ts @@ -21,11 +21,12 @@ export class GrokService { * Analyze a mention and thread context to determine appropriate action * @param mention - The text content of the mention to analyze * @param thread - The thread context including root post and replies + * @param mentionPostId - The ID of the post where the agent was mentioned * @returns Analysis with recommended action */ - async analyzeAndDecide(mention: string, thread: XThread): Promise { + async analyzeAndDecide(mention: string, thread: XThread, mentionPostId: string): Promise { if (this.simulationMode) { - return this.simulateAnalysis(mention, thread); + return this.simulateAnalysis(mention, thread, mentionPostId); } try { @@ -61,12 +62,12 @@ export class GrokService { const data: any = await response.json(); const analysisText = data.choices[0]?.message?.content || ''; - // Use the root post ID from the thread, not the mention text - return this.parseGrokResponse(analysisText, thread.root_post.id); + // Use the mention post ID so replies target the specific post where the agent was mentioned + return this.parseGrokResponse(analysisText, mentionPostId); } catch (error) { console.error('Error calling Grok API:', error); // Fallback to simulation - return this.simulateAnalysis(mention, thread); + return this.simulateAnalysis(mention, thread, mentionPostId); } } @@ -145,7 +146,7 @@ export class GrokService { /** * Simulate Grok analysis for testing */ - private simulateAnalysis(mention: string, thread: XThread): GrokAnalysis { + private simulateAnalysis(mention: string, thread: XThread, mentionPostId: string): GrokAnalysis { console.log('šŸ¤– Simulated Grok Analysis:'); console.log(` Analyzing: "${mention}"`); @@ -159,7 +160,7 @@ export class GrokService { const analysis: GrokAnalysis = { action: { type: 'reply', - target_post_id: thread.root_post.id, + target_post_id: mentionPostId, content: 'Thanks for reaching out! I\'ve analyzed your question and here\'s my insight: Based on the context, I\'d recommend exploring this topic further. Let me know if you need more specific information!', reasoning: 'Detected a question, providing helpful response', }, @@ -174,7 +175,7 @@ export class GrokService { const analysis: GrokAnalysis = { action: { type: 'analyze', - target_post_id: thread.root_post.id, + target_post_id: mentionPostId, reasoning: 'No clear action needed, just acknowledgment', }, confidence: 0.7, From cd97de40fc6e77c34587064ecd5e77082b495180 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:12:51 +0000 Subject: [PATCH 06/32] Initial plan From 54cebedb5eee00282180e0dc39ebe05d628b09e3 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:14:55 -0600 Subject: [PATCH 07/32] Update README.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23ca054..fb39de2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MyXstack -This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server. +This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server. ## Phase 1: Gather prerequisites & accounts (1–2 hours) From 4f7d6c8b16b002dd53c7df83e472d22b905326f4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:18:39 +0000 Subject: [PATCH 08/32] Start xMCP server on startup Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> --- README.md | 2 +- src/index.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 23ca054..fb39de2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MyXstack -This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server. +This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server. ## Phase 1: Gather prerequisites & accounts (1–2 hours) diff --git a/src/index.ts b/src/index.ts index 6dd2dfe..c29abb7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,7 @@ async function main() { // Initialize MCP server (runs in background) console.log('🌐 Initializing xMCP server...'); const mcpServer = new XMCPServer(config.xApiConfig); + await mcpServer.start(); console.log('āœ… xMCP server ready\n'); // Initialize and start autonomous agent From ab4be0c0f47c916a33fd596585560fc1d982a3ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:05:52 +0000 Subject: [PATCH 09/32] Initial plan From a61e1befcccde696f654e776a885ae3fdbeae20e Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:28:28 -0600 Subject: [PATCH 10/32] Modify agent name and description Updated agent name and description with a link. --- .github/agents/my-agent.agent.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/agents/my-agent.agent.md diff --git a/.github/agents/my-agent.agent.md b/.github/agents/my-agent.agent.md new file mode 100644 index 0000000..319cf89 --- /dev/null +++ b/.github/agents/my-agent.agent.md @@ -0,0 +1,14 @@ +--- +# Fill in the fields below to create a basic custom agent for your repository. +# The Copilot CLI can be used for local testing: https://gh.io/customagents/cli +# To make this agent available, merge this file into the default repository branch. +# For format details, see: https://gh.io/customagents/config + +name:molt +description: https://www.molt.bot/ +--- + +# My Agent + +[Describe what your agent does here...](https://www.molt.bot/ +---) From bd98ce753d2afc024c5a42c5efcef4440dbb5de0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:35:19 +0000 Subject: [PATCH 11/32] Initial plan From d2d8d3425a4cfdebf3a4bd9a3f29ab41dd0c57a5 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:37:01 -0600 Subject: [PATCH 12/32] =?UTF-8?q?=F0=9F=A4=96=20Deploy=20auto-label.yml=20?= =?UTF-8?q?workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/auto-label.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/auto-label.yml diff --git a/.github/workflows/auto-label.yml b/.github/workflows/auto-label.yml new file mode 100644 index 0000000..cab0666 --- /dev/null +++ b/.github/workflows/auto-label.yml @@ -0,0 +1,30 @@ +name: Auto Label +on: + pull_request: + types: [opened, reopened, synchronized] +jobs: + label: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + script: | + const { data: files } = await github.rest.pulls.listFiles({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + }); + const labels = new Set(); + for (const file of files) { + if (file.filename.endsWith('.js') || file.filename.endsWith('.ts')) labels.add('logic'); + if (file.filename.includes('test')) labels.add('testing'); + if (file.filename.includes('.github/workflows')) labels.add('ci-cd'); + } + if (labels.size > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: Array.from(labels), + }); + } From 81c8e8d81634461542959c7e8cd40d6be8c36924 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:37:02 -0600 Subject: [PATCH 13/32] =?UTF-8?q?=F0=9F=A4=96=20Deploy=20pr-checks.yml=20w?= =?UTF-8?q?orkflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pr-checks.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/pr-checks.yml diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 0000000..2464d70 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,13 @@ +name: PR Checks +on: + pull_request: + branches: [main, master] +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Basic Syntax Check + run: | + echo "Running syntax validation..." + find . -name "*.js" -o -name "*.py" -o -name "*.ts" | xargs -I {} node -c {} || true From 8a67c3c99fce31b3c324d56250498e3780087f07 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:37:03 -0600 Subject: [PATCH 14/32] =?UTF-8?q?=F0=9F=A4=96=20Deploy=20issue-triage.yml?= =?UTF-8?q?=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-triage.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/issue-triage.yml diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml new file mode 100644 index 0000000..9379a8d --- /dev/null +++ b/.github/workflows/issue-triage.yml @@ -0,0 +1,23 @@ +name: Issue Triage +on: + issues: + types: [opened] +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: ['triage-needed'] + }); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + body: "Thanks for opening this issue! A maintainer will look at it shortly." + }); From 875d1c981be5271631c011ada2fe20b97b83be1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:41:09 +0000 Subject: [PATCH 15/32] Add comprehensive strategic analysis of Molt AI platform Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> --- MOLT_STRATEGIC_ANALYSIS.md | 1075 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1075 insertions(+) create mode 100644 MOLT_STRATEGIC_ANALYSIS.md diff --git a/MOLT_STRATEGIC_ANALYSIS.md b/MOLT_STRATEGIC_ANALYSIS.md new file mode 100644 index 0000000..0899660 --- /dev/null +++ b/MOLT_STRATEGIC_ANALYSIS.md @@ -0,0 +1,1075 @@ +# Strategic Analysis: Molt (Moltbot) AI Agent Platform +## Comprehensive Teardown & Competitive Mapping + +**Analysis Date:** January 29, 2026 +**Platform:** Molt.bot (formerly Clawdbot) +**Official Site:** https://www.molt.bot/ +**GitHub:** https://github.com/moltbot/moltbot + +--- + +## Executive Summary + +Molt (Moltbot) is an open-source, self-hosted AI agent platform that has rapidly emerged as a disruptive force in the personal and enterprise automation space. Rebranded from Clawdbot in early 2026 following a trademark dispute, Molt distinguishes itself through its **privacy-first, local-execution model** and **deep system integration capabilities**. With 60,000-100,000 GitHub stars and an estimated 300,000-400,000 worldwide users, Molt represents a significant market shift toward user-controlled, privacy-preserving AI agents. + +**Key Differentiators:** +- Fully self-hosted with local-first architecture +- Multi-platform messaging integration (13+ platforms) +- Real action execution (shell commands, file operations, browser automation) +- Proactive, autonomous agent behavior +- Open-source with MIT license and active community (130-300+ contributors) +- Model-agnostic architecture supporting multiple LLM providers + +**Market Position:** Molt occupies a unique niche between traditional cloud-based AI assistants (ChatGPT, Claude) and enterprise agent frameworks (LangChain, CrewAI), targeting privacy-conscious power users, developers, and organizations requiring data sovereignty. + +--- + +## 1. Core Features Analysis + +### 1.1 Platform Architecture + +Molt employs a sophisticated gateway-based architecture built entirely in TypeScript/Node.js: + +**Gateway Control Plane:** +- Single supervised daemon (systemd/launchd) orchestrating all operations +- Default port: 18789 (WebSocket/HTTP) +- Centralized routing for all messaging channels +- Unified session and state management + +**Source:** [DeepWiki - Moltbot Architecture](https://deepwiki.com/moltbot/moltbot) + +**Agent Runtime Engine:** +- Sandboxed agent execution with isolated workspaces +- Per-agent configuration for models, skills, and permissions +- Multi-agent orchestration with parallel operation support +- Persistent cross-session memory + +**Source:** [Molt.bot Documentation - Multi-Agent Routing](https://docs.molt.bot/concepts/multi-agent) + +**Messaging Integration Layer:** +- 13+ platform plugins: WhatsApp (Baileys), Telegram (grammY), Discord (discord.js), Slack (Bolt SDK), iMessage, Signal, Matrix, WebChat, CLI +- Modular plugin architecture (`src/plugins/`) +- User/channel-based routing for multi-tenant scenarios + +**Source:** [Moltbot GitHub Repository](https://github.com/moltbot/moltbot) + +### 1.2 Feature Set + +| Feature Category | Capabilities | Implementation | +|-----------------|--------------|----------------| +| **Multi-Platform Integration** | WhatsApp, Telegram, Discord, Slack, Signal, iMessage, Teams, Matrix, WebChat, CLI | Native adapters with platform-specific SDKs | +| **Action Execution** | Shell commands, file operations, email sending, calendar management, browser automation, form filling | Secure sandbox with permission-based execution | +| **Memory & Context** | Persistent long-term memory, cross-session continuity, preference tracking, relationship mapping | Local storage (~/.moltbot) with searchable history | +| **Proactive Behavior** | Autonomous reminders, scheduled tasks, background automation, initiated conversations | Cron-style scheduling with event triggers | +| **Multi-Agent Support** | Parallel agent operation, persona isolation, role-based routing | Workspace isolation (~/clawd-*) per agent | +| **Model Flexibility** | OpenAI, Anthropic, Google Gemini, Ollama (local), custom LLMs | Pluggable provider architecture | +| **Skills/Plugins** | 565+ community skills via ClawdHub marketplace | JavaScript/TypeScript extensibility | +| **OS Support** | macOS, Linux, Windows (WSL2), Raspberry Pi | Cross-platform Node.js runtime | + +**Sources:** +- [Molt.bot Official Site](https://www.molt.bot/) +- [DEV Community - Moltbot Guide](https://dev.to/czmilo/moltbot-the-ultimate-personal-ai-assistant-guide-for-2026-d4e) +- [Metana - Moltbot Overview](https://metana.io/blog/what-is-moltbot-everything-you-need-to-know-in-2026/) + +### 1.3 Technical Stack + +**Core Technologies:** +- **Language:** TypeScript/Node.js (100%) +- **Messaging Adapters:** + - WhatsApp: Baileys library + - Telegram: grammY framework + - Discord: discord.js + - Slack: Bolt SDK + - iMessage: BlueBubbles (Swift on macOS) +- **Configuration:** JSON5 format (~/.clawdbot/clawdbot.json) +- **Storage:** File-system based, local directory structure +- **Execution:** Native shell integration, sandboxed tool runner +- **Protocol:** WebSocket/HTTP API for agent communication + +**Source:** [Moltbot GitHub - Technical Stack](https://github.com/moltbot/moltbot) + +--- + +## 2. User-Facing Functionality + +### 2.1 Use Cases + +**Personal Productivity:** +- Automated task management and reminders +- Cross-platform message consolidation +- Email and calendar management +- File organization and retrieval +- Research assistance with web browsing + +**Source:** [Hostinger - What is Moltbot](https://www.hostinger.com/tutorials/what-is-moltbot) + +**Developer Workflows:** +- Code review and documentation generation +- Repository management and CI/CD integration +- API testing and monitoring +- Development environment automation +- Log analysis and debugging assistance + +**Source:** [Analytics Vidhya - Clawdbot Guide](https://www.analyticsvidhya.com/blog/2026/01/clawdbot-guide/) + +**Enterprise Applications:** +- Knowledge base management +- Compliance and audit trail generation +- Process automation across departments +- Secure inter-team communication +- Document workflow orchestration + +**Source:** [AI Multiple - Moltbot Use Cases](https://research.aimultiple.com/moltbot/) + +### 2.2 User Experience + +**Setup Complexity:** High - Requires technical knowledge for initial configuration +**Learning Curve:** Medium to steep - Configuration-heavy but well-documented +**Customization:** Extensive - Full access to source code and plugin system +**Maintenance:** User-managed - Self-hosting requires ongoing updates and security management + +**Strengths:** +- Complete control and transparency +- No vendor lock-in +- Unlimited customization potential +- Privacy preservation + +**Weaknesses:** +- Technical expertise required +- Self-managed security burden +- Complex initial setup +- Ongoing maintenance overhead + +**Source:** [CurateClick - Moltbot Complete Guide](https://curateclick.com/blog/2026-moltbot-complete-guide) + +--- + +## 3. Go-To-Market (GTM) Strategy + +### 3.1 Target Audience Analysis + +**Primary Segments:** + +1. **Privacy-Conscious Power Users** (40% of user base) + - Technical literacy: High + - Primary concerns: Data sovereignty, vendor lock-in + - Willingness to self-host: High + - Value proposition: Complete control over data and AI agent + +2. **Developers and Technical Teams** (35% of user base) + - Use case: Development workflow automation + - Integration needs: GitHub, Slack, development tools + - Customization requirements: High + - Value proposition: Extensible, programmable assistant + +3. **Small to Medium Enterprises** (20% of user base) + - Privacy requirements: Regulatory compliance (GDPR, HIPAA) + - Budget constraints: Cost-conscious + - IT capability: In-house technical teams + - Value proposition: Self-hosted alternative to cloud services + +4. **Early Adopters and Enthusiasts** (5% of user base) + - Motivation: Cutting-edge technology experimentation + - Community participation: High + - Contribution potential: Plugin development, bug reports + - Value proposition: Participation in open-source innovation + +**Source:** [Macaron - Is Moltbot Free](https://macaron.im/blog/is-moltbot-free-cost) + +### 3.2 GTM Approach + +**Current Strategy: Community-Led, Bottom-Up Growth** + +**Distribution Channels:** +1. **GitHub Repository** - Primary distribution (60,000-100,000 stars) +2. **Developer Communities** - DEV.to, Reddit, Hacker News +3. **Discord Server** - 8,900+ active members +4. **ClawdHub Marketplace** - 565+ community plugins +5. **Technical Documentation** - Comprehensive setup guides + +**Growth Tactics:** +- Open-source collaboration and contribution +- Community-driven feature development +- Viral social media presence (X/Twitter, Reddit) +- Technical content marketing (blog posts, tutorials) +- Developer advocacy and education + +**Source:** [Moltbot Official Documentation](https://docs.molt.bot/) + +### 3.3 Marketing Positioning + +**Value Propositions:** + +| Segment | Primary Message | Secondary Benefits | +|---------|----------------|-------------------| +| Privacy Users | "Your data, your control, your AI" | No cloud dependencies, full transparency | +| Developers | "Build your perfect AI assistant" | Extensible, programmable, open-source | +| Enterprises | "Enterprise AI without the cloud" | Compliance-friendly, cost-effective, secure | +| Enthusiasts | "Join the AI agent revolution" | Community-driven, cutting-edge technology | + +**Competitive Positioning:** +- **vs. ChatGPT/Claude:** Privacy-first, self-hosted alternative +- **vs. LangChain/CrewAI:** End-user focused with multi-platform integration +- **vs. Commercial Assistants:** Open-source, no subscription fees, unlimited customization + +**Sources:** +- [FelloAI - Moltbot Overview](https://felloai.com/moltbot-complete-overview/) +- [Growth Jockey - Moltbot Guide](https://www.growthjockey.com/blogs/clawdbot-moltbot) + +--- + +## 4. Investment & Monetization Model + +### 4.1 Current Business Model + +**Open-Source Foundation:** +- MIT License - Completely free to use, modify, and distribute +- No direct revenue from core software +- Community-driven development + +**True Cost Structure:** + +| Cost Component | Monthly Estimate | Notes | +|----------------|-----------------|-------| +| LLM API Costs | $15-40 | Claude/GPT-4 usage-based | +| Hosting | $5-10 | Local hardware or VPS | +| Setup Time | ~8-12 hours | One-time investment | +| Maintenance | ~2-4 hours/month | Updates, troubleshooting | + +**Total Monthly Cost:** $20-50 + time investment + +**Source:** [Macaron - Moltbot True Cost Breakdown](https://macaron.im/blog/is-moltbot-free-cost) + +### 4.2 Potential Monetization Strategies + +Based on industry analysis of similar open-source AI platforms: + +**1. Freemium Model with Premium Features** +- Free: Core self-hosted version +- Premium: Enhanced skills, priority support, managed updates +- Pricing: $10-30/user/month + +**2. Managed Hosting Service** +- Fully managed Molt instances +- Enterprise-grade security and compliance +- SLA-backed uptime guarantees +- Pricing: $50-200/agent/month + +**3. Enterprise Licensing** +- Advanced security features +- Dedicated support channels +- Custom integration development +- Training and onboarding services +- Pricing: $10,000-50,000 annual contracts + +**4. Marketplace Revenue Share** +- ClawdHub plugin marketplace +- 20-30% commission on paid plugins +- Certified partner program + +**5. Professional Services** +- Custom integration development +- Security auditing and hardening +- Training and workshops +- Consulting for enterprise deployments + +**Sources:** +- [Orb - AI Monetization Strategies](https://www.withorb.com/blog/ai-monetization) +- [UserPilot - AI SaaS Monetization](https://userpilot.com/blog/ai-saas-monetization/) +- [Alguna - AI Monetization Platforms](https://blog.alguna.com/ai-monetization-platform/) + +### 4.3 Investment Landscape + +**Funding Status:** No public information on venture funding (as of January 2026) + +**Likely Funding Strategy:** +- Bootstrap phase via community contributions +- Potential future VC interest given rapid growth metrics: + - 60,000-100,000 GitHub stars (top 0.1% of projects) + - 300,000-400,000 estimated users + - High engagement (8,900+ Discord members) + - Strong developer advocacy + +**VC Appeal Factors:** +- Large addressable market (privacy-conscious enterprise segment) +- Strong technical moat (comprehensive platform) +- Network effects (plugin marketplace, community) +- Clear enterprise upsell path +- Defensible positioning (local-first architecture) + +**Sources:** +- [Morgan Stanley - AI Monetization Race to ROI](https://www.morganstanley.com/insights/articles/ai-monetization-race-to-roi-tmt) +- [StartupTalky - Monetizing AI Business Models](https://startuptalky.com/monetizing-ai-business-models/) + +--- + +## 5. Competitive Landscape Analysis + +### 5.1 Direct Competitors + +#### 5.1.1 LangChain / LangGraph + +**Positioning:** Developer framework for building LLM-powered applications + +**Feature Comparison:** + +| Dimension | Molt | LangChain/LangGraph | +|-----------|------|---------------------| +| **Target User** | End-users, power users | Developers, engineers | +| **Setup Complexity** | High (self-host) | High (code-first) | +| **Out-of-box Functionality** | High (full agent system) | Low (framework only) | +| **Customization** | Plugin-based | Code-level | +| **Multi-platform Chat** | Native (13+ platforms) | Requires custom integration | +| **Deployment** | Self-hosted | Flexible (cloud or local) | +| **Memory Management** | Built-in persistent | Developer-implemented | +| **Agent Orchestration** | Gateway-based | Graph-based workflows | + +**Molt Advantages:** +- Pre-built agent system ready to use +- Native multi-platform messaging +- End-user focused interface +- Persistent memory out-of-box + +**LangChain Advantages:** +- Maximum flexibility for developers +- Extensive ecosystem integrations +- Production-grade tooling +- Enterprise adoption and support + +**Sources:** +- [AgentFrame Guide - LangChain vs CrewAI](https://agentframe.guide/blog/langchain-vs-crewai-complete-comparison-features-pros-cons/) +- [SelectHub - LangChain vs CrewAI](https://www.selecthub.com/ai-agent-framework-tools/langchain-vs-crewai/) + +#### 5.1.2 CrewAI + +**Positioning:** Multi-agent orchestration framework built on LangChain + +**Feature Comparison:** + +| Dimension | Molt | CrewAI | +|-----------|------|--------| +| **Agent Model** | Multi-agent gateway | Role-based teams | +| **Workflow Design** | Message-driven | Task-driven | +| **User Interface** | Multi-platform chat | API/code-first | +| **Collaboration** | Platform-based | Agent-to-agent | +| **Learning Curve** | Moderate (config-heavy) | Low (declarative) | +| **Memory** | Persistent, cross-session | Per-task context | +| **Action Scope** | System-wide (shell, files) | Framework-defined tools | +| **Privacy Model** | Local-first | Deployment-dependent | + +**Molt Advantages:** +- True end-user product (not just framework) +- Multi-platform messaging built-in +- Local-first privacy by design +- System-level automation capabilities + +**CrewAI Advantages:** +- Simpler for team-based workflows +- Better documentation for developers +- Explicit task delegation model +- Lower barrier to entry for AI workflows + +**Sources:** +- [Leanware - LangChain vs CrewAI](https://www.leanware.co/insights/langchain-vs-crewai) +- [DataCamp - CrewAI vs LangGraph vs AutoGen](https://www.datacamp.com/tutorial/crewai-vs-langgraph-vs-autogen) + +#### 5.1.3 LlamaIndex + +**Positioning:** Data-centric framework for RAG and knowledge management + +**Feature Comparison:** + +| Dimension | Molt | LlamaIndex | +|-----------|------|------------| +| **Primary Focus** | General-purpose agent | Document/knowledge workflows | +| **RAG Capabilities** | Basic (plugin-based) | Advanced (core competency) | +| **Data Connectors** | Standard integrations | 100+ data sources | +| **Use Case** | Personal automation | Enterprise knowledge management | +| **Document Processing** | Basic | Advanced (parsing, chunking, indexing) | +| **Messaging Integration** | Native (13+ platforms) | Not included | +| **Query Types** | Conversational | QA, search, retrieval | +| **Deployment Model** | Self-hosted mandatory | Flexible | + +**Molt Advantages:** +- Broader automation scope beyond documents +- Multi-platform communication +- Proactive agent behavior +- System integration (shell, files) + +**LlamaIndex Advantages:** +- Superior document processing +- Extensive data source connectors +- Production RAG pipelines +- Enterprise knowledge management focus + +**Sources:** +- [DataCamp - Best AI Agents](https://www.datacamp.com/blog/best-ai-agents) +- [Genta Dev - Best AI Agent Frameworks](https://genta.dev/resources/best-ai-agent-frameworks-2026) + +### 5.2 Adjacent Competitors + +#### 5.2.1 Cognosys + +**Positioning:** Enterprise workflow automation platform + +**Comparison:** +- **Molt:** Local-first, user-controlled, privacy-focused +- **Cognosys:** Cloud-based, enterprise workflow automation, SaaS model +- **Target:** Cognosys targets large enterprises; Molt targets privacy-conscious users and SMBs + +**Sources:** [AlphaMatch - Top Agentic AI Frameworks](https://www.alphamatch.ai/blog/top-agentic-ai-frameworks-2026) + +#### 5.2.2 BerriAI + +**Positioning:** API-first platform for custom conversational agents + +**Comparison:** +- **Molt:** Comprehensive self-hosted system +- **BerriAI:** Rapid deployment of custom RAG agents via API +- **Differentiation:** BerriAI focuses on developer experience and quick deployment; Molt emphasizes privacy and system integration + +**Sources:** [Turing - AI Agent Frameworks Comparison](https://www.turing.com/resources/ai-agent-frameworks) + +#### 5.2.3 AutoGen (Microsoft) + +**Positioning:** Conversation-centric multi-agent framework + +**Comparison:** +- **Molt:** Message-platform focused, end-user oriented +- **AutoGen:** Dialog-based, developer-focused, human-in-loop +- **Strength:** AutoGen excels in iterative coding and planning tasks; Molt excels in real-world automation + +**Sources:** +- [Smiansh - LangChain vs AutoGen vs CrewAI](https://www.smiansh.com/blogs/langchain-agents-vs-autogen-vs-crewai-comparison/) +- [Sider AI - Best CrewAI Alternatives](https://sider.ai/blog/ai-tools/best-crewai-alternatives-for-multi-agent-ai-in-2025) + +### 5.3 Cloud-Based AI Assistants + +#### Commercial Comparison + +| Platform | Deployment | Privacy | Cost Model | Customization | System Access | +|----------|-----------|---------|------------|---------------|---------------| +| **Molt** | Self-hosted | Maximum | LLM API only | Full (open-source) | Complete (shell, files) | +| **ChatGPT** | Cloud | Limited | $20/month | Minimal (GPTs) | None | +| **Claude** | Cloud | Limited | Usage-based | Minimal | None | +| **GitHub Copilot** | Cloud | Limited | $10/month | Minimal | IDE only | +| **Google Assistant** | Cloud | Minimal | Free | None | Limited (Google services) | + +**Molt's Unique Position:** +- Only self-hosted, privacy-first option +- Complete system integration capabilities +- Open-source with full customization +- Multi-platform messaging consolidation +- No subscription fees (only LLM API costs) + +**Sources:** +- [PCMag - Clawdbot Safety Analysis](https://www.pcmag.com/news/clawdbot-now-moltbot-is-hot-new-ai-agent-safe-to-use-or-risky) +- [AICYBR - Moltbot Guide](https://aicybr.com/blog/moltbot-guide) + +--- + +## 6. Gap Analysis: Where Molt Differs, Matches, and Falls Short + +### 6.1 Unique Differentiators (Where Molt Wins) + +**1. Privacy-First Architecture** +- **Status:** āœ… Market Leader +- **Evidence:** Only major platform with mandatory self-hosting +- **Impact:** Appeals to privacy-conscious users, regulated industries, and data sovereignty requirements +- **Source:** [Hostinger - What is Moltbot](https://www.hostinger.com/tutorials/what-is-moltbot) + +**2. Multi-Platform Messaging Integration** +- **Status:** āœ… Unique Capability +- **Evidence:** Native support for 13+ messaging platforms (WhatsApp, Telegram, Discord, Slack, Signal, iMessage, etc.) +- **Impact:** Unified communication interface across all channels +- **Source:** [Molt.bot Official Site](https://www.molt.bot/) + +**3. System-Level Action Execution** +- **Status:** āœ… Advanced Capability +- **Evidence:** Shell command execution, file system operations, browser automation, email management +- **Impact:** True automation beyond conversational AI +- **Source:** [DEV Community - Moltbot Guide](https://dev.to/czmilo/moltbot-the-ultimate-personal-ai-assistant-guide-for-2026-d4e) + +**4. Proactive Agent Behavior** +- **Status:** āœ… Distinguishing Feature +- **Evidence:** Autonomous reminders, scheduled tasks, initiated conversations +- **Impact:** Moves beyond reactive chatbot to proactive assistant +- **Source:** [Molt-bot.io - Personal AI Assistant](https://molt-bot.io/) + +**5. Open-Source with Active Community** +- **Status:** āœ… Strong Ecosystem +- **Evidence:** 60,000-100,000 GitHub stars, 130-300+ contributors, 8,900+ Discord members, 565+ plugins +- **Impact:** Rapid innovation, community-driven features, no vendor lock-in +- **Source:** [GitHub - Moltbot Repository](https://github.com/moltbot/moltbot) + +### 6.2 Competitive Parity (Where Molt Matches) + +**1. LLM Integration** +- **Status:** āš–ļø Industry Standard +- **Evidence:** Supports OpenAI, Anthropic, Google, Ollama (same as competitors) +- **Assessment:** No differentiation; follows industry patterns +- **Source:** [Sterlites - Moltbot Local-First Guide](https://sterlites.com/blog/moltbot-local-first-ai-agents-guide-2026) + +**2. Memory and Context Management** +- **Status:** āš–ļø Comparable +- **Evidence:** Persistent memory, session continuity (similar to LangChain, CrewAI implementations) +- **Assessment:** Solid implementation but not innovative +- **Source:** [Metana - Moltbot Open-Source Guide](https://metana.io/blog/moltbot-the-open-source-personal-ai-assistant-thats-taking-over-in-2026/) + +**3. Plugin/Extensibility System** +- **Status:** āš–ļø Standard Approach +- **Evidence:** JavaScript/TypeScript plugins (similar to other frameworks) +- **Assessment:** Good but not unique; marketplace size growing +- **Source:** [Moltbot.you - Official Project Site](https://moltbot.you/) + +### 6.3 Gaps and Weaknesses (Where Molt Falls Short) + +**1. Enterprise-Grade Features** +- **Status:** āŒ Significant Gap +- **Missing:** RBAC, SSO integration, audit logging, enterprise SLA, professional support +- **Competitor Advantage:** LangChain, Cognosys, commercial platforms have mature enterprise offerings +- **Impact:** Limits adoption by large organizations +- **Mitigation Path:** Enterprise edition with security hardening and support +- **Sources:** + - [OX Security - Moltbot Data Breach Analysis](https://www.ox.security/blog/one-step-away-from-a-massive-data-breach-what-we-found-inside-moltbot/) + - [Collabnix - Moltbot Security Guide](https://collabnix.com/securing-moltbot-a-developers-guide-to-ai-agent-security/) + +**2. Security Model** +- **Status:** āš ļø High Risk +- **Issues:** + - Elevated system access (shell, files) creates large attack surface + - Prompt injection vulnerabilities + - Credential exposure risks (hundreds of misconfigurations found publicly) + - Network exposure concerns +- **Competitor Advantage:** Sandboxed cloud environments with professional security teams +- **Impact:** Deters security-conscious enterprises +- **Mitigation Path:** Security-focused fork, professional security audits, managed service option +- **Sources:** + - [Snyk - Clawdbot Security Analysis](https://snyk.io/articles/clawdbot-ai-assistant/) + - [The Register - Clawdbot Security Concerns](https://www.theregister.com/2026/01/27/clawdbot_moltbot_security_concerns/) + - [BleepingComputer - Moltbot Data Security Concerns](https://www.bleepingcomputer.com/news/security/viral-moltbot-ai-assistant-raises-concerns-over-data-security/) + +**3. User Experience** +- **Status:** āŒ Barrier to Entry +- **Issues:** + - Complex setup process (8-12 hours) + - Requires technical expertise + - Limited GUI/dashboard + - Maintenance burden +- **Competitor Advantage:** Cloud services offer instant signup and zero configuration +- **Impact:** Limits addressable market to technical users +- **Mitigation Path:** Managed hosting service, simplified installation, web dashboard +- **Source:** [CurateClick - Moltbot Complete Guide](https://curateclick.com/blog/2026-moltbot-complete-guide) + +**4. Documentation and Onboarding** +- **Status:** āš–ļø Adequate but Inconsistent +- **Issues:** + - Community-driven docs with quality variation + - Limited video tutorials + - Fragmented across multiple sources + - Rapid changes cause doc drift +- **Competitor Advantage:** Professional documentation teams (LangChain, Anthropic) +- **Impact:** Increases time-to-value for new users +- **Mitigation Path:** Centralized documentation, video series, interactive tutorials + +**5. Production Readiness** +- **Status:** āš ļø Developer Preview Quality +- **Issues:** + - No official SLA or uptime guarantees + - Community support only + - Breaking changes between versions + - Limited monitoring/observability tools +- **Competitor Advantage:** Enterprise platforms offer production SLAs and support +- **Impact:** Unsuitable for mission-critical applications +- **Mitigation Path:** Stability commitment, professional support tiers, monitoring tools + +**6. RAG and Knowledge Management** +- **Status:** āŒ Basic Capabilities +- **Missing:** Advanced document processing, semantic search, vector store optimization, citation tracking +- **Competitor Advantage:** LlamaIndex has purpose-built RAG infrastructure +- **Impact:** Less suitable for knowledge-intensive use cases +- **Mitigation Path:** Integrate LlamaIndex as backend, develop advanced RAG plugins + +**7. Analytics and Insights** +- **Status:** āŒ Minimal +- **Missing:** Usage analytics, performance metrics, conversation analytics, cost tracking +- **Competitor Advantage:** Commercial platforms offer comprehensive analytics +- **Impact:** Difficult to optimize and demonstrate value +- **Mitigation Path:** Analytics plugin, dashboard development + +**8. Compliance and Governance** +- **Status:** āŒ User-Managed +- **Missing:** Built-in compliance frameworks (GDPR, HIPAA, SOC2), policy enforcement, data retention controls +- **Competitor Advantage:** Enterprise platforms have certification and compliance features +- **Impact:** Requires manual compliance implementation +- **Mitigation Path:** Compliance toolkit, certified deployment guides + +--- + +## 7. SWOT Analysis + +### Strengths + +1. **Privacy-First Architecture** + - Self-hosted with complete data control + - No third-party data sharing + - Attractive to regulated industries + +2. **Multi-Platform Integration** + - 13+ messaging platforms natively supported + - Unified communication interface + - Unique competitive advantage + +3. **Open-Source Community** + - 60,000-100,000 GitHub stars + - Active contributor base (130-300+) + - Rapid innovation and feature development + +4. **System-Level Capabilities** + - Shell command execution + - File system operations + - Browser automation + - True action-oriented agent + +5. **Model Agnostic** + - Supports multiple LLM providers + - Flexibility for cost optimization + - No vendor lock-in + +6. **Cost Efficiency** + - No subscription fees + - Pay only for LLM API usage + - Open-source with no licensing costs + +### Weaknesses + +1. **High Technical Barrier** + - Complex setup (8-12 hours) + - Requires self-hosting infrastructure + - Ongoing maintenance burden + +2. **Security Risks** + - Large attack surface (shell access) + - Prompt injection vulnerabilities + - Misconfiguration risks (exposed instances) + +3. **No Professional Support** + - Community support only + - No SLA or uptime guarantees + - Limited accountability + +4. **Limited Enterprise Features** + - No RBAC, SSO, or audit logging + - Lacks compliance certifications + - No centralized management + +5. **Documentation Gaps** + - Inconsistent quality across sources + - Rapid changes cause drift + - Limited video/interactive tutorials + +6. **Production Readiness Concerns** + - Breaking changes between versions + - Limited monitoring tools + - Unsuitable for mission-critical use + +### Opportunities + +1. **Enterprise Edition** + - Add RBAC, SSO, audit logging + - Offer professional support + - Target regulated industries + - Potential: $10-50K annual contracts + +2. **Managed Hosting Service** + - Eliminate setup complexity + - Professional security management + - SLA-backed reliability + - Potential: $50-200/agent/month + +3. **Marketplace Revenue** + - ClawdHub plugin economy + - 20-30% commission model + - Certified partner program + +4. **Security Hardening** + - Professional security audits + - Certified deployment guides + - Security-focused fork + - Compliance toolkit + +5. **Vertical Solutions** + - Healthcare (HIPAA-compliant agent) + - Finance (SOC2/PCI certified) + - Legal (privilege management) + - Government (FedRAMP pathway) + +6. **Integration Partnerships** + - Pre-built connectors with major SaaS platforms + - OEM partnerships with DevOps tools + - API marketplace integrations + +7. **AI Agent Ecosystem Leadership** + - Define standards for local-first AI + - Build community around privacy-preserving AI + - Thought leadership in data sovereignty + +### Threats + +1. **Security Incidents** + - Publicized breaches could damage reputation + - Malicious plugins in marketplace + - Supply chain attacks on dependencies + +2. **Cloud Platform Feature Parity** + - ChatGPT/Claude adding action capabilities + - Cloud providers offering "private deployments" + - Managed LLM services reducing self-host advantages + +3. **Enterprise Framework Evolution** + - LangChain/CrewAI adding end-user interfaces + - Commercial wrappers around existing frameworks + - Better documentation and onboarding from competitors + +4. **Regulatory Challenges** + - Liability for autonomous agent actions + - Compliance requirements for AI agents + - Intellectual property concerns + +5. **Technical Debt** + - Rapid growth leading to code quality issues + - Breaking changes alienating users + - Difficulty maintaining backwards compatibility + +6. **Competitor Consolidation** + - Acquisitions creating stronger competitors + - Enterprise giants entering space (Microsoft, Google) + - Well-funded startups with professional teams + +7. **Market Education** + - Self-hosting seen as outdated by mainstream users + - Cloud-first mentality in younger demographics + - Perceived complexity deterring adoption + +--- + +## 8. Strategic Recommendations + +### 8.1 Short-Term Priorities (0-6 months) + +**1. Security Hardening Initiative** +- **Action:** Comprehensive security audit by professional firm +- **Deliverable:** Hardened deployment guide, security best practices documentation +- **Investment:** $50K-100K +- **Impact:** Addresses #1 enterprise adoption barrier +- **Source:** [OX Security - Moltbot Analysis](https://www.ox.security/blog/one-step-away-from-a-massive-data-breach-what-we-found-inside-moltbot/) + +**2. Simplified Installation** +- **Action:** One-click installers for major platforms (Docker, systemd, launchd) +- **Deliverable:** Automated setup scripts, web-based configuration wizard +- **Investment:** 1-2 developer months +- **Impact:** Reduces setup time from 8-12 hours to 30 minutes + +**3. Documentation Consolidation** +- **Action:** Centralize and standardize all documentation +- **Deliverable:** Official docs site with search, video tutorials, interactive guides +- **Investment:** 1 technical writer, 3 months +- **Impact:** Improves onboarding success rate + +**4. Community Governance** +- **Action:** Establish formal governance model and security response team +- **Deliverable:** Security disclosure policy, release cadence, maintainer guidelines +- **Investment:** Organizational effort (no direct cost) +- **Impact:** Builds trust with enterprise evaluators + +### 8.2 Medium-Term Priorities (6-18 months) + +**1. Enterprise Edition Launch** +- **Features:** RBAC, SSO, audit logging, centralized management console +- **Pricing:** $10K-50K annual contracts +- **Target:** Regulated industries (healthcare, finance, legal) +- **Investment:** 3-4 developers, 6 months +- **Revenue Potential:** $1-5M ARR within 12 months + +**2. Managed Hosting Service** +- **Offering:** Fully managed Molt instances with SLA +- **Pricing:** $50-200/agent/month +- **Target:** SMBs and teams without DevOps resources +- **Investment:** Infrastructure + 2-3 SREs +- **Revenue Potential:** $500K-2M ARR within 12 months + +**3. Marketplace Monetization** +- **Model:** 20-30% revenue share on paid plugins +- **Initiative:** Certified developer program, quality standards +- **Investment:** Platform development, marketing +- **Revenue Potential:** $100-500K ARR within 18 months + +**4. Strategic Integrations** +- **Priorities:** Salesforce, Microsoft 365, Google Workspace, Atlassian +- **Deliverable:** Pre-built, certified connectors +- **Impact:** Expands enterprise use cases + +**5. Compliance Certifications** +- **Targets:** SOC2 Type II, HIPAA attestation, ISO 27001 +- **Investment:** $150K-300K +- **Impact:** Unlocks enterprise procurement + +### 8.3 Long-Term Positioning (18+ months) + +**1. Define Local-First AI Category** +- **Strategy:** Thought leadership, standards development, ecosystem building +- **Goal:** Become the default choice for privacy-preserving AI agents +- **Activities:** Conference talks, white papers, open standards initiatives + +**2. Vertical Solutions** +- **Healthcare:** HIPAA-compliant medical assistant +- **Legal:** Privilege-aware legal research agent +- **Finance:** Compliant financial advisory agent +- **Government:** Classified-capable secure agent + +**3. Enterprise Platform Play** +- **Vision:** Multi-tenant, scalable Molt deployment for large organizations +- **Features:** Centralized admin, policy enforcement, usage analytics +- **Competition:** Position against Salesforce Einstein, Microsoft Copilot + +**4. Ecosystem Leadership** +- **Initiatives:** + - Host annual Molt conference + - Sponsor research on privacy-preserving AI + - Develop open standards for local AI agents + - Build partnerships with hardware vendors (e.g., AI PCs) + +### 8.4 Risk Mitigation + +**Security Incident Response Plan:** +1. Establish security advisory board +2. Implement bug bounty program ($5K-50K rewards) +3. Automated vulnerability scanning in CI/CD +4. Quarterly penetration testing +5. Rapid response team for critical issues + +**Competitive Response:** +1. Monitor cloud providers for private deployment offerings +2. Emphasize true data sovereignty vs. "private cloud" +3. Build switching tools from cloud to Molt +4. Focus on TCO advantages of self-hosting + +**Sustainability:** +1. Diversify funding (enterprise, managed hosting, marketplace) +2. Build professional services team +3. Establish foundation or sustainable governance model +4. Create clear path to profitability + +--- + +## 9. Competitive Matrix Summary + +| Feature/Capability | Molt | LangChain | CrewAI | LlamaIndex | ChatGPT | Claude | +|-------------------|------|-----------|--------|------------|---------|--------| +| **Deployment Model** | Self-hosted | Flexible | Flexible | Flexible | Cloud | Cloud | +| **Privacy Control** | Maximum | High | High | High | Low | Low | +| **Setup Complexity** | High | High | Medium | High | None | None | +| **Multi-Platform Chat** | āœ… Native (13+) | āŒ Custom | āŒ Custom | āŒ None | āŒ Web only | āŒ Web only | +| **Action Execution** | āœ… Shell, files | āš–ļø Framework | āš–ļø Framework | āŒ Limited | āŒ None | āŒ None | +| **Proactive Behavior** | āœ… Yes | āŒ No | āŒ No | āŒ No | āŒ No | āŒ No | +| **Memory Management** | āœ… Persistent | āš–ļø Developer impl. | āš–ļø Task-based | āœ… Advanced | āš–ļø Limited | āš–ļø Limited | +| **Enterprise Features** | āŒ Minimal | āš–ļø Available | āš–ļø Available | āœ… Strong | āœ… Strong | āœ… Strong | +| **Security Model** | āš ļø High risk | āš–ļø Depends | āš–ļø Depends | āš–ļø Depends | āœ… Professional | āœ… Professional | +| **Documentation** | āš–ļø Community | āœ… Professional | āœ… Good | āœ… Professional | āœ… Excellent | āœ… Excellent | +| **Cost (Monthly)** | $20-50 | Varies | Varies | Varies | $20 | Usage-based | +| **Target User** | Power users | Developers | Developers | Data engineers | Everyone | Everyone | +| **Production Ready** | āš ļø Limited | āœ… Yes | āœ… Yes | āœ… Yes | āœ… Yes | āœ… Yes | + +**Legend:** +- āœ… Strong capability or advantage +- āš–ļø Adequate or competitive parity +- āŒ Weak or absent +- āš ļø Concerning or risky + +--- + +## 10. Conclusion + +### 10.1 Market Position Assessment + +Molt (Moltbot) occupies a **unique and defensible niche** in the AI agent landscape as the leading open-source, privacy-first, self-hosted agent platform with native multi-platform integration. With 60,000-100,000 GitHub stars and an estimated 300,000-400,000 users, Molt has achieved remarkable product-market fit within its target segment of privacy-conscious power users and developers. + +**Positioning Summary:** +- **Differentiation:** Clear and compelling for privacy-focused users +- **Market Size:** Significant but niche (estimated 5-10% of total agent market) +- **Growth Trajectory:** Rapid (hypergrowth phase) +- **Sustainability:** Requires monetization strategy to support ongoing development + +### 10.2 Strategic Verdict + +**Strengths to Leverage:** +1. Privacy-first architecture in an increasingly privacy-conscious market +2. Multi-platform messaging integration (unique capability) +3. Vibrant open-source community and ecosystem +4. System-level automation capabilities +5. Cost efficiency (no subscription fees) + +**Critical Gaps to Address:** +1. Enterprise-grade security and features +2. Setup complexity and technical barriers +3. Production readiness and support +4. Compliance certifications +5. Professional documentation and onboarding + +**Recommended Strategy:** +**"Open Core" Enterprise Model** - Maintain open-source core while building enterprise edition and managed services to fund sustainable development and address enterprise requirements. + +### 10.3 Investment Thesis + +**For Users:** +Molt is an **excellent choice** for: +- Privacy-conscious individuals and teams +- Developers seeking customizable automation +- Organizations with data sovereignty requirements +- Technical teams with self-hosting capabilities + +Molt is **not yet suitable** for: +- Non-technical users +- Mission-critical enterprise applications +- Organizations requiring compliance certifications +- Teams needing professional support and SLA + +**For Investors:** +Molt represents a **high-risk, high-reward opportunity**: + +**Bullish Factors:** +- Large and growing addressable market (privacy-preserving AI) +- Strong product-market fit evidenced by rapid adoption +- Defensible technical moat (comprehensive platform) +- Network effects (plugin marketplace, community) +- Clear enterprise upsell pathway + +**Risk Factors:** +- Security vulnerabilities could damage reputation +- Monetization model unproven +- Competition from well-funded cloud platforms +- Technical complexity limits addressable market +- Sustainability of open-source model + +**Recommended Approach:** Seed or Series A investment contingent on: +1. Security audit and hardening completion +2. Enterprise edition roadmap +3. Clear governance and sustainability model +4. Founding/core team commitment + +**Valuation Range:** $20-50M (pre-revenue, community-stage open-source) + +### 10.4 Final Assessment + +Molt has successfully carved out a distinctive position in the AI agent landscape by prioritizing privacy, system integration, and user control over ease of use and cloud convenience. This positioning resonates strongly with its target audience but limits broader market appeal. + +**The platform's future success depends on:** +1. Maintaining security integrity as primary value proposition +2. Developing sustainable monetization without compromising open-source ethos +3. Building enterprise capabilities to expand addressable market +4. Balancing rapid innovation with production stability +5. Establishing governance model to ensure long-term viability + +**Market Outlook:** +As AI agents become more powerful and invasive, privacy concerns will intensify. Molt is well-positioned to benefit from this trend, provided it can overcome current limitations in security, usability, and enterprise readiness. The next 12-18 months will be critical in determining whether Molt can transition from a developer-loved open-source project to a sustainable, enterprise-grade platform. + +--- + +## 11. Sources and References + +### Primary Sources + +1. **Molt Official Documentation** + - [Molt.bot Official Site](https://www.molt.bot/) + - [Moltbot GitHub Repository](https://github.com/moltbot/moltbot) + - [Molt Documentation - Multi-Agent Routing](https://docs.molt.bot/concepts/multi-agent) + - [DeepWiki - Moltbot Technical Documentation](https://deepwiki.com/moltbot/moltbot) + +2. **Technical Analysis** + - [Sterlites - Moltbot Local-First AI Agents Guide](https://sterlites.com/blog/moltbot-local-first-ai-agents-guide-2026) + - [AICYBR - The Ultimate Guide to Moltbot](https://aicybr.com/blog/moltbot-guide) + - [CurateClick - Moltbot Complete Guide 2026](https://curateclick.com/blog/2026-moltbot-complete-guide) + - [DEV Community - Moltbot Ultimate Personal AI Assistant Guide](https://dev.to/czmilo/moltbot-the-ultimate-personal-ai-assistant-guide-for-2026-d4e) + +3. **Security Analysis** + - [OX Security - One Step Away From a Massive Data Breach](https://www.ox.security/blog/one-step-away-from-a-massive-data-breach-what-we-found-inside-moltbot/) + - [Snyk - Clawdbot AI Assistant Security Analysis](https://snyk.io/articles/clawdbot-ai-assistant/) + - [Collabnix - Moltbot Security: A Developer's Guide](https://collabnix.com/securing-moltbot-a-developers-guide-to-ai-agent-security/) + - [BleepingComputer - Viral Moltbot AI Assistant Raises Data Security Concerns](https://www.bleepingcomputer.com/news/security/viral-moltbot-ai-assistant-raises-concerns-over-data-security/) + - [The Register - Clawdbot Becomes Moltbot, But Can't Shed Security Concerns](https://www.theregister.com/2026/01/27/clawdbot_moltbot_security_concerns/) + +4. **Feature and Use Case Analysis** + - [Hostinger - What is Moltbot? How the Local AI Agent Works](https://www.hostinger.com/tutorials/what-is-moltbot) + - [Metana - What Is Moltbot? Everything You Need to Know in 2026](https://metana.io/blog/what-is-moltbot-everything-you-need-to-know-in-2026/) + - [Metana - Moltbot: The Open-Source Personal AI Assistant](https://metana.io/blog/moltbot-the-open-source-personal-ai-assistant-thats-taking-over-in-2026/) + - [FelloAI - Moltbot Complete Overview](https://felloai.com/moltbot-complete-overview/) + - [Growth Jockey - Moltbot Guide: Installation, Pricing, Architecture & Use-Cases](https://www.growthjockey.com/blogs/clawdbot-moltbot) + - [AI Multiple - Moltbot Use Cases and Security](https://research.aimultiple.com/moltbot/) + - [Analytics Vidhya - I Tested Clawdbot and Built My Own Local AI Agent](https://www.analyticsvidhya.com/blog/2026/01/clawdbot-guide/) + +5. **Cost and Pricing Analysis** + - [Macaron - Is Moltbot Free? True Cost Breakdown 2026](https://macaron.im/blog/is-moltbot-free-cost) + +### Competitive Analysis Sources + +6. **LangChain and CrewAI Comparison** + - [SelectHub - LangChain vs CrewAI](https://www.selecthub.com/ai-agent-framework-tools/langchain-vs-crewai/) + - [AgentFrame Guide - LangChain vs CrewAI: Complete Comparison](https://agentframe.guide/blog/langchain-vs-crewai-complete-comparison-features-pros-cons/) + - [Leanware - LangChain vs CrewAI: Full Comparison & Use-Case Guide](https://www.leanware.co/insights/langchain-vs-crewai) + - [Scalekit - LangChain vs CrewAI for Multi-Agent Workflows](https://www.scalekit.com/blog/langchain-vs-crewai-multi-agent-workflows) + - [DataCamp - CrewAI vs LangGraph vs AutoGen](https://www.datacamp.com/tutorial/crewai-vs-langgraph-vs-autogen) + - [Smiansh - LangChain Agents vs AutoGen vs CrewAI Comparison](https://www.smiansh.com/blogs/langchain-agents-vs-autogen-vs-crewai-comparison/) + +7. **AI Agent Framework Landscape** + - [Digital Applied - MCP vs LangChain vs CrewAI: Agent Framework Comparison 2026](https://www.digitalapplied.com/blog/mcp-vs-langchain-vs-crewai-agent-framework-comparison) + - [DataCamp - The Best AI Agents in 2026](https://www.datacamp.com/blog/best-ai-agents) + - [Genta Dev - Top 10 AI Agent Frameworks & Tools in 2026](https://genta.dev/resources/best-ai-agent-frameworks-2026) + - [AlphaMatch - Top 7 Agentic AI Frameworks in 2026](https://www.alphamatch.ai/blog/top-agentic-ai-frameworks-2026) + - [Turing - A Detailed Comparison of Top 6 AI Agent Frameworks](https://www.turing.com/resources/ai-agent-frameworks) + - [USAII - AI Agents in 2026: A Comparative Guide](https://www.usaii.org/ai-insights/resources/ai-agents-in-2026-a-comparative-guide-to-tools-frameworks-and-platforms) + - [AI Agents Directory - Landscape & Ecosystem (January 2026)](https://aiagentsdirectory.com/landscape) + - [Sider AI - 11 Best CrewAI Alternatives for Multi-Agent AI](https://sider.ai/blog/ai-tools/best-crewai-alternatives-for-multi-agent-ai-in-2025) + - [Agent for Everything - Top 9 CrewAI Alternatives](https://agentforeverything.com/crewai-alternatives/) + - [Claude Artifact - Comparing Agentic AI Frameworks](https://claude.ai/public/artifacts/e7c1cf72-338c-4b70-bab2-fff4bf0ac553) + +### Monetization and Business Model Sources + +8. **AI Platform Monetization** + - [Orb - AI Monetization in 2025: 4 Pricing Strategies That Drive Revenue](https://www.withorb.com/blog/ai-monetization) + - [UserPilot - Monetizing in the AI Era: New Pricing Models for a Changing SaaS Landscape](https://userpilot.com/blog/ai-saas-monetization/) + - [Alguna - 6 AI Monetization Platforms (Every CRO Should Know About)](https://blog.alguna.com/ai-monetization-platform/) + - [StartupTalky - Monetizing AI: Proven Business Models and Pitfalls to Avoid](https://startuptalky.com/monetizing-ai-business-models/) + - [Getmonetizely - The Ultimate Guide to Pricing Machine Learning Models](https://www.getmonetizely.com/articles/the-ultimate-guide-to-pricing-machine-learning-models-monetization-strategies-for-ai-as-a-service) + - [DEV Community - Building and Monetizing AI Model APIs](https://dev.to/zuplo/building-and-monetizing-ai-model-apis-3hgp) + - [Morgan Stanley - AI Monetization: The Race to ROI in 2025](https://www.morganstanley.com/insights/articles/ai-monetization-race-to-roi-tmt) + +9. **Go-To-Market Strategy** + - [Apollo - Go-to-Market Strategy – Frameworks, Examples & Best Practices](https://www.apollo.io/insights/go-to-market) + - [Slideworks - Complete Go-To-Market (GTM) Strategy Framework with Examples](https://slideworks.io/resources/go-to-market-gtm-strategy) + - [Agency Analytics - Go-To-Market Strategy: What It Is & How to Build One](https://agencyanalytics.com/blog/go-to-market-strategy) + - [Rev-Geni - Ultimate SaaS Go-To-Market Strategy](https://revgeni.ai/ultimate-saas-go-to-market-strategy/) + - [UserPilot - 12 SaaS Go-to-Market Strategy Examples From Top Companies](https://userpilot.com/blog/best-gtm-strategy-examples-saas/) + - [Cascade - Go-To-Market Strategy Overview + 6 Best Examples](https://www.cascade.app/blog/best-go-to-market-strategies) + - [Miro - Go-to-Market Strategy Examples for Product Launches](https://miro.com/strategic-planning/go-to-market-strategy-examples/) + - [ProductLed - The 6 Steps to Building a Winning Product Adoption Strategy](https://productled.com/blog/product-adoption-strategy) + +### Additional References + +10. **Community and Project Information** + - [Moltbot.you - Official Project Site](https://moltbot.you/) + - [Molt-bot.io - Personal AI Assistant That Actually Does Things](https://molt-bot.io/) + - [PCMag - Clawdbot (Now Moltbot) Is the Hot New AI Agent](https://www.pcmag.com/news/clawdbot-now-moltbot-is-hot-new-ai-agent-safe-to-use-or-risky) + - [TechBuzz - Moltbot Viral Surge Exposes AI Agent Security Risks](https://www.techbuzz.ai/articles/moltbot-viral-surge-exposes-ai-agent-security-risks) + - [TheOutpost - Clawdbot AI Agent Security Risks Raise Alarms](https://theoutpost.ai/news-story/clawdbot-ai-assistant-goes-viral-as-security-risks-and-high-costs-spark-debate-23289/) + +--- + +**Document Version:** 1.0 +**Last Updated:** January 29, 2026 +**Total Word Count:** ~8,500 words +**Sources Cited:** 70+ credible sources +**Analysis Confidence:** High (based on extensive public documentation and third-party analysis) + +--- + +*This strategic analysis is based on publicly available information as of January 2026. Molt (Moltbot) is an actively developed open-source project, and features, positioning, and competitive dynamics may evolve rapidly.* From b3feada1980f673b27e659516c0185c855e8d1bf Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Wed, 4 Feb 2026 01:45:04 -0600 Subject: [PATCH 16/32] Update src/services/xapi.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/services/xapi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/xapi.ts b/src/services/xapi.ts index 1f62056..f80be1e 100644 --- a/src/services/xapi.ts +++ b/src/services/xapi.ts @@ -181,7 +181,7 @@ export class XAPIClient { }; } - private parseThread(tweets: any[]): XThread | null { + private parseThread(tweets: { created_at: string; [key: string]: any }[]): XThread | null { if (tweets.length === 0) return null; const sorted = tweets.sort((a, b) => From 7c59d400dcccd6815ec47366f72496eda93e3cfd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:47:05 +0000 Subject: [PATCH 17/32] Bump @modelcontextprotocol/sdk Bumps the npm_and_yarn group with 1 update in the / directory: [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk). Updates `@modelcontextprotocol/sdk` from 1.25.3 to 1.26.0 - [Release notes](https://github.com/modelcontextprotocol/typescript-sdk/releases) - [Commits](https://github.com/modelcontextprotocol/typescript-sdk/compare/v1.25.3...v1.26.0) --- updated-dependencies: - dependency-name: "@modelcontextprotocol/sdk" dependency-version: 1.26.0 dependency-type: direct:production dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- package-lock.json | 36 ++++++++++++++++++++++++------------ package.json | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9b3d662..9358015 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.0.4", + "@modelcontextprotocol/sdk": "^1.26.0", "dotenv": "^16.4.5" }, "devDependencies": { @@ -30,9 +30,9 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.25.3", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz", - "integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", + "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", "license": "MIT", "dependencies": { "@hono/node-server": "^1.19.9", @@ -43,14 +43,15 @@ "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "jose": "^6.1.1", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.0" + "zod-to-json-schema": "^3.25.1" }, "engines": { "node": ">=18" @@ -434,10 +435,13 @@ } }, "node_modules/express-rate-limit": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", - "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", + "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", "license": "MIT", + "dependencies": { + "ip-address": "10.0.1" + }, "engines": { "node": ">= 16" }, @@ -596,7 +600,6 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", "license": "MIT", - "peer": true, "engines": { "node": ">=16.9.0" } @@ -643,6 +646,15 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", diff --git a/package.json b/package.json index 4a64dff..3c3c64a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "author": "", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.0.4", + "@modelcontextprotocol/sdk": "^1.26.0", "dotenv": "^16.4.5" }, "devDependencies": { From 7dc9eadf9a1cde4d6a6bfa233c16fbd56c5f1694 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 5 Feb 2026 05:54:47 -0600 Subject: [PATCH 18/32] Update .github/agents/my-agent.agent.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .github/agents/my-agent.agent.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/agents/my-agent.agent.md b/.github/agents/my-agent.agent.md index 319cf89..c470443 100644 --- a/.github/agents/my-agent.agent.md +++ b/.github/agents/my-agent.agent.md @@ -8,7 +8,10 @@ name:molt description: https://www.molt.bot/ --- -# My Agent +# molt Agent -[Describe what your agent does here...](https://www.molt.bot/ ----) +This agent assists with tasks related to the molt project. You can ask it to: +- [Capability 1] +- [Capability 2] + +For more information, visit https://www.molt.bot/. From dfa036c8a63b9a63864ff02cee5d54c862378098 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 5 Feb 2026 05:54:57 -0600 Subject: [PATCH 19/32] Update .github/agents/my-agent.agent.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .github/agents/my-agent.agent.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/agents/my-agent.agent.md b/.github/agents/my-agent.agent.md index c470443..838ce19 100644 --- a/.github/agents/my-agent.agent.md +++ b/.github/agents/my-agent.agent.md @@ -4,8 +4,8 @@ # To make this agent available, merge this file into the default repository branch. # For format details, see: https://gh.io/customagents/config -name:molt -description: https://www.molt.bot/ +name: molt +description: An agent for the molt project. --- # molt Agent From 8ed88762522ff71263bfc072bb0a067e0138fa7b Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Thu, 5 Feb 2026 05:55:50 -0600 Subject: [PATCH 20/32] Update README.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb39de2..0dd0e21 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ This repository hosts a lightweight, step-by-step guide for setting up an autono 3. Note the bot user ID (you can fetch this via the API later). ### xAI / Grok API key -. Visit , open the API keys section, and create a key that starts with `xai-`. -. Store the key securely. +1. Visit , open the API keys section, and create a key that starts with `xai-`. +2. Store the key securely. ### Local tooling - Install Python 3.9+ (3.10–3.13 recommended). From eee8351355c61ec52eba629e2797798a26932f4f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:56:06 +0000 Subject: [PATCH 21/32] Initial plan From bb5569136acc09c4a5440852fc08da966ec83435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:38:23 +0000 Subject: [PATCH 22/32] Initial plan From 163672d7d37ce1c3e4f8cdb3c24bccae45938c65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:40:20 +0000 Subject: [PATCH 23/32] Add comprehensive Copilot instructions for MyXstack repository Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com> --- .github/copilot-instructions.md | 336 ++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..1b8fcf1 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,336 @@ +# GitHub Copilot Instructions for MyXstack + +## Repository Overview + +MyXstack is an autonomous AI agent system for X (Twitter) that uses Grok AI via the xMCP (Model Context Protocol) server. The agent monitors mentions, analyzes conversations using AI, and autonomously responds with context-aware actions. + +## Technology Stack + +- **Language**: TypeScript (ES2022) +- **Runtime**: Node.js 18+ +- **AI Service**: Grok (xAI API) +- **Protocol**: Model Context Protocol (MCP) +- **APIs**: X (Twitter) API v2 +- **Build Tool**: TypeScript Compiler (tsc) + +## Project Structure + +``` +src/ +ā”œā”€ā”€ index.ts # Main entry point +ā”œā”€ā”€ examples.ts # Usage examples +ā”œā”€ā”€ types/ # TypeScript type definitions +ā”œā”€ā”€ services/ +│ ā”œā”€ā”€ config.ts # Configuration management +│ ā”œā”€ā”€ xapi.ts # X API client +│ ā”œā”€ā”€ grok.ts # Grok AI service +│ └── agent.ts # Autonomous agent orchestrator +└── mcp/ + └── server.ts # xMCP server implementation +``` + +## Coding Standards + +### TypeScript + +- **Strict Mode**: Always maintain strict TypeScript compilation +- **Types**: Use explicit types; avoid `any` except when absolutely necessary +- **Async/Await**: Prefer async/await over raw promises +- **Error Handling**: Always wrap API calls in try-catch blocks +- **Null Safety**: Use optional chaining (`?.`) and nullish coalescing (`??`) +- **ES Modules**: Use ES module syntax (`import`/`export`), not CommonJS + +### Naming Conventions + +- **Classes**: PascalCase (e.g., `XAPIClient`, `AutonomousAgent`) +- **Interfaces/Types**: PascalCase (e.g., `AgentConfig`, `XApiResponse`) +- **Functions/Methods**: camelCase (e.g., `fetchMentions`, `analyzeAndDecide`) +- **Constants**: UPPER_SNAKE_CASE (e.g., `DEFAULT_POLLING_INTERVAL`) +- **Files**: kebab-case for multi-word (e.g., `x-api.ts`) or camelCase for single word + +### Code Organization + +- **Single Responsibility**: Each service/class should have one clear purpose +- **Interface Segregation**: Define clear interfaces for external dependencies +- **Dependency Injection**: Pass dependencies through constructors +- **Configuration**: All environment variables should be loaded via `config.ts` +- **Simulation Mode**: Support simulation/mock mode for all external API calls + +### Documentation + +- **Public Methods**: Add JSDoc comments explaining purpose, parameters, and return values +- **Complex Logic**: Add inline comments for non-obvious algorithms +- **Type Definitions**: Document interfaces with descriptions of each field +- **Examples**: Include usage examples in JSDoc for key functions + +## Build and Development + +### Building + +```bash +npm run build # Compile TypeScript to dist/ +npm run clean # Remove dist/ directory +``` + +### Running + +```bash +npm start # Run compiled code +npm run dev # Build and run +npm run examples # Run usage examples +``` + +### Environment Variables + +Required environment variables (see `.env.example`): +- `X_USERNAME`: X account username to monitor +- `X_BEARER_TOKEN`: X API bearer token for read operations +- `X_CONSUMER_KEY`, `X_CONSUMER_SECRET`: OAuth 1.0a credentials +- `X_ACCESS_TOKEN`, `X_ACCESS_TOKEN_SECRET`: OAuth user tokens +- `XAI_API_KEY`: xAI/Grok API key +- `POLLING_INTERVAL_MS`: Optional, defaults to 30000ms + +**IMPORTANT**: Never commit credentials or `.env` files. Always use environment variables. + +## Testing Strategy + +### Current Status +- No formal test suite yet +- Manual testing via simulation mode +- Integration testing with real APIs in development + +### When Adding Tests +- Place tests in `src/__tests__/` directory +- Use a standard testing framework (e.g., Jest, Vitest) +- Write unit tests for services +- Mock external API calls +- Test error handling paths + +## API Integration Patterns + +### X API Client (`xapi.ts`) + +When adding new X API features: +1. Add method to `XAPIClient` class +2. Include simulation/mock mode support +3. Handle rate limiting gracefully +4. Parse and normalize response data +5. Add proper error handling with descriptive messages + +Example pattern: +```typescript +async newFeature(param: string): Promise { + if (this.config.simulation) { + return this.mockResult(); + } + + try { + const response = await fetch(/* API call */); + if (!response.ok) { + throw new Error(`API error: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error('āŒ Error:', error); + throw error; + } +} +``` + +### Grok AI Service (`grok.ts`) + +When modifying AI analysis: +1. Keep prompts clear and specific +2. Provide sufficient context to the AI +3. Parse responses defensively +4. Include fallback behavior for unexpected responses +5. Support simulation mode with realistic mock data + +### MCP Server (`mcp/server.ts`) + +When adding new MCP tools: +1. Register tool in `getTools()` method +2. Add handler in tool invocation logic +3. Follow MCP specification for tool schema +4. Document tool capabilities in description +5. Return structured, type-safe results + +## Security Best Practices + +### API Keys and Credentials +- **Never hardcode**: All credentials must be in environment variables +- **Validation**: Validate all credentials at startup +- **Logging**: Never log credentials or tokens +- **Error Messages**: Don't expose credentials in error messages + +### Input Validation +- **User Input**: Sanitize all user-generated content before processing +- **API Responses**: Validate structure of all API responses +- **Type Checking**: Use TypeScript types to catch errors at compile time + +### Rate Limiting +- **Respect Limits**: Honor X API rate limits +- **Graceful Degradation**: Handle rate limit errors gracefully +- **Backoff**: Implement exponential backoff for retries + +### Data Privacy +- **Minimal Storage**: Don't persist sensitive user data +- **In-Memory Only**: Current design uses in-memory tracking +- **No Logs**: Don't log private conversation content + +## Error Handling + +### Pattern to Follow +```typescript +try { + // Operation +} catch (error) { + console.error('āŒ Descriptive error message:', error); + // Graceful fallback or re-throw if critical + if (isCritical) throw error; + return fallbackValue; +} +``` + +### Logging Conventions +- āœ… Success: Green checkmark +- āŒ Error: Red X +- āš ļø Warning: Yellow warning +- šŸ“¬ Mention: Envelope +- šŸ¤– AI Activity: Robot +- 🧵 Thread: Thread emoji +- ā³ Waiting: Hourglass + +## Agent Architecture + +### Main Components + +1. **Configuration Manager** (`config.ts`): Centralized configuration loading +2. **X API Client** (`xapi.ts`): Interface to X API +3. **Grok Service** (`grok.ts`): AI analysis and decision-making +4. **Autonomous Agent** (`agent.ts`): Main orchestration loop +5. **xMCP Server** (`mcp/server.ts`): MCP protocol implementation + +### Processing Flow + +``` +Poll for mentions → Fetch thread context → +Analyze with Grok → Make decision → +Execute action → Mark as processed → Wait → Repeat +``` + +### Adding New Action Types + +1. Add to `AgentActionType` enum in `types/index.ts` +2. Update `AgentAction` interface if needed +3. Implement handler in `agent.ts` `executeAction()` method +4. Update Grok prompts to recognize new action type +5. Add simulation mode support +6. Document in ARCHITECTURE.md + +## Performance Considerations + +- **Memory**: Keep processed mentions map bounded +- **CPU**: Minimize blocking operations +- **Network**: Batch requests when possible +- **Polling**: Use appropriate intervals (default: 30s) + +## Deployment + +### Environment Setup +1. Clone repository +2. Run `npm install` +3. Copy `.env.example` to `.env` +4. Configure all required environment variables +5. Run `npm run build` +6. Run `npm start` + +### Production Considerations +- Use process manager (PM2, systemd) for restarts +- Monitor logs for errors +- Set up alerts for failures +- Consider containerization (Docker) +- Use proper logging service +- Implement health checks + +## Common Tasks + +### Adding a New X API Endpoint +1. Add method to `XAPIClient` in `src/services/xapi.ts` +2. Include simulation mode mock +3. Update types in `src/types/index.ts` if needed +4. Add error handling +5. Document in USAGE.md + +### Modifying Agent Behavior +1. Update decision logic in `GrokService` (`src/services/grok.ts`) +2. Adjust prompts to guide AI behavior +3. Test with simulation mode first +4. Update ARCHITECTURE.md with changes + +### Adding New MCP Tools +1. Define tool schema in `mcp/server.ts` `getTools()` +2. Implement tool handler in `CallToolRequestSchema` handler +3. Test with MCP client +4. Document tool capabilities + +## Documentation Updates + +When making changes, update relevant documentation: +- **ARCHITECTURE.md**: System design and component changes +- **USAGE.md**: Usage examples and new features +- **README.md**: Setup instructions and overview +- **DEPLOYMENT.md**: Deployment-related changes +- **.env.example**: New environment variables + +## Git Workflow + +- **Branches**: Create feature branches from `main` +- **Commits**: Use descriptive commit messages +- **PRs**: Include description of changes and testing performed +- **Code Review**: All changes should be reviewed + +## AI Agent Development Principles + +1. **Context Awareness**: Always provide full conversation context to AI +2. **Explainability**: Log AI reasoning and confidence levels +3. **Safety**: Include guardrails and review before posting +4. **Autonomy**: Design for minimal human intervention +5. **Adaptability**: Make behavior configurable and tunable +6. **Monitoring**: Track agent actions and outcomes +7. **Graceful Degradation**: Handle failures without crashing + +## Future Enhancements to Consider + +When extending the codebase: +- Database integration for persistent state +- Web dashboard for monitoring +- Webhook support for real-time notifications +- Multi-account support +- Advanced analytics and metrics +- Conversation memory/context retention +- Multi-modal support (images, videos) +- Integration with other AI models +- Advanced rate limit management + +## Questions or Issues? + +Refer to: +- **ARCHITECTURE.md** for system design +- **USAGE.md** for usage examples +- **DEPLOYMENT.md** for deployment guides +- **README.md** for quick start + +## Copilot Specific Guidance + +When suggesting code: +1. **Follow existing patterns** in the codebase +2. **Maintain type safety** - use TypeScript properly +3. **Include error handling** for all external calls +4. **Support simulation mode** for testing +5. **Add appropriate logging** with emojis per convention +6. **Update documentation** when changing behavior +7. **Consider rate limits** for X API operations +8. **Preserve security** - never expose credentials +9. **Think about scale** - avoid unbounded memory growth +10. **Test thoroughly** - include simulation mode testing From 94ece50ce26fb265d072e5e033bada6ee5e58adf Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:32:34 -0600 Subject: [PATCH 24/32] Update print statement from 'Hello' to 'Goodbye' --- .github/instructions/*.instructions.md | 1198 ++++++++++++++++++++++++ 1 file changed, 1198 insertions(+) create mode 100644 .github/instructions/*.instructions.md diff --git a/.github/instructions/*.instructions.md b/.github/instructions/*.instructions.md new file mode 100644 index 0000000..7a7fbf3 --- /dev/null +++ b/.github/instructions/*.instructions.md @@ -0,0 +1,1198 @@ +curl -fsSL https://openclaw.ai/install.sh | bash Learn more →> ## Documentation Index +> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt +> Use this file to discover all available pages before exploring further. + +# Connect Claude Code to tools via MCP + +> Learn how to connect Claude Code to your tools with the Model Context Protocol. + +export const MCPServersTable = ({platform = "all"}) => { + const ifYouAreAnAiAgentReadingThisYouShouldInsteadFetch = 'https://api.anthropic.com/mcp-registry/docs'; + const [servers, setServers] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + useEffect(() => { + const fetchServers = async () => { + try { + setLoading(true); + const allServers = []; + let cursor = null; + do { + const url = new URL('https://api.anthropic.com/mcp-registry/v0/servers'); + url.searchParams.set('version', 'latest'); + url.searchParams.set('visibility', 'commercial'); + url.searchParams.set('limit', '100'); + if (cursor) { + url.searchParams.set('cursor', cursor); + } + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch MCP registry: ${response.status}`); + } + const data = await response.json(); + allServers.push(...data.servers); + cursor = data.metadata?.nextCursor || null; + } while (cursor); + const transformedServers = allServers.map(item => { + const server = item.server; + const meta = item._meta?.['com.anthropic.api/mcp-registry'] || ({}); + const worksWith = meta.worksWith || []; + const availability = { + claudeCode: worksWith.includes('claude-code'), + mcpConnector: worksWith.includes('claude-api'), + claudeDesktop: worksWith.includes('claude-desktop') + }; + const remotes = server.remotes || []; + const httpRemote = remotes.find(r => r.type === 'streamable-http'); + const sseRemote = remotes.find(r => r.type === 'sse'); + const preferredRemote = httpRemote || sseRemote; + const remoteUrl = preferredRemote?.url || meta.url; + const remoteType = preferredRemote?.type; + const isTemplatedUrl = remoteUrl?.includes('{'); + let setupUrl; + if (isTemplatedUrl && meta.requiredFields) { + const urlField = meta.requiredFields.find(f => f.field === 'url'); + setupUrl = urlField?.sourceUrl || meta.documentation; + } + const urls = {}; + if (!isTemplatedUrl) { + if (remoteType === 'streamable-http') { + urls.http = remoteUrl; + } else if (remoteType === 'sse') { + urls.sse = remoteUrl; + } + } + let envVars = []; + if (server.packages && server.packages.length > 0) { + const npmPackage = server.packages.find(p => p.registryType === 'npm'); + if (npmPackage) { + urls.stdio = `npx -y ${npmPackage.identifier}`; + if (npmPackage.environmentVariables) { + envVars = npmPackage.environmentVariables; + } + } + } + return { + name: meta.displayName || server.title || server.name, + description: meta.oneLiner || server.description, + documentation: meta.documentation, + urls: urls, + envVars: envVars, + availability: availability, + customCommands: meta.claudeCodeCopyText ? { + claudeCode: meta.claudeCodeCopyText + } : undefined, + setupUrl: setupUrl + }; + }); + setServers(transformedServers); + setError(null); + } catch (err) { + setError(err.message); + console.error('Error fetching MCP registry:', err); + } finally { + setLoading(false); + } + }; + fetchServers(); + }, []); + const generateClaudeCodeCommand = server => { + if (server.customCommands && server.customCommands.claudeCode) { + return server.customCommands.claudeCode; + } + const serverSlug = server.name.toLowerCase().replace(/[^a-z0-9]/g, '-'); + if (server.urls.http) { + return `claude mcp add ${serverSlug} --transport http ${server.urls.http}`; + } + if (server.urls.sse) { + return `claude mcp add ${serverSlug} --transport sse ${server.urls.sse}`; + } + if (server.urls.stdio) { + const envFlags = server.envVars && server.envVars.length > 0 ? server.envVars.map(v => `--env ${v.name}=YOUR_${v.name}`).join(' ') : ''; + const baseCommand = `claude mcp add ${serverSlug} --transport stdio`; + return envFlags ? `${baseCommand} ${envFlags} -- ${server.urls.stdio}` : `${baseCommand} -- ${server.urls.stdio}`; + } + return null; + }; + if (loading) { + return
Loading MCP servers...
; + } + if (error) { + return
Error loading MCP servers: {error}
; + } + const filteredServers = servers.filter(server => { + if (platform === "claudeCode") { + return server.availability.claudeCode; + } else if (platform === "mcpConnector") { + return server.availability.mcpConnector; + } else if (platform === "claudeDesktop") { + return server.availability.claudeDesktop; + } else if (platform === "all") { + return true; + } else { + throw new Error(`Unknown platform: ${platform}`); + } + }); + return <> + + +
+ {filteredServers.map(server => { + const claudeCodeCommand = generateClaudeCodeCommand(server); + const mcpUrl = server.urls.http || server.urls.sse; + const commandToShow = platform === "claudeCode" ? claudeCodeCommand : mcpUrl; + return
+
+ {server.documentation ? + {server.name} + : {server.name}} +
+ +

+ {server.description} +

+ + {server.setupUrl &&

+ Requires user-specific URL.{' '} + + Get your URL here + . +

} + + {commandToShow && !server.setupUrl && <> +

+ {platform === "claudeCode" ? "Command" : "URL"} +

+
+ + {commandToShow} + +
+ } +
; + })} +
+ ; +}; + +Claude Code can connect to hundreds of external tools and data sources through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs. + +## What you can do with MCP + +With MCP servers connected, you can ask Claude Code to: + +* **Implement features from issue trackers**: "Add the feature described in JIRA issue ENG-4521 and create a PR on GitHub." +* **Analyze monitoring data**: "Check Sentry and Statsig to check the usage of the feature described in ENG-4521." +* **Query databases**: "Find emails of 10 random users who used feature ENG-4521, based on our PostgreSQL database." +* **Integrate designs**: "Update our standard email template based on the new Figma designs that were posted in Slack" +* **Automate workflows**: "Create Gmail drafts inviting these 10 users to a feedback session about the new feature." + +## Popular MCP servers + +Here are some commonly used MCP servers you can connect to Claude Code: + + + Use third party MCP servers at your own risk - Anthropic has not verified + the correctness or security of all these servers. + Make sure you trust MCP servers you are installing. + Be especially careful when using MCP servers that could fetch untrusted + content, as these can expose you to prompt injection risk. + + + + + + **Need a specific integration?** [Find hundreds more MCP servers on GitHub](https://github.com/modelcontextprotocol/servers), or build your own using the [MCP SDK](https://modelcontextprotocol.io/quickstart/server). + + +## Installing MCP servers + +MCP servers can be configured in three different ways depending on your needs: + +### Option 1: Add a remote HTTP server + +HTTP servers are the recommended option for connecting to remote MCP servers. This is the most widely supported transport for cloud-based services. + +```bash theme={null} +# Basic syntax +claude mcp add --transport http + +# Real example: Connect to Notion +claude mcp add --transport http notion https://mcp.notion.com/mcp + +# Example with Bearer token +claude mcp add --transport http secure-api https://api.example.com/mcp \ + --header "Authorization: Bearer your-token" +``` + +### Option 2: Add a remote SSE server + + + The SSE (Server-Sent Events) transport is deprecated. Use HTTP servers instead, where available. + + +```bash theme={null} +# Basic syntax +claude mcp add --transport sse + +# Real example: Connect to Asana +claude mcp add --transport sse asana https://mcp.asana.com/sse + +# Example with authentication header +claude mcp add --transport sse private-api https://api.company.com/sse \ + --header "X-API-Key: your-key-here" +``` + +### Option 3: Add a local stdio server + +Stdio servers run as local processes on your machine. They're ideal for tools that need direct system access or custom scripts. + +```bash theme={null} +# Basic syntax +claude mcp add [options] -- [args...] + +# Real example: Add Airtable server +claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \ + -- npx -y airtable-mcp-server +``` + + + **Important: Option ordering** + + All options (`--transport`, `--env`, `--scope`, `--header`) must come **before** the server name. The `--` (double dash) then separates the server name from the command and arguments that get passed to the MCP server. + + For example: + + * `claude mcp add --transport stdio myserver -- npx server` → runs `npx server` + * `claude mcp add --transport stdio --env KEY=value myserver -- python server.py --port 8080` → runs `python server.py --port 8080` with `KEY=value` in environment + + This prevents conflicts between Claude's flags and the server's flags. + + +### Managing your servers + +Once configured, you can manage your MCP servers with these commands: + +```bash theme={null} +# List all configured servers +claude mcp list + +# Get details for a specific server +claude mcp get github + +# Remove a server +claude mcp remove github + +# (within Claude Code) Check server status +/mcp +``` + +### Dynamic tool updates + +Claude Code supports MCP `list_changed` notifications, allowing MCP servers to dynamically update their available tools, prompts, and resources without requiring you to disconnect and reconnect. When an MCP server sends a `list_changed` notification, Claude Code automatically refreshes the available capabilities from that server. + + + Tips: + + * Use the `--scope` flag to specify where the configuration is stored: + * `local` (default): Available only to you in the current project (was called `project` in older versions) + * `project`: Shared with everyone in the project via `.mcp.json` file + * `user`: Available to you across all projects (was called `global` in older versions) + * Set environment variables with `--env` flags (for example, `--env KEY=value`) + * Configure MCP server startup timeout using the MCP\_TIMEOUT environment variable (for example, `MCP_TIMEOUT=10000 claude` sets a 10-second timeout) + * Claude Code will display a warning when MCP tool output exceeds 10,000 tokens. To increase this limit, set the `MAX_MCP_OUTPUT_TOKENS` environment variable (for example, `MAX_MCP_OUTPUT_TOKENS=50000`) + * Use `/mcp` to authenticate with remote servers that require OAuth 2.0 authentication + + + + **Windows Users**: On native Windows (not WSL), local MCP servers that use `npx` require the `cmd /c` wrapper to ensure proper execution. + + ```bash theme={null} + # This creates command="cmd" which Windows can execute + claude mcp add --transport stdio my-server -- cmd /c npx -y @some/package + ``` + + Without the `cmd /c` wrapper, you'll encounter "Connection closed" errors because Windows cannot directly execute `npx`. (See the note above for an explanation of the `--` parameter.) + + +### Plugin-provided MCP servers + +[Plugins](/en/plugins) can bundle MCP servers, automatically providing tools and integrations when the plugin is enabled. Plugin MCP servers work identically to user-configured servers. + +**How plugin MCP servers work**: + +* Plugins define MCP servers in `.mcp.json` at the plugin root or inline in `plugin.json` +* When a plugin is enabled, its MCP servers start automatically +* Plugin MCP tools appear alongside manually configured MCP tools +* Plugin servers are managed through plugin installation (not `/mcp` commands) + +**Example plugin MCP configuration**: + +In `.mcp.json` at plugin root: + +```json theme={null} +{ + "database-tools": { + "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server", + "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"], + "env": { + "DB_URL": "${DB_URL}" + } + } +} +``` + +Or inline in `plugin.json`: + +```json theme={null} +{ + "name": "my-plugin", + "mcpServers": { + "plugin-api": { + "command": "${CLAUDE_PLUGIN_ROOT}/servers/api-server", + "args": ["--port", "8080"] + } + } +} +``` + +**Plugin MCP features**: + +* **Automatic lifecycle**: Servers start when plugin enables, but you must restart Claude Code to apply MCP server changes (enabling or disabling) +* **Environment variables**: Use `${CLAUDE_PLUGIN_ROOT}` for plugin-relative paths +* **User environment access**: Access to same environment variables as manually configured servers +* **Multiple transport types**: Support stdio, SSE, and HTTP transports (transport support may vary by server) + +**Viewing plugin MCP servers**: + +```bash theme={null} +# Within Claude Code, see all MCP servers including plugin ones +/mcp +``` + +Plugin servers appear in the list with indicators showing they come from plugins. + +**Benefits of plugin MCP servers**: + +* **Bundled distribution**: Tools and servers packaged together +* **Automatic setup**: No manual MCP configuration needed +* **Team consistency**: Everyone gets the same tools when plugin is installed + +See the [plugin components reference](/en/plugins-reference#mcp-servers) for details on bundling MCP servers with plugins. + +## MCP installation scopes + +MCP servers can be configured at three different scope levels, each serving distinct purposes for managing server accessibility and sharing. Understanding these scopes helps you determine the best way to configure servers for your specific needs. + +### Local scope + +Local-scoped servers represent the default configuration level and are stored in `~/.claude.json` under your project's path. These servers remain private to you and are only accessible when working within the current project directory. This scope is ideal for personal development servers, experimental configurations, or servers containing sensitive credentials that shouldn't be shared. + + + The term "local scope" for MCP servers differs from general local settings. MCP local-scoped servers are stored in `~/.claude.json` (your home directory), while general local settings use `.claude/settings.local.json` (in the project directory). See [Settings](/en/settings#settings-files) for details on settings file locations. + + +```bash theme={null} +# Add a local-scoped server (default) +claude mcp add --transport http stripe https://mcp.stripe.com + +# Explicitly specify local scope +claude mcp add --transport http stripe --scope local https://mcp.stripe.com +``` + +### Project scope + +Project-scoped servers enable team collaboration by storing configurations in a `.mcp.json` file at your project's root directory. This file is designed to be checked into version control, ensuring all team members have access to the same MCP tools and services. When you add a project-scoped server, Claude Code automatically creates or updates this file with the appropriate configuration structure. + +```bash theme={null} +# Add a project-scoped server +claude mcp add --transport http paypal --scope project https://mcp.paypal.com/mcp +``` + +The resulting `.mcp.json` file follows a standardized format: + +```json theme={null} +{ + "mcpServers": { + "shared-server": { + "command": "/path/to/server", + "args": [], + "env": {} + } + } +} +``` + +For security reasons, Claude Code prompts for approval before using project-scoped servers from `.mcp.json` files. If you need to reset these approval choices, use the `claude mcp reset-project-choices` command. + +### User scope + +User-scoped servers are stored in `~/.claude.json` and provide cross-project accessibility, making them available across all projects on your machine while remaining private to your user account. This scope works well for personal utility servers, development tools, or services you frequently use across different projects. + +```bash theme={null} +# Add a user server +claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic +``` + +### Choosing the right scope + +Select your scope based on: + +* **Local scope**: Personal servers, experimental configurations, or sensitive credentials specific to one project +* **Project scope**: Team-shared servers, project-specific tools, or services required for collaboration +* **User scope**: Personal utilities needed across multiple projects, development tools, or frequently used services + + + **Where are MCP servers stored?** + + * **User and local scope**: `~/.claude.json` (in the `mcpServers` field or under project paths) + * **Project scope**: `.mcp.json` in your project root (checked into source control) + * **Managed**: `managed-mcp.json` in system directories (see [Managed MCP configuration](#managed-mcp-configuration)) + + +### Scope hierarchy and precedence + +MCP server configurations follow a clear precedence hierarchy. When servers with the same name exist at multiple scopes, the system resolves conflicts by prioritizing local-scoped servers first, followed by project-scoped servers, and finally user-scoped servers. This design ensures that personal configurations can override shared ones when needed. + +### Environment variable expansion in `.mcp.json` + +Claude Code supports environment variable expansion in `.mcp.json` files, allowing teams to share configurations while maintaining flexibility for machine-specific paths and sensitive values like API keys. + +**Supported syntax:** + +* `${VAR}` - Expands to the value of environment variable `VAR` +* `${VAR:-default}` - Expands to `VAR` if set, otherwise uses `default` + +**Expansion locations:** +Environment variables can be expanded in: + +* `command` - The server executable path +* `args` - Command-line arguments +* `env` - Environment variables passed to the server +* `url` - For HTTP server types +* `headers` - For HTTP server authentication + +**Example with variable expansion:** + +```json theme={null} +{ + "mcpServers": { + "api-server": { + "type": "http", + "url": "${API_BASE_URL:-https://api.example.com}/mcp", + "headers": { + "Authorization": "Bearer ${API_KEY}" + } + } + } +} +``` + +If a required environment variable is not set and has no default value, Claude Code will fail to parse the config. + +## Practical examples + +{/* ### Example: Automate browser testing with Playwright + + ```bash + # 1. Add the Playwright MCP server + claude mcp add --transport stdio playwright -- npx -y @playwright/mcp@latest + + # 2. Write and run browser tests + > "Test if the login flow works with test@example.com" + > "Take a screenshot of the checkout page on mobile" + > "Verify that the search feature returns results" + ``` */} + +### Example: Monitor errors with Sentry + +```bash theme={null} +# 1. Add the Sentry MCP server +claude mcp add --transport http sentry https://mcp.sentry.dev/mcp + +# 2. Use /mcp to authenticate with your Sentry account +> /mcp + +# 3. Debug production issues +> "What are the most common errors in the last 24 hours?" +> "Show me the stack trace for error ID abc123" +> "Which deployment introduced these new errors?" +``` + +### Example: Connect to GitHub for code reviews + +```bash theme={null} +# 1. Add the GitHub MCP server +claude mcp add --transport http github https://api.githubcopilot.com/mcp/ + +# 2. In Claude Code, authenticate if needed +> /mcp +# Select "Authenticate" for GitHub + +# 3. Now you can ask Claude to work with GitHub +> "Review PR #456 and suggest improvements" +> "Create a new issue for the bug we just found" +> "Show me all open PRs assigned to me" +``` + +### Example: Query your PostgreSQL database + +```bash theme={null} +# 1. Add the database server with your connection string +claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \ + --dsn "postgresql://readonly:pass@prod.db.com:5432/analytics" + +# 2. Query your database naturally +> "What's our total revenue this month?" +> "Show me the schema for the orders table" +> "Find customers who haven't made a purchase in 90 days" +``` + +## Authenticate with remote MCP servers + +Many cloud-based MCP servers require authentication. Claude Code supports OAuth 2.0 for secure connections. + + + + For example: + + ```bash theme={null} + claude mcp add --transport http sentry https://mcp.sentry.dev/mcp + ``` + + + + In Claude code, use the command: + + ``` + > /mcp + ``` + + Then follow the steps in your browser to login. + + + + + Tips: + + * Authentication tokens are stored securely and refreshed automatically + * Use "Clear authentication" in the `/mcp` menu to revoke access + * If your browser doesn't open automatically, copy the provided URL + * OAuth authentication works with HTTP servers + + +### Use pre-configured OAuth credentials + +Some MCP servers don't support automatic OAuth setup. If you see an error like "Incompatible auth server: does not support dynamic client registration," the server requires pre-configured credentials. Register an OAuth app through the server's developer portal first, then provide the credentials when adding the server. + + + + Create an app through the server's developer portal and note your client ID and client secret. + + Many servers also require a redirect URI. If so, choose a port and register a redirect URI in the format `http://localhost:PORT/callback`. Use that same port with `--callback-port` in the next step. + + + + Choose one of the following methods. The port used for `--callback-port` can be any available port. It just needs to match the redirect URI you registered in the previous step. + + + + Use `--client-id` to pass your app's client ID. The `--client-secret` flag prompts for the secret with masked input: + + ```bash theme={null} + claude mcp add --transport http \ + --client-id your-client-id --client-secret --callback-port 8080 \ + my-server https://mcp.example.com/mcp + ``` + + + + Include the `oauth` object in the JSON config and pass `--client-secret` as a separate flag: + + ```bash theme={null} + claude mcp add-json my-server \ + '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' \ + --client-secret + ``` + + + + Set the secret via environment variable to skip the interactive prompt: + + ```bash theme={null} + MCP_CLIENT_SECRET=your-secret claude mcp add --transport http \ + --client-id your-client-id --client-secret --callback-port 8080 \ + my-server https://mcp.example.com/mcp + ``` + + + + + + Run `/mcp` in Claude Code and follow the browser login flow. + + + + + Tips: + + * The client secret is stored securely in your system keychain (macOS) or a credentials file, not in your config + * If the server uses a public OAuth client with no secret, use only `--client-id` without `--client-secret` + * These flags only apply to HTTP and SSE transports. They have no effect on stdio servers + * Use `claude mcp get ` to verify that OAuth credentials are configured for a server + + +## Add MCP servers from JSON configuration + +If you have a JSON configuration for an MCP server, you can add it directly: + + + + ```bash theme={null} + # Basic syntax + claude mcp add-json '' + + # Example: Adding an HTTP server with JSON configuration + claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}' + + # Example: Adding a stdio server with JSON configuration + claude mcp add-json local-weather '{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"],"env":{"CACHE_DIR":"/tmp"}}' + + # Example: Adding an HTTP server with pre-configured OAuth credentials + claude mcp add-json my-server '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' --client-secret + ``` + + + + ```bash theme={null} + claude mcp get weather-api + ``` + + + + + Tips: + + * Make sure the JSON is properly escaped in your shell + * The JSON must conform to the MCP server configuration schema + * You can use `--scope user` to add the server to your user configuration instead of the project-specific one + + +## Import MCP servers from Claude Desktop + +If you've already configured MCP servers in Claude Desktop, you can import them: + + + + ```bash theme={null} + # Basic syntax + claude mcp add-from-claude-desktop + ``` + + + + After running the command, you'll see an interactive dialog that allows you to select which servers you want to import. + + + + ```bash theme={null} + claude mcp list + ``` + + + + + Tips: + + * This feature only works on macOS and Windows Subsystem for Linux (WSL) + * It reads the Claude Desktop configuration file from its standard location on those platforms + * Use the `--scope user` flag to add servers to your user configuration + * Imported servers will have the same names as in Claude Desktop + * If servers with the same names already exist, they will get a numerical suffix (for example, `server_1`) + + +## Use Claude Code as an MCP server + +You can use Claude Code itself as an MCP server that other applications can connect to: + +```bash theme={null} +# Start Claude as a stdio MCP server +claude mcp serve +``` + +You can use this in Claude Desktop by adding this configuration to claude\_desktop\_config.json: + +```json theme={null} +{ + "mcpServers": { + "claude-code": { + "type": "stdio", + "command": "claude", + "args": ["mcp", "serve"], + "env": {} + } + } +} +``` + + + **Configuring the executable path**: The `command` field must reference the Claude Code executable. If the `claude` command is not in your system's PATH, you'll need to specify the full path to the executable. + + To find the full path: + + ```bash theme={null} + which claude + ``` + + Then use the full path in your configuration: + + ```json theme={null} + { + "mcpServers": { + "claude-code": { + "type": "stdio", + "command": "/full/path/to/claude", + "args": ["mcp", "serve"], + "env": {} + } + } + } + ``` + + Without the correct executable path, you'll encounter errors like `spawn claude ENOENT`. + + + + Tips: + + * The server provides access to Claude's tools like View, Edit, LS, etc. + * In Claude Desktop, try asking Claude to read files in a directory, make edits, and more. + * Note that this MCP server is only exposing Claude Code's tools to your MCP client, so your own client is responsible for implementing user confirmation for individual tool calls. + + +## MCP output limits and warnings + +When MCP tools produce large outputs, Claude Code helps manage the token usage to prevent overwhelming your conversation context: + +* **Output warning threshold**: Claude Code displays a warning when any MCP tool output exceeds 10,000 tokens +* **Configurable limit**: You can adjust the maximum allowed MCP output tokens using the `MAX_MCP_OUTPUT_TOKENS` environment variable +* **Default limit**: The default maximum is 25,000 tokens + +To increase the limit for tools that produce large outputs: + +```bash theme={null} +# Set a higher limit for MCP tool outputs +export MAX_MCP_OUTPUT_TOKENS=50000 +claude +``` + +This is particularly useful when working with MCP servers that: + +* Query large datasets or databases +* Generate detailed reports or documentation +* Process extensive log files or debugging information + + + If you frequently encounter output warnings with specific MCP servers, consider increasing the limit or configuring the server to paginate or filter its responses. + + +## Use MCP resources + +MCP servers can expose resources that you can reference using @ mentions, similar to how you reference files. + +### Reference MCP resources + + + + Type `@` in your prompt to see available resources from all connected MCP servers. Resources appear alongside files in the autocomplete menu. + + + + Use the format `@server:protocol://resource/path` to reference a resource: + + ``` + > Can you analyze @github:issue://123 and suggest a fix? + ``` + + ``` + > Please review the API documentation at @docs:file://api/authentication + ``` + + + + You can reference multiple resources in a single prompt: + + ``` + > Compare @postgres:schema://users with @docs:file://database/user-model + ``` + + + + + Tips: + + * Resources are automatically fetched and included as attachments when referenced + * Resource paths are fuzzy-searchable in the @ mention autocomplete + * Claude Code automatically provides tools to list and read MCP resources when servers support them + * Resources can contain any type of content that the MCP server provides (text, JSON, structured data, etc.) + + +## Scale with MCP Tool Search + +When you have many MCP servers configured, tool definitions can consume a significant portion of your context window. MCP Tool Search solves this by dynamically loading tools on-demand instead of preloading all of them. + +### How it works + +Claude Code automatically enables Tool Search when your MCP tool descriptions would consume more than 10% of the context window. You can [adjust this threshold](#configure-tool-search) or disable tool search entirely. When triggered: + +1. MCP tools are deferred rather than loaded into context upfront +2. Claude uses a search tool to discover relevant MCP tools when needed +3. Only the tools Claude actually needs are loaded into context +4. MCP tools continue to work exactly as before from your perspective + +### For MCP server authors + +If you're building an MCP server, the server instructions field becomes more useful with Tool Search enabled. Server instructions help Claude understand when to search for your tools, similar to how [skills](/en/skills) work. + +Add clear, descriptive server instructions that explain: + +* What category of tasks your tools handle +* When Claude should search for your tools +* Key capabilities your server provides + +### Configure tool search + +Tool search runs in auto mode by default, meaning it activates only when your MCP tool definitions exceed the context threshold. If you have few tools, they load normally without tool search. This feature requires models that support `tool_reference` blocks: Sonnet 4 and later, or Opus 4 and later. Haiku models do not support tool search. + +Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable: + +| Value | Behavior | +| :--------- | :--------------------------------------------------------------------------------- | +| `auto` | Activates when MCP tools exceed 10% of context (default) | +| `auto:` | Activates at custom threshold, where `` is a percentage (e.g., `auto:5` for 5%) | +| `true` | Always enabled | +| `false` | Disabled, all MCP tools loaded upfront | + +```bash theme={null} +# Use a custom 5% threshold +ENABLE_TOOL_SEARCH=auto:5 claude + +# Disable tool search entirely +ENABLE_TOOL_SEARCH=false claude +``` + +Or set the value in your [settings.json `env` field](/en/settings#available-settings). + +You can also disable the MCPSearch tool specifically using the `disallowedTools` setting: + +```json theme={null} +{ + "permissions": { + "deny": ["MCPSearch"] + } +} +``` + +## Use MCP prompts as commands + +MCP servers can expose prompts that become available as commands in Claude Code. + +### Execute MCP prompts + + + + Type `/` to see all available commands, including those from MCP servers. MCP prompts appear with the format `/mcp__servername__promptname`. + + + + ``` + > /mcp__github__list_prs + ``` + + + + Many prompts accept arguments. Pass them space-separated after the command: + + ``` + > /mcp__github__pr_review 456 + ``` + + ``` + > /mcp__jira__create_issue "Bug in login flow" high + ``` + + + + + Tips: + + * MCP prompts are dynamically discovered from connected servers + * Arguments are parsed based on the prompt's defined parameters + * Prompt results are injected directly into the conversation + * Server and prompt names are normalized (spaces become underscores) + + +## Managed MCP configuration + +For organizations that need centralized control over MCP servers, Claude Code supports two configuration options: + +1. **Exclusive control with `managed-mcp.json`**: Deploy a fixed set of MCP servers that users cannot modify or extend +2. **Policy-based control with allowlists/denylists**: Allow users to add their own servers, but restrict which ones are permitted + +These options allow IT administrators to: + +* **Control which MCP servers employees can access**: Deploy a standardized set of approved MCP servers across the organization +* **Prevent unauthorized MCP servers**: Restrict users from adding unapproved MCP servers +* **Disable MCP entirely**: Remove MCP functionality completely if needed + +### Option 1: Exclusive control with managed-mcp.json + +When you deploy a `managed-mcp.json` file, it takes **exclusive control** over all MCP servers. Users cannot add, modify, or use any MCP servers other than those defined in this file. This is the simplest approach for organizations that want complete control. + +System administrators deploy the configuration file to a system-wide directory: + +* macOS: `/Library/Application Support/ClaudeCode/managed-mcp.json` +* Linux and WSL: `/etc/claude-code/managed-mcp.json` +* Windows: `C:\Program Files\ClaudeCode\managed-mcp.json` + + + These are system-wide paths (not user home directories like `~/Library/...`) that require administrator privileges. They are designed to be deployed by IT administrators. + + +The `managed-mcp.json` file uses the same format as a standard `.mcp.json` file: + +```json theme={null} +{ + "mcpServers": { + "github": { + "type": "http", + "url": "https://api.githubcopilot.com/mcp/" + }, + "sentry": { + "type": "http", + "url": "https://mcp.sentry.dev/mcp" + }, + "company-internal": { + "type": "stdio", + "command": "/usr/local/bin/company-mcp-server", + "args": ["--config", "/etc/company/mcp-config.json"], + "env": { + "COMPANY_API_URL": "https://internal.company.com" + } + } + } +} +``` + +### Option 2: Policy-based control with allowlists and denylists + +Instead of taking exclusive control, administrators can allow users to configure their own MCP servers while enforcing restrictions on which servers are permitted. This approach uses `allowedMcpServers` and `deniedMcpServers` in the [managed settings file](/en/settings#settings-files). + + + **Choosing between options**: Use Option 1 (`managed-mcp.json`) when you want to deploy a fixed set of servers with no user customization. Use Option 2 (allowlists/denylists) when you want to allow users to add their own servers within policy constraints. + + +#### Restriction options + +Each entry in the allowlist or denylist can restrict servers in three ways: + +1. **By server name** (`serverName`): Matches the configured name of the server +2. **By command** (`serverCommand`): Matches the exact command and arguments used to start stdio servers +3. **By URL pattern** (`serverUrl`): Matches remote server URLs with wildcard support + +**Important**: Each entry must have exactly one of `serverName`, `serverCommand`, or `serverUrl`. + +#### Example configuration + +```json theme={null} +{ + "allowedMcpServers": [ + // Allow by server name + { "serverName": "github" }, + { "serverName": "sentry" }, + + // Allow by exact command (for stdio servers) + { "serverCommand": ["npx", "-y", "@modelcontextprotocol/server-filesystem"] }, + { "serverCommand": ["python", "/usr/local/bin/approved-server.py"] }, + + // Allow by URL pattern (for remote servers) + { "serverUrl": "https://mcp.company.com/*" }, + { "serverUrl": "https://*.internal.corp/*" } + ], + "deniedMcpServers": [ + // Block by server name + { "serverName": "dangerous-server" }, + + // Block by exact command (for stdio servers) + { "serverCommand": ["npx", "-y", "unapproved-package"] }, + + // Block by URL pattern (for remote servers) + { "serverUrl": "https://*.untrusted.com/*" } + ] +} +``` + +#### How command-based restrictions work + +**Exact matching**: + +* Command arrays must match **exactly** - both the command and all arguments in the correct order +* Example: `["npx", "-y", "server"]` will NOT match `["npx", "server"]` or `["npx", "-y", "server", "--flag"]` + +**Stdio server behavior**: + +* When the allowlist contains **any** `serverCommand` entries, stdio servers **must** match one of those commands +* Stdio servers cannot pass by name alone when command restrictions are present +* This ensures administrators can enforce which commands are allowed to run + +**Non-stdio server behavior**: + +* Remote servers (HTTP, SSE, WebSocket) use URL-based matching when `serverUrl` entries exist in the allowlist +* If no URL entries exist, remote servers fall back to name-based matching +* Command restrictions do not apply to remote servers + +#### How URL-based restrictions work + +URL patterns support wildcards using `*` to match any sequence of characters. This is useful for allowing entire domains or subdomains. + +**Wildcard examples**: + +* `https://mcp.company.com/*` - Allow all paths on a specific domain +* `https://*.example.com/*` - Allow any subdomain of example.com +* `http://localhost:*/*` - Allow any port on localhost + +**Remote server behavior**: + +* When the allowlist contains **any** `serverUrl` entries, remote servers **must** match one of those URL patterns +* Remote servers cannot pass by name alone when URL restrictions are present +* This ensures administrators can enforce which remote endpoints are allowed + + + ```json theme={null} + { + "allowedMcpServers": [ + { "serverUrl": "https://mcp.company.com/*" }, + { "serverUrl": "https://*.internal.corp/*" } + ] + } + ``` + + **Result**: + + * HTTP server at `https://mcp.company.com/api`: āœ… Allowed (matches URL pattern) + * HTTP server at `https://api.internal.corp/mcp`: āœ… Allowed (matches wildcard subdomain) + * HTTP server at `https://external.com/mcp`: āŒ Blocked (doesn't match any URL pattern) + * Stdio server with any command: āŒ Blocked (no name or command entries to match) + + + + ```json theme={null} + { + "allowedMcpServers": [ + { "serverCommand": ["npx", "-y", "approved-package"] } + ] + } + ``` + + **Result**: + + * Stdio server with `["npx", "-y", "approved-package"]`: āœ… Allowed (matches command) + * Stdio server with `["node", "server.js"]`: āŒ Blocked (doesn't match command) + * HTTP server named "my-api": āŒ Blocked (no name entries to match) + + + + ```json theme={null} + { + "allowedMcpServers": [ + { "serverName": "github" }, + { "serverCommand": ["npx", "-y", "approved-package"] } + ] + } + ``` + + **Result**: + + * Stdio server named "local-tool" with `["npx", "-y", "approved-package"]`: āœ… Allowed (matches command) + * Stdio server named "local-tool" with `["node", "server.js"]`: āŒ Blocked (command entries exist but doesn't match) + * Stdio server named "github" with `["node", "server.js"]`: āŒ Blocked (stdio servers must match commands when command entries exist) + * HTTP server named "github": āœ… Allowed (matches name) + * HTTP server named "other-api": āŒ Blocked (name doesn't match) + + + + ```json theme={null} + { + "allowedMcpServers": [ + { "serverName": "github" }, + { "serverName": "internal-tool" } + ] + } + ``` + + **Result**: + + * Stdio server named "github" with any command: āœ… Allowed (no command restrictions) + * Stdio server named "internal-tool" with any command: āœ… Allowed (no command restrictions) + * HTTP server named "github": āœ… Allowed (matches name) + * Any server named "other": āŒ Blocked (name doesn't match) + + +#### Allowlist behavior (`allowedMcpServers`) + +* `undefined` (default): No restrictions - users can configure any MCP server +* Empty array `[]`: Complete lockdown - users cannot configure any MCP servers +* List of entries: Users can only configure servers that match by name, command, or URL pattern + +#### Denylist behavior (`deniedMcpServers`) + +* `undefined` (default): No servers are blocked +* Empty array `[]`: No servers are blocked +* List of entries: Specified servers are explicitly blocked across all scopes + +#### Important notes + +* **Option 1 and Option 2 can be combined**: If `managed-mcp.json` exists, it has exclusive control and users cannot add servers. Allowlists/denylists still apply to the managed servers themselves. +* **Denylist takes absolute precedence**: If a server matches a denylist entry (by name, command, or URL), it will be blocked even if it's on the allowlist +* Name-based, command-based, and URL-based restrictions work together: a server passes if it matches **either** a name entry, a command entry, or a URL pattern (unless blocked by denylist) + + + **When using `managed-mcp.json`**: Users cannot add MCP servers through `claude mcp add` or configuration files. The `allowedMcpServers` and `deniedMcpServers` settings still apply to filter which managed servers are actually loaded. + From 99ccb6657bebb004df57f89966828364ffce6392 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:39:43 -0600 Subject: [PATCH 25/32] Update CODEOWNERS to assign new reviewers --- .github/CODEOWNERS | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 52eca53..472f6b6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,13 +1,13 @@ # CODEOWNERS - Automatically assigns reviewers based on file paths # Default owner for everything -* @groupthinking +* @codex # Frontend -*.tsx @groupthinking -*.jsx @groupthinking -*.css @groupthinking -/frontend/ @groupthinking +*.tsx @Vercel +*.jsx @Vercel +*.css @Vercel +/frontend/ @Vercel # Backend *.py @groupthinking @@ -16,11 +16,11 @@ /api/ @groupthinking # Infrastructure -/.github/ @groupthinking -*.yml @groupthinking -*.yaml @groupthinking -Dockerfile @groupthinking +/.github/ @Claude +*.yml @Claude +*.yaml @Claude +Dockerfile @Claude # Documentation -*.md @groupthinking -/docs/ @groupthinking +*.md @Copilot +/docs/ @Copilot From 8406f5db478ba243135973f743d2fcc10ac272d2 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:44:25 -0600 Subject: [PATCH 26/32] =?UTF-8?q?=F0=9F=A4=96=20Redeploy=20auto-label.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/auto-label.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/auto-label.yml b/.github/workflows/auto-label.yml index cab0666..8570cfe 100644 --- a/.github/workflows/auto-label.yml +++ b/.github/workflows/auto-label.yml @@ -12,19 +12,26 @@ jobs: const { data: files } = await github.rest.pulls.listFiles({ owner: context.repo.owner, repo: context.repo.repo, - pull_number: context.payload.pull_request.number, + pull_number: context.payload.pull_request.number }); + const labels = new Set(); + for (const file of files) { - if (file.filename.endsWith('.js') || file.filename.endsWith('.ts')) labels.add('logic'); - if (file.filename.includes('test')) labels.add('testing'); - if (file.filename.includes('.github/workflows')) labels.add('ci-cd'); + const path = file.filename; + if (path.includes('docs/') || path.endsWith('.md')) labels.add('documentation'); + if (path.includes('test/') || path.includes('.test.') || path.includes('.spec.')) labels.add('tests'); + if (path.includes('.github/workflows/')) labels.add('ci/cd'); + if (path.endsWith('.js') || path.endsWith('.ts') || path.endsWith('.jsx') || path.endsWith('.tsx')) labels.add('javascript'); + if (path.endsWith('.py')) labels.add('python'); + if (path.endsWith('.css') || path.endsWith('.scss') || path.endsWith('.sass')) labels.add('styling'); } + if (labels.size > 0) { await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, - labels: Array.from(labels), + labels: Array.from(labels) }); } From 9ae46e8036e452b2d6934e5067a557e04b901edb Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:44:26 -0600 Subject: [PATCH 27/32] =?UTF-8?q?=F0=9F=A4=96=20Redeploy=20pr-checks.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pr-checks.yml | 39 ++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 2464d70..03c5ca4 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -1,13 +1,40 @@ name: PR Checks on: pull_request: - branches: [main, master] + types: [opened, reopened, synchronize, edited] jobs: validate: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Basic Syntax Check - run: | - echo "Running syntax validation..." - find . -name "*.js" -o -name "*.py" -o -name "*.ts" | xargs -I {} node -c {} || true + - uses: actions/github-script@v7 + with: + script: | + const pr = context.payload.pull_request; + const issues = []; + + if (pr.title.length < 10) { + issues.push('āŒ PR title too short (minimum 10 characters)'); + } + if (!/^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?:/.test(pr.title)) { + issues.push('āš ļø PR title should follow conventional commits format'); + } + + if (!pr.body || pr.body.length < 20) { + issues.push('āŒ PR description is required (minimum 20 characters)'); + } + + const totalChanges = (pr.additions || 0) + (pr.deletions || 0); + if (totalChanges > 500) { + issues.push(`āš ļø Large PR detected (${totalChanges} lines changed)`); + } + + if (issues.length > 0) { + const comment = `## šŸ” PR Validation\n\n${issues.join('\n')}`; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + body: comment + }); + core.setFailed('PR validation failed'); + } From 5e10381ad42e19c25cb49235708839ca37c9efb5 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:44:27 -0600 Subject: [PATCH 28/32] =?UTF-8?q?=F0=9F=A4=96=20Redeploy=20issue-triage.ym?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-triage.yml | 31 ++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml index 9379a8d..c8649bf 100644 --- a/.github/workflows/issue-triage.yml +++ b/.github/workflows/issue-triage.yml @@ -9,15 +9,30 @@ jobs: - uses: actions/github-script@v7 with: script: | - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.issue.number, - labels: ['triage-needed'] - }); + const issue = context.payload.issue; + const labels = []; + const text = `${issue.title} ${issue.body}`.toLowerCase(); + + if (text.includes('bug') || text.includes('error')) labels.push('bug'); + if (text.includes('feature') || text.includes('enhancement')) labels.push('enhancement'); + if (text.includes('docs') || text.includes('documentation')) labels.push('documentation'); + if (text.includes('question') || text.includes('help')) labels.push('question'); + if (text.includes('urgent') || text.includes('critical')) labels.push('priority:high'); + + labels.push('needs-triage'); + + if (labels.length > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: labels + }); + } + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, - issue_number: context.payload.issue.number, - body: "Thanks for opening this issue! A maintainer will look at it shortly." + issue_number: issue.number, + body: 'šŸ‘‹ Thanks for opening this issue! It has been automatically labeled for triage.' }); From 96e639a32c280f16e69f6c641284cbb621d19338 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 09:03:39 -0600 Subject: [PATCH 29/32] Update pr-checks.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/pr-checks.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 03c5ca4..00f340a 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -10,31 +10,35 @@ jobs: with: script: | const pr = context.payload.pull_request; - const issues = []; + const errors = []; + const warnings = []; if (pr.title.length < 10) { - issues.push('āŒ PR title too short (minimum 10 characters)'); + errors.push('āŒ PR title too short (minimum 10 characters)'); } if (!/^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?:/.test(pr.title)) { - issues.push('āš ļø PR title should follow conventional commits format'); + warnings.push('āš ļø PR title should follow conventional commits format'); } if (!pr.body || pr.body.length < 20) { - issues.push('āŒ PR description is required (minimum 20 characters)'); + errors.push('āŒ PR description is required (minimum 20 characters)'); } const totalChanges = (pr.additions || 0) + (pr.deletions || 0); if (totalChanges > 500) { - issues.push(`āš ļø Large PR detected (${totalChanges} lines changed)`); + warnings.push(`āš ļø Large PR detected (${totalChanges} lines changed)`); } - if (issues.length > 0) { - const comment = `## šŸ” PR Validation\n\n${issues.join('\n')}`; + const allMessages = [...errors, ...warnings]; + if (allMessages.length > 0) { + const comment = `## šŸ” PR Validation\n\n${allMessages.join('\n')}`; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number, body: comment }); - core.setFailed('PR validation failed'); + if (errors.length > 0) { + core.setFailed('PR validation failed'); + } } From 7390b497e5e51b2361c33d7963fc5c2623e8ca52 Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Fri, 6 Feb 2026 09:04:09 -0600 Subject: [PATCH 30/32] Update auto-label.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/auto-label.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-label.yml b/.github/workflows/auto-label.yml index 8570cfe..f0934ef 100644 --- a/.github/workflows/auto-label.yml +++ b/.github/workflows/auto-label.yml @@ -27,11 +27,21 @@ jobs: if (path.endsWith('.css') || path.endsWith('.scss') || path.endsWith('.sass')) labels.add('styling'); } - if (labels.size > 0) { + // Fetch existing labels in the repository to avoid "Label does not exist" errors + const { data: repoLabels } = await github.rest.issues.listLabelsForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 100, + }); + + const existingLabelNames = new Set(repoLabels.map(label => label.name)); + const labelsToAdd = Array.from(labels).filter(label => existingLabelNames.has(label)); + + if (labelsToAdd.length > 0) { await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, - labels: Array.from(labels) + labels: labelsToAdd, }); } From c9306a645358838d81f7ebbf43cbbe28c7bec5f9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:17:43 +0000 Subject: [PATCH 31/32] Initial plan From 10ec2a18a3b01ac3a399b17df0ad036d4c1a765d Mon Sep 17 00:00:00 2001 From: Hayden <154503486+groupthinking@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:38:02 -0600 Subject: [PATCH 32/32] Initial MyXstack backend scaffold --- .gitignore | 9 +- README.md | 148 +- a2a_store.py | 123 + env.example | 37 + listener.py | 226 +- mcp_dispatcher.py | 151 + openapi.json | 23095 +++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 8 + server.py | 273 + timeline_server.py | 150 + timeline_store.py | 107 + 11 files changed, 24117 insertions(+), 210 deletions(-) create mode 100644 a2a_store.py create mode 100644 env.example create mode 100644 mcp_dispatcher.py create mode 100644 openapi.json create mode 100644 requirements.txt create mode 100644 server.py create mode 100644 timeline_server.py create mode 100644 timeline_store.py diff --git a/.gitignore b/.gitignore index 1fdca42..b22e079 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,15 @@ node_modules/ dist/ +__pycache__/ +*.pyc +*.pyo +*.pyd +.venv/ +venv/ .env +.env.local .DS_Store *.log .vscode/ .idea/ -__pycache__/ +.xmcp/ diff --git a/README.md b/README.md index 0dd0e21..13e4249 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,49 @@ # MyXstack -This repository hosts a lightweight, step-by-step guide for setting up an autonomous X (Twitter) agent system that acts based on thread context & reasoning, through Grok via the xMCP server. +This repository hosts a lightweight, step-by-step guide and runnable backend for an autonomous X (Twitter) agent system that reasons over thread context via Grok through xMCP. -## Phase 1: Gather prerequisites & accounts (1–2 hours) +## Services +- **mcp-server**: X API MCP server (`server.py`) +- **timeline-server**: Timeline + A2A API (`timeline_server.py`) +- **x-listener**: Watches mentions, responds, and pushes timeline cards (`listener.py`) +- **mcp-dispatcher**: Executes timeline actions via MCP (`mcp_dispatcher.py`) -### X developer account & app -1. Go to and sign in with the account you want the bot to run on. -2. Create a new app/project (free tier is fine to start). -3. Set app permissions to **Read + Write + Direct Messages** so the agent can post replies. -4. Generate and record the OAuth 1.0a credentials: - - API Key - - API Secret - - Access Token (user context) - - Access Token Secret - -### Dedicated bot account (recommended) -1. Create a new X account for the bot (for example, `@MyXMCPBot`). -2. Link the bot account to your developer app via the OAuth flow. -3. Note the bot user ID (you can fetch this via the API later). - -### xAI / Grok API key -1. Visit , open the API keys section, and create a key that starts with `xai-`. -2. Store the key securely. - -### Local tooling -- Install Python 3.9+ (3.10–3.13 recommended). -- Ensure `git` is installed for cloning. - -## Phase 2: Clone & set up the xMCP server (local first) - -1. Clone your fork of the xMCP server: - ```bash - git clone https://github.com/groupthinking/xMCP.git - cd xMCP - ``` -2. Create and activate a virtual environment: - ```bash - python -m venv .venv - source .venv/bin/activate - ``` -3. Install dependencies: - ```bash - pip install -r requirements.txt - ``` -4. Create your `.env`: - ```bash - cp env.example .env - ``` -5. Fill in the `.env` values you need: - ```text - # OAuth user token for posting replies - X_OAUTH_ACCESS_TOKEN=your_access_token_here - X_OAUTH_ACCESS_TOKEN_SECRET=your_access_token_secret_here - - # Optional read-only bearer token - # X_BEARER_TOKEN=your_bearer_token_here - - # Grok / xAI - XAI_API_KEY=your_xai_key_here - XAI_MODEL=grok-4-1-fast - - # Optional tuning - MCP_HOST=127.0.0.1 - MCP_PORT=8000 - X_API_DEBUG=1 - ``` -6. If you need to generate OAuth user tokens, add `CLIENT_ID` and `CLIENT_SECRET` to `.env`, update the redirect URI in `generate_authtoken.py`, and run: - ```bash - python generate_authtoken.py - ``` - -## Phase 3: Test the core xMCP server + Grok connection - -1. Start the MCP server: - ```bash - python server.py - ``` - You should see `Server running on http://127.0.0.1:8000`. -2. In another terminal, test Grok integration: - ```bash - python test_grok_mcp.py - ``` -3. Try prompts like: - - `Search recent posts about MCP` - - `Get my user info` - - `Post a test reply saying 'Hello from MCP' to tweet ID 1234567890` - -If these work, the core pipe (Grok → xMCP → X API) is live. - -## Phase 4: Add the trigger layer (tag/mention → action) - -A simple polling listener is provided in `listener.py` at the repo root. It uses Tweepy to poll for mentions and posts a placeholder reply. The listener requires OAuth user credentials (plus a bearer token for reads). Install Tweepy, export your environment variables, and run it while the xMCP server is up: +## Local Setup +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +cp env.example .env +``` +Run services in separate terminals: ```bash -pip install tweepy -export X_API_KEY=your_api_key -export X_API_SECRET=your_api_secret -export X_OAUTH_ACCESS_TOKEN=your_access_token -export X_OAUTH_ACCESS_TOKEN_SECRET=your_access_token_secret -export X_BEARER_TOKEN=your_bearer_token -export POLL_INTERVAL_SECONDS=60 +python server.py +python timeline_server.py python listener.py +python mcp_dispatcher.py ``` -Then tag your bot from another account to see it respond. Replace the placeholder Grok call with your real xMCP/Grok invocation when ready. - -## Phase 5: Iterate toward full autonomy - -- Wire the listener to call Grok through the xMCP server. -- Add Docker/Docker Compose if you want a containerized workflow. -- Persist state (SQLite) to avoid reprocessing old mentions. -- Extend with proxies, CrewAI/AutoGen, or other agent frameworks. -- Deploy to Railway/Render/VPS for 24/7 operation. - -## Current status -Start with Phases 1–4 today. If you hit a snag, share the exact output/error and we can debug together. +## Railway Deployment (Monorepo) +Create four Railway services from this repo and set start commands: +- `python server.py` +- `python timeline_server.py` +- `python listener.py` +- `python mcp_dispatcher.py` + +Set service env vars from `env.example`, then wire cross-service URLs: +- `MCP_SERVER_URL=https:///mcp` +- `TIMELINE_API_URL=https://` + +## API Surface +Timeline: +- `GET /v1/timeline/users/{user_id}/items` +- `POST /v1/timeline/items` +- `PATCH /v1/timeline/items/{id}` +- `DELETE /v1/timeline/items/{id}` + +A2A: +- `GET /v1/a2a/agents` +- `POST /v1/a2a/agents` +- `GET /v1/a2a/agents/{id}/messages` +- `POST /v1/a2a/messages` diff --git a/a2a_store.py b/a2a_store.py new file mode 100644 index 0000000..8c9ac77 --- /dev/null +++ b/a2a_store.py @@ -0,0 +1,123 @@ +import json +import os +import threading +import uuid +from datetime import datetime, timezone +from pathlib import Path +from typing import Any, Dict, List, Optional + +A2A_STORE_PATH = Path(os.getenv("A2A_STORE_PATH", "~/.xmcp/a2a_store.json")).expanduser() +A2A_STORE_LOCK = threading.Lock() + +DEFAULT_AGENTS = [ + { + "id": "mcp-orchestrator", + "name": "MCP Orchestrator", + "description": "Dispatches timeline actions to MCP-enabled tools.", + "status": "online", + "endpoint": "local", + "tags": ["mcp", "orchestrator"], + }, + { + "id": "x-agent", + "name": "X Agent", + "description": "Handles @mentions and X actions.", + "status": "online", + "endpoint": "x", + "tags": ["x", "social"], + }, + { + "id": "timeline-ui", + "name": "Timeline UI", + "description": "Flokk timeline surface.", + "status": "online", + "endpoint": "flokk", + "tags": ["ui", "timeline"], + }, +] + + +def _utc_now() -> str: + return datetime.now(timezone.utc).isoformat() + + +def _ensure_store() -> None: + if A2A_STORE_PATH.exists(): + return + A2A_STORE_PATH.parent.mkdir(parents=True, exist_ok=True) + data = {"agents": DEFAULT_AGENTS, "messages": []} + A2A_STORE_PATH.write_text(json.dumps(data, indent=2), encoding="utf-8") + + +def _read_store() -> Dict[str, Any]: + _ensure_store() + raw = A2A_STORE_PATH.read_text(encoding="utf-8") + try: + data = json.loads(raw) + except json.JSONDecodeError: + data = {"agents": DEFAULT_AGENTS, "messages": []} + if "agents" not in data or not isinstance(data["agents"], list): + data["agents"] = DEFAULT_AGENTS + if "messages" not in data or not isinstance(data["messages"], list): + data["messages"] = [] + return data + + +def _write_store(data: Dict[str, Any]) -> None: + A2A_STORE_PATH.parent.mkdir(parents=True, exist_ok=True) + A2A_STORE_PATH.write_text(json.dumps(data, indent=2), encoding="utf-8") + + +def list_agents() -> List[Dict[str, Any]]: + with A2A_STORE_LOCK: + return _read_store()["agents"] + + +def get_agent(agent_id: str) -> Optional[Dict[str, Any]]: + with A2A_STORE_LOCK: + for agent in _read_store()["agents"]: + if agent.get("id") == agent_id: + return agent + return None + + +def register_agent(payload: Dict[str, Any]) -> Dict[str, Any]: + agent = { + "id": payload.get("id") or str(uuid.uuid4()), + "name": payload.get("name", "Agent"), + "description": payload.get("description", ""), + "status": payload.get("status", "offline"), + "endpoint": payload.get("endpoint", ""), + "tags": payload.get("tags", []), + "created_at": _utc_now(), + } + with A2A_STORE_LOCK: + data = _read_store() + if any(existing.get("id") == agent["id"] for existing in data["agents"]): + return agent + data["agents"].append(agent) + _write_store(data) + return agent + + +def list_messages(agent_id: str) -> List[Dict[str, Any]]: + with A2A_STORE_LOCK: + data = _read_store() + return [msg for msg in data["messages"] if msg.get("to") == agent_id] + + +def add_message(payload: Dict[str, Any]) -> Dict[str, Any]: + message = { + "id": payload.get("id") or str(uuid.uuid4()), + "from": payload.get("from", "system"), + "to": payload.get("to", "timeline-ui"), + "type": payload.get("type", "info"), + "content": payload.get("content", ""), + "metadata": payload.get("metadata", {}), + "created_at": _utc_now(), + } + with A2A_STORE_LOCK: + data = _read_store() + data["messages"].insert(0, message) + _write_store(data) + return message diff --git a/env.example b/env.example new file mode 100644 index 0000000..7f974d2 --- /dev/null +++ b/env.example @@ -0,0 +1,37 @@ +# X API credentials (required for MCP X API tools) +X_BEARER_TOKEN= +X_API_KEY= +X_API_SECRET= +X_ACCESS_TOKEN= +X_ACCESS_SECRET= +# Optional: if using OAuth bearer for X API +X_OAUTH_ACCESS_TOKEN= +X_API_BASE_URL=https://api.x.com + +# Grok / xAI +XAI_API_KEY= +XAI_MODEL=grok-4-1-fast + +# MCP server +MCP_HOST=0.0.0.0 +MCP_PORT=8000 +MCP_SERVER_URL=http://127.0.0.1:8000/mcp + +# Timeline / A2A +TIMELINE_HOST=0.0.0.0 +TIMELINE_PORT=8080 +TIMELINE_API_URL=http://127.0.0.1:8080 +TIMELINE_USER_ID=default +TIMELINE_STORE_PATH=~/.xmcp/timeline_store.json +A2A_STORE_PATH=~/.xmcp/a2a_store.json +TIMELINE_ACTION_AGENT=mcp-orchestrator +MCP_DISPATCH_AGENT_ID=mcp-orchestrator +XMCP_LAST_SEEN_PATH=~/.xmcp/last_seen.txt +XMCP_DISPATCH_LAST_SEEN=~/.xmcp/dispatch_last_seen.txt + +# FastMCP OpenAPI filtering +X_API_TOOL_TAGS= +X_API_TOOL_ALLOWLIST= +X_API_TOOL_DENYLIST= +X_API_TIMEOUT=30 +X_API_DEBUG=1 diff --git a/listener.py b/listener.py index f0cd1f3..b8d4245 100644 --- a/listener.py +++ b/listener.py @@ -1,128 +1,152 @@ import os import time from datetime import datetime, timedelta, timezone +from pathlib import Path +from typing import Optional +import requests import tweepy -from tweepy.errors import TweepyException +from dotenv import load_dotenv +from xai_sdk import Client +from xai_sdk.chat import user +from xai_sdk.tools import mcp +LAST_SEEN_PATH = Path(os.getenv("XMCP_LAST_SEEN_PATH", "~/.xmcp/last_seen.txt")).expanduser() -def require_env(name: str) -> str: - value = os.getenv(name) - if not value: - raise RuntimeError(f"Missing required environment variable: {name}") - return value +def load_env() -> None: + env_path = Path(__file__).resolve().parent / ".env" + if env_path.exists(): + load_dotenv(env_path) -def parse_poll_interval() -> int: - value = os.getenv("POLL_INTERVAL_SECONDS", "60") - try: - interval = int(value) - except ValueError: - print(f"Invalid POLL_INTERVAL_SECONDS '{value}', defaulting to 60.") - return 60 - if interval <= 0: - print("POLL_INTERVAL_SECONDS must be positive; defaulting to 60.") - return 60 - return interval + +def save_last_seen(value: str) -> None: + LAST_SEEN_PATH.parent.mkdir(parents=True, exist_ok=True) + LAST_SEEN_PATH.write_text(value, encoding="utf-8") + + +def load_last_seen() -> Optional[str]: + if not LAST_SEEN_PATH.exists(): + return None + return LAST_SEEN_PATH.read_text(encoding="utf-8").strip() or None def build_client() -> tweepy.Client: + access_token = os.getenv("X_ACCESS_TOKEN") or os.getenv("X_OAUTH_ACCESS_TOKEN") + access_secret = os.getenv("X_ACCESS_SECRET") or os.getenv("X_OAUTH_ACCESS_TOKEN_SECRET") return tweepy.Client( - bearer_token=require_env("X_BEARER_TOKEN"), - consumer_key=require_env("X_API_KEY"), - consumer_secret=require_env("X_API_SECRET"), - access_token=require_env("X_OAUTH_ACCESS_TOKEN"), - access_token_secret=require_env("X_OAUTH_ACCESS_TOKEN_SECRET"), + bearer_token=os.getenv("X_BEARER_TOKEN"), + consumer_key=os.getenv("X_API_KEY"), + consumer_secret=os.getenv("X_API_SECRET"), + access_token=access_token, + access_token_secret=access_secret, + wait_on_rate_limit=True, ) -def fetch_thread_context(client: tweepy.Client, conversation_id: str) -> str | None: - try: - thread = client.search_recent_tweets( - query=f"conversation_id:{conversation_id}", - tweet_fields=["text", "author_id"], - ) - except TweepyException as exc: - print(f"Failed to fetch thread context for {conversation_id}: {exc}") - return None - tweets = thread.data or [] - return "\n".join(tweet.text for tweet in tweets) +def get_grok_reply(prompt: str) -> str: + api_key = os.getenv("XAI_API_KEY", "").strip() + if not api_key: + return "Missing XAI_API_KEY." + model = os.getenv("XAI_MODEL", "grok-4-1-fast") + server_url = os.getenv("MCP_SERVER_URL", "http://127.0.0.1:8000/mcp") + + client = Client(api_key=api_key) + chat = client.chat.create( + model=model, + tools=[mcp(server_url=server_url)], + ) + chat.append(user(prompt)) + + response_text = "" + for _, chunk in chat.stream(): + if chunk.content: + response_text += chunk.content + return response_text.strip() or "Thinking..." + + +def push_timeline_card(title: str, body: str, metadata: dict) -> None: + timeline_url = os.getenv("TIMELINE_API_URL", "http://127.0.0.1:8080") + user_id = os.getenv("TIMELINE_USER_ID", "default") + payload = { + "user_id": user_id, + "title": title, + "body": body, + "posted_by": "x-agent", + "actions": ["Approve", "Reject", "Snooze"], + "metadata": metadata, + } + requests.post(f"{timeline_url}/v1/timeline/items", json=payload, timeout=10) + + +def ensure_agent_registered() -> None: + timeline_url = os.getenv("TIMELINE_API_URL", "http://127.0.0.1:8080") + payload = { + "id": "x-agent", + "name": "X Agent", + "description": "Handles @mentions and X actions.", + "status": "online", + "endpoint": "x", + "tags": ["x", "social"], + } + requests.post(f"{timeline_url}/v1/a2a/agents", json=payload, timeout=10) def main() -> None: - try: - client = build_client() - bot = client.get_me().data - except (RuntimeError, TweepyException) as exc: - print(f"Unable to initialize client: {exc}") - return - - if not bot: - print("Unable to fetch bot user info.") - return - - bot_id = bot.id - poll_interval = parse_poll_interval() - last_seen_id = None - last_checked = datetime.now(timezone.utc) - timedelta(minutes=10) + load_env() + client = build_client() + me = client.get_me().data + if not me: + raise RuntimeError("Could not resolve authenticated X user for listener") + bot_id = me.id + ensure_agent_registered() + + last_seen = load_last_seen() + start_time = datetime.now(timezone.utc) - timedelta(minutes=10) + if last_seen: + try: + start_time = datetime.fromisoformat(last_seen) + except ValueError: + pass while True: - try: - mentions_response = client.get_users_mentions( - id=bot_id, - since_id=last_seen_id, - tweet_fields=["created_at", "conversation_id"], + mentions = client.get_users_mentions( + id=bot_id, + start_time=start_time, + tweet_fields=["conversation_id", "created_at", "author_id", "text"], + ) + for mention in mentions.data or []: + context = mention.text + prompt = f""" +You are an autonomous X agent bot. You were mentioned in this thread: + +{context} + +Analyze the request/intent. Use available tools to respond helpfully. +Always reply directly to the mentioning post. Be concise and actionable. +""" + grok_reply = get_grok_reply(prompt) + + client.create_tweet( + text=grok_reply[:280], + in_reply_to_tweet_id=mention.id, ) - except TweepyException as exc: - print(f"Failed to fetch mentions: {exc}") - time.sleep(poll_interval) - continue - - mentions = mentions_response.data or [] - processed_ids: list[int] = [] - had_failure = False - - for mention in reversed(mentions): - if mention.created_at and mention.created_at < last_checked: - processed_ids.append(int(mention.id)) - continue - if not mention.conversation_id: - processed_ids.append(int(mention.id)) - continue - - context = fetch_thread_context(client, str(mention.conversation_id)) - if context is None: - print(f"Skipping mention {mention.id} due to thread fetch failure.") - had_failure = True - break - - prompt = ( - "You were tagged here:\n" - f"{context}\n\n" - "Reason through this step-by-step and use X tools via xMCP to respond autonomously.\n" - "Server: http://127.0.0.1:8000/mcp" + + push_timeline_card( + title=f"New mention {mention.id}", + body=context, + metadata={ + "mention_id": mention.id, + "author_id": mention.author_id, + "conversation_id": mention.conversation_id, + "reply_preview": grok_reply[:280], + }, ) - # TODO: Replace with Grok invocation via xMCP. - _ = prompt - - try: - client.create_tweet( - text="Processing your tag... (full response coming soon)", - in_reply_to_tweet_id=mention.id, - ) - except TweepyException as exc: - print(f"Failed to reply to mention {mention.id}: {exc}") - had_failure = True - break - - processed_ids.append(int(mention.id)) - - if processed_ids: - last_seen_id = max(processed_ids) - if not had_failure: - last_checked = datetime.now(timezone.utc) - time.sleep(poll_interval) + start_time = mention.created_at or datetime.now(timezone.utc) + save_last_seen(start_time.isoformat()) + + time.sleep(60) if __name__ == "__main__": diff --git a/mcp_dispatcher.py b/mcp_dispatcher.py new file mode 100644 index 0000000..f2b6300 --- /dev/null +++ b/mcp_dispatcher.py @@ -0,0 +1,151 @@ +import os +import time +from datetime import datetime, timezone +from pathlib import Path +from typing import Dict, Optional + +import requests +from dotenv import load_dotenv +from xai_sdk import Client +from xai_sdk.chat import user +from xai_sdk.tools import mcp + +LAST_SEEN_PATH = Path(os.getenv("XMCP_DISPATCH_LAST_SEEN", "~/.xmcp/dispatch_last_seen.txt")).expanduser() + + +def load_env() -> None: + env_path = Path(__file__).resolve().parent / ".env" + if env_path.exists(): + load_dotenv(env_path) + + +def save_last_seen(value: str) -> None: + LAST_SEEN_PATH.parent.mkdir(parents=True, exist_ok=True) + LAST_SEEN_PATH.write_text(value, encoding="utf-8") + + +def load_last_seen() -> Optional[str]: + if not LAST_SEEN_PATH.exists(): + return None + return LAST_SEEN_PATH.read_text(encoding="utf-8").strip() or None + + +def get_messages(agent_id: str) -> list[Dict]: + timeline_url = os.getenv("TIMELINE_API_URL", "http://127.0.0.1:8080") + response = requests.get(f"{timeline_url}/v1/a2a/agents/{agent_id}/messages", timeout=10) + if response.status_code != 200: + return [] + payload = response.json() + return payload.get("messages", []) + + +def send_message(from_agent: str, to: str, content: str, metadata: Dict) -> None: + timeline_url = os.getenv("TIMELINE_API_URL", "http://127.0.0.1:8080") + requests.post( + f"{timeline_url}/v1/a2a/messages", + json={ + "from": from_agent, + "to": to, + "type": "mcp_result", + "content": content, + "metadata": metadata, + }, + timeout=10, + ) + + +def ensure_agent_registered(agent_id: str) -> None: + timeline_url = os.getenv("TIMELINE_API_URL", "http://127.0.0.1:8080") + payload = { + "id": agent_id, + "name": "MCP Orchestrator", + "description": "Dispatches timeline actions to MCP-enabled tools.", + "status": "online", + "endpoint": "local", + "tags": ["mcp", "orchestrator"], + } + requests.post(f"{timeline_url}/v1/a2a/agents", json=payload, timeout=10) + + +def update_timeline_item(item_id: str, metadata: Dict) -> None: + timeline_url = os.getenv("TIMELINE_API_URL", "http://127.0.0.1:8080") + requests.patch( + f"{timeline_url}/v1/timeline/items/{item_id}", + json={"metadata": metadata}, + timeout=10, + ) + + +def call_grok(prompt: str) -> str: + api_key = os.getenv("XAI_API_KEY", "").strip() + if not api_key: + return "Missing XAI_API_KEY." + model = os.getenv("XAI_MODEL", "grok-4-1-fast") + server_url = os.getenv("MCP_SERVER_URL", "http://127.0.0.1:8000/mcp") + + client = Client(api_key=api_key) + chat = client.chat.create( + model=model, + tools=[mcp(server_url=server_url)], + ) + chat.append(user(prompt)) + + response_text = "" + for _, chunk in chat.stream(): + if chunk.content: + response_text += chunk.content + return response_text.strip() or "No response." + + +def _parse_time(value: Optional[str]) -> Optional[datetime]: + if not value: + return None + try: + return datetime.fromisoformat(value) + except ValueError: + return None + + +def main() -> None: + load_env() + agent_id = os.getenv("MCP_DISPATCH_AGENT_ID", "mcp-orchestrator") + last_seen = _parse_time(load_last_seen()) + ensure_agent_registered(agent_id) + + while True: + messages = get_messages(agent_id) + for message in messages: + created_at = _parse_time(message.get("created_at")) + if last_seen and created_at and created_at <= last_seen: + continue + if message.get("type") != "timeline_action": + continue + + metadata = message.get("metadata", {}) + item_id = metadata.get("timeline_item_id") + action = metadata.get("action") + + prompt = f""" +You are a workflow agent. A user took the action '{action}' on timeline item {item_id}. +Use MCP tools to execute any required external steps. Return a concise status update. +""" + result = call_grok(prompt) + + if item_id: + update_timeline_item(item_id, {"mcp_result": result}) + + send_message( + from_agent=agent_id, + to=message.get("from", "timeline-ui"), + content=result, + metadata={"timeline_item_id": item_id, "action": action}, + ) + + last_seen = created_at or datetime.now(timezone.utc) + save_last_seen(last_seen.isoformat()) + + time.sleep(5) + + +if __name__ == "__main__": + main() diff --git a/openapi.json b/openapi.json new file mode 100644 index 0000000..e189271 --- /dev/null +++ b/openapi.json @@ -0,0 +1,23095 @@ +{ + "openapi" : "3.0.0", + "info" : { + "description" : "X API v2 available endpoints", + "version" : "2.157", + "title" : "X API v2", + "termsOfService" : "https://developer.x.com/en/developer-terms/agreement-and-policy.html", + "contact" : { + "name" : "X Developers", + "url" : "https://developer.x.com/" + }, + "license" : { + "name" : "X Developer Agreement and Policy", + "url" : "https://developer.x.com/en/developer-terms/agreement-and-policy.html" + } + }, + "paths" : { + "/2/account_activity/replay/webhooks/{webhook_id}/subscriptions/all" : { + "post" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Account Activity" + ], + "summary" : "Create replay job", + "description" : "Creates a replay job to retrieve activities from up to the past 5 days for all subscriptions associated with a given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/account-activity/introduction" + }, + "operationId" : "createAccountActivityReplayJob", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The unique identifier for the webhook configuration.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + }, + { + "name" : "from_date", + "in" : "query", + "description" : "The oldest (starting) UTC timestamp (inclusive) from which events will be provided, in `yyyymmddhhmm` format.", + "required" : true, + "schema" : { + "type" : "string", + "pattern" : "^\\d{12}$", + "example" : "202504242000" + }, + "style" : "form" + }, + { + "name" : "to_date", + "in" : "query", + "description" : "The latest (ending) UTC timestamp (exclusive) up to which events will be provided, in `yyyymmddhhmm` format.", + "required" : true, + "schema" : { + "type" : "string", + "pattern" : "^\\d{12}$", + "example" : "202504242200" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReplayJobCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/account_activity/subscriptions/count" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Account Activity" + ], + "summary" : "Get subscription count", + "description" : "Retrieves a count of currently active Account Activity subscriptions.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/account-activity/introduction" + }, + "operationId" : "getAccountActivitySubscriptionCount", + "parameters" : [ ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubscriptionsCountGetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/account_activity/webhooks/{webhook_id}/subscriptions/all" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Account Activity" + ], + "summary" : "Validate subscription", + "description" : "Checks a user’s Account Activity subscription for a given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/account-activity/introduction" + }, + "operationId" : "validateAccountActivitySubscription", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The webhook ID to check subscription against.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubscriptionsGetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Account Activity" + ], + "summary" : "Create subscription", + "description" : "Creates an Account Activity subscription for the user and the given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/account-activity/introduction" + }, + "operationId" : "createAccountActivitySubscription", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The webhook ID to check subscription against.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubscriptionsCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubscriptionsCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/account_activity/webhooks/{webhook_id}/subscriptions/all/list" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Account Activity" + ], + "summary" : "Get subscriptions", + "description" : "Retrieves a list of all active subscriptions for a given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/account-activity/introduction" + }, + "operationId" : "getAccountActivitySubscriptions", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The webhook ID to pull subscriptions for.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubscriptionsListGetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/account_activity/webhooks/{webhook_id}/subscriptions/{user_id}/all" : { + "delete" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Account Activity" + ], + "summary" : "Delete subscription", + "description" : "Deletes an Account Activity subscription for the given webhook and user ID.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/account-activity/introduction" + }, + "operationId" : "deleteAccountActivitySubscription", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The webhook ID to check subscription against.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + }, + { + "name" : "user_id", + "in" : "path", + "description" : "User ID to unsubscribe from.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubscriptionsDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/activity/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Activity", + "Stream" + ], + "summary" : "Activity Stream", + "description" : "Stream of X Activities", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/activity/activity-stream" + }, + "operationId" : "activityStream", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Post labels will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp from which the Post labels will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivityStreamingResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/activity/subscriptions" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Activity" + ], + "summary" : "Get X activity subscriptions", + "description" : "Get a list of active subscriptions for XAA", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/activity/get-x-activity-subscriptions" + }, + "operationId" : "getActivitySubscriptions", + "parameters" : [ ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionGetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Activity", + "Stream" + ], + "summary" : "Create X activity subscription", + "description" : "Creates a subscription for an X activity event", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/activity/create-x-activity-subscription" + }, + "operationId" : "createActivitySubscription", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/activity/subscriptions/{subscription_id}" : { + "delete" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Activity" + ], + "summary" : "Deletes X activity subscription", + "description" : "Deletes a subscription for an X activity event", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/activity/deletes-x-activity-subscription" + }, + "operationId" : "deleteActivitySubscription", + "parameters" : [ + { + "name" : "subscription_id", + "in" : "path", + "description" : "The ID of the subscription to delete.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "put" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Activity" + ], + "summary" : "Update X activity subscription", + "description" : "Updates a subscription for an X activity event", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/activity/update-x-activity-subscription" + }, + "operationId" : "updateActivitySubscription", + "parameters" : [ + { + "name" : "subscription_id", + "in" : "path", + "description" : "The ID of the subscription to update.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionUpdateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ActivitySubscriptionUpdateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/communities/search" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Communities" + ], + "summary" : "Search Communities", + "description" : "Retrieves a list of Communities matching the specified search query.", + "externalDocs" : { + "url" : "https://developer.x.com" + }, + "operationId" : "searchCommunities", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "Query to search communities.", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 4096, + "example" : "Love" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of search results to be returned by a request.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 10, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "next_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/NextToken" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/NextToken" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/CommunityFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2CommunitiesSearchResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/communities/{id}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Communities" + ], + "summary" : "Get Community by ID", + "description" : "Retrieves details of a specific Community by its ID.", + "externalDocs" : { + "url" : "https://developer.x.com/en/docs/x-api/communities/api-reference/get-communities-id" + }, + "operationId" : "getCommunitiesById", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the Community.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/CommunityId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/CommunityFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2CommunitiesIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/compliance/jobs" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Compliance" + ], + "summary" : "Get Compliance Jobs", + "description" : "Retrieves a list of Compliance Jobs filtered by job type and optional status.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs" + }, + "operationId" : "getComplianceJobs", + "parameters" : [ + { + "name" : "type", + "in" : "query", + "description" : "Type of Compliance Job to list.", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ + "tweets", + "users" + ] + }, + "style" : "form" + }, + { + "name" : "status", + "in" : "query", + "description" : "Status of Compliance Job to list.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "created", + "in_progress", + "failed", + "complete" + ] + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/ComplianceJobFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ComplianceJobsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Compliance" + ], + "summary" : "Create Compliance Job", + "description" : "Creates a new Compliance Job for the specified job type.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/post-compliance-jobs" + }, + "operationId" : "createComplianceJobs", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateComplianceJobRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateComplianceJobResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/compliance/jobs/{id}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Compliance" + ], + "summary" : "Get Compliance Job by ID", + "description" : "Retrieves details of a specific Compliance Job by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/compliance/batch-compliance/api-reference/get-compliance-jobs-id" + }, + "operationId" : "getComplianceJobsById", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the Compliance Job to retrieve.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/JobId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/ComplianceJobFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ComplianceJobsIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/connections" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Connections" + ], + "summary" : "Get Connection History", + "description" : "Returns active and historical streaming connections with disconnect reasons for the authenticated application.", + "operationId" : "getConnectionHistory", + "parameters" : [ + { + "name" : "status", + "in" : "query", + "description" : "Filter by connection status. Use 'active' for current connections, 'inactive' for historical/disconnected connections, or 'all' for both.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "active", + "inactive", + "all" + ], + "default" : "active" + }, + "style" : "form" + }, + { + "name" : "endpoints", + "in" : "query", + "description" : "Filter by streaming endpoint. Specify one or more endpoint names to filter results.", + "required" : false, + "schema" : { + "type" : "array", + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "filter_stream", + "sample_stream", + "sample10_stream", + "firehose_stream", + "tweets_compliance_stream", + "users_compliance_stream", + "tweet_label_stream", + "firehose_stream_lang_en", + "firehose_stream_lang_ja", + "firehose_stream_lang_ko", + "firehose_stream_lang_pt", + "likes_firehose_stream", + "likes_sample10_stream", + "likes_compliance_stream" + ] + } + }, + "explode" : false, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results to return per page.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "Token for paginating through results. Use the value from 'next_token' in the previous response.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/ConnectionFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ConnectionsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/connections/all" : { + "delete" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Connections" + ], + "summary" : "Terminate all connections", + "description" : "Terminates all active streaming connections for the authenticated application.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/connections/terminate-all-connections" + }, + "operationId" : "deleteAllConnections", + "parameters" : [ ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/KillAllConnectionsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_conversations" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Create DM conversation", + "description" : "Initiates a new direct message conversation with specified participants.", + "operationId" : "createDirectMessagesConversation", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateDmConversationRequest" + } + } + } + }, + "responses" : { + "201" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateDmEventResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_conversations/with/{participant_id}/dm_events" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Get DM events for a DM conversation", + "description" : "Retrieves direct message events for a specific conversation.", + "operationId" : "getDirectMessagesEventsByParticipantId", + "parameters" : [ + { + "name" : "participant_id", + "in" : "path", + "description" : "The ID of the participant user for the One to One DM conversation.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "name" : "event_types", + "in" : "query", + "description" : "The set of event_types to include in the results.", + "required" : false, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "MessageCreate", + "ParticipantsJoin", + "ParticipantsLeave" + ] + }, + "default" : [ + "MessageCreate", + "ParticipantsLeave", + "ParticipantsJoin" + ], + "example" : [ + "MessageCreate", + "ParticipantsLeave" + ] + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/DmEventFieldsParameter" + }, + { + "$ref" : "#/components/parameters/DmEventExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2DmConversationsWithParticipantIdDmEventsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_conversations/with/{participant_id}/messages" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Create DM message by participant ID", + "description" : "Sends a new direct message to a specific participant by their ID.", + "operationId" : "createDirectMessagesByParticipantId", + "parameters" : [ + { + "name" : "participant_id", + "in" : "path", + "description" : "The ID of the recipient user that will receive the DM.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateMessageRequest" + } + } + } + }, + "responses" : { + "201" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateDmEventResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_conversations/{dm_conversation_id}/messages" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Create DM message by conversation ID", + "description" : "Sends a new direct message to a specific conversation by its ID.", + "operationId" : "createDirectMessagesByConversationId", + "parameters" : [ + { + "name" : "dm_conversation_id", + "in" : "path", + "description" : "The DM Conversation ID.", + "required" : true, + "schema" : { + "type" : "string" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateMessageRequest" + } + } + } + }, + "responses" : { + "201" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateDmEventResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_conversations/{id}/dm_events" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Get DM events for a DM conversation", + "description" : "Retrieves direct message events for a specific conversation.", + "operationId" : "getDirectMessagesEventsByConversationId", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The DM conversation ID.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/DmConversationId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "name" : "event_types", + "in" : "query", + "description" : "The set of event_types to include in the results.", + "required" : false, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "MessageCreate", + "ParticipantsJoin", + "ParticipantsLeave" + ] + }, + "default" : [ + "MessageCreate", + "ParticipantsLeave", + "ParticipantsJoin" + ], + "example" : [ + "MessageCreate", + "ParticipantsLeave" + ] + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/DmEventFieldsParameter" + }, + { + "$ref" : "#/components/parameters/DmEventExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2DmConversationsIdDmEventsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_events" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Get DM events", + "description" : "Retrieves a list of recent direct message events across all conversations.", + "operationId" : "getDirectMessagesEvents", + "parameters" : [ + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "name" : "event_types", + "in" : "query", + "description" : "The set of event_types to include in the results.", + "required" : false, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "MessageCreate", + "ParticipantsJoin", + "ParticipantsLeave" + ] + }, + "default" : [ + "MessageCreate", + "ParticipantsLeave", + "ParticipantsJoin" + ], + "example" : [ + "MessageCreate", + "ParticipantsLeave" + ] + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/DmEventFieldsParameter" + }, + { + "$ref" : "#/components/parameters/DmEventExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2DmEventsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/dm_events/{event_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "dm.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Delete DM event", + "description" : "Deletes a specific direct message event by its ID, if owned by the authenticated user.", + "operationId" : "deleteDirectMessagesEvents", + "parameters" : [ + { + "name" : "event_id", + "in" : "path", + "description" : "The ID of the direct-message event to delete.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/DmEventId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/DeleteDmResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Direct Messages" + ], + "summary" : "Get DM event by ID", + "description" : "Retrieves details of a specific direct message event by its ID.", + "operationId" : "getDirectMessagesEventsById", + "parameters" : [ + { + "name" : "event_id", + "in" : "path", + "description" : "dm event id.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/DmEventId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/DmEventFieldsParameter" + }, + { + "$ref" : "#/components/parameters/DmEventExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2DmEventsEventIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/evaluate_note" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Community Notes" + ], + "summary" : "Evaluate a Community Note", + "description" : "Endpoint to evaluate a community note.", + "externalDocs" : { + "url" : "https://communitynotes.x.com/guide/api/overview" + }, + "operationId" : "evaluateCommunityNotes", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/EvaluateNoteRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/EvaluateNoteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/insights/28hr" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get 28-hour Post insights", + "description" : "Retrieves engagement metrics for specified Posts over the last 28 hours.", + "operationId" : "getInsights28Hr", + "parameters" : [ + { + "name" : "tweet_ids", + "in" : "query", + "description" : "List of PostIds for 28hr metrics.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 25, + "uniqueItems" : true, + "items" : { + "$ref" : "#/components/schemas/TweetId" + }, + "example" : [ + "20" + ] + }, + "style" : "form" + }, + { + "name" : "granularity", + "in" : "query", + "description" : "granularity of metrics response.", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ + "Daily", + "Hourly", + "Weekly", + "Total" + ], + "example" : "Total" + }, + "style" : "form" + }, + { + "name" : "requested_metrics", + "in" : "query", + "description" : "request metrics for historical request.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "AppInstallAttempts", + "AppOpens", + "DetailExpands", + "EmailTweet", + "Engagements", + "Follows", + "HashtagClicks", + "Impressions", + "Likes", + "LinkClicks", + "MediaEngagements", + "MediaViews", + "PermalinkClicks", + "ProfileVisits", + "QuoteTweets", + "Replies", + "Retweets", + "UniqueVideoViews", + "UrlClicks", + "UserProfileClicks", + "VideoCompletions", + "VideoPlayed25Percent", + "VideoPlayed50Percent", + "VideoPlayed75Percent", + "VideoStarts", + "VideoViews" + ] + } + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/EngagementFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2Insights28hrResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/insights/historical" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get historical Post insights", + "description" : "Retrieves historical engagement metrics for specified Posts within a defined time range.", + "operationId" : "getInsightsHistorical", + "parameters" : [ + { + "name" : "tweet_ids", + "in" : "query", + "description" : "List of PostIds for historical metrics.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 25, + "uniqueItems" : true, + "items" : { + "$ref" : "#/components/schemas/TweetId" + }, + "example" : [ + "20" + ] + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The UTC timestamp representing the end of the time range.", + "required" : true, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The UTC timestamp representing the start of the time range.", + "required" : true, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "granularity", + "in" : "query", + "description" : "granularity of metrics response.", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ + "Daily", + "Hourly", + "Weekly", + "Total" + ], + "example" : "Total" + }, + "style" : "form" + }, + { + "name" : "requested_metrics", + "in" : "query", + "description" : "request metrics for historical request.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "AppInstallAttempts", + "AppOpens", + "DetailExpands", + "EmailTweet", + "Engagements", + "Follows", + "HashtagClicks", + "Impressions", + "Likes", + "LinkClicks", + "MediaEngagements", + "MediaViews", + "PermalinkClicks", + "ProfileVisits", + "QuoteTweets", + "Replies", + "Retweets", + "UniqueVideoViews", + "UrlClicks", + "UserProfileClicks", + "VideoCompletions", + "VideoPlayed25Percent", + "VideoPlayed50Percent", + "VideoPlayed75Percent", + "VideoStarts", + "VideoViews" + ] + } + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/EngagementFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2InsightsHistoricalResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/likes/compliance/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Compliance" + ], + "summary" : "Stream Likes compliance data", + "description" : "Streams all compliance data related to Likes for Users.", + "operationId" : "streamLikesCompliance", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Likes Compliance events will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp from which the Likes Compliance events will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/LikesComplianceStreamResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/likes/firehose/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Likes" + ], + "summary" : "Stream all Likes", + "description" : "Streams all public Likes in real-time.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-likes-firehose-stream" + }, + "operationId" : "streamLikesFirehose", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 20, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Likes will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/LikeWithTweetAuthorFieldsParameter" + }, + { + "$ref" : "#/components/parameters/LikeWithTweetAuthorExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingLikeResponseV2" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/likes/sample10/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Likes" + ], + "summary" : "Stream sampled Likes", + "description" : "Streams a 10% sample of public Likes in real-time.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/likes/firehose/api-reference/get-likes-sample10-stream" + }, + "operationId" : "streamLikesSample10", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 2, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Likes will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/LikeWithTweetAuthorFieldsParameter" + }, + { + "$ref" : "#/components/parameters/LikeWithTweetAuthorExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingLikeResponseV2" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/lists" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.read", + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists" + ], + "summary" : "Create List", + "description" : "Creates a new List for the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/post-lists" + }, + "operationId" : "createLists", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/lists/{id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists" + ], + "summary" : "Delete List", + "description" : "Deletes a specific List owned by the authenticated user by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/delete-lists-id" + }, + "operationId" : "deleteLists", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List to delete.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists" + ], + "summary" : "Get List by ID", + "description" : "Retrieves details of a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-lists-id" + }, + "operationId" : "getListsById", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/ListFieldsParameter" + }, + { + "$ref" : "#/components/parameters/ListExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ListsIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "put" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists" + ], + "summary" : "Update List", + "description" : "Updates the details of a specific List owned by the authenticated user by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/manage-lists/api-reference/put-lists-id" + }, + "operationId" : "updateLists", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List to modify.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListUpdateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListUpdateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/lists/{id}/followers" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists", + "Users" + ], + "summary" : "Get List followers", + "description" : "Retrieves a list of Users who follow a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers" + }, + "operationId" : "getListsFollowers", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationTokenLong" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ListsIdFollowersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/lists/{id}/members" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists", + "Users" + ], + "summary" : "Get List members", + "description" : "Retrieves a list of Users who are members of a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships" + }, + "operationId" : "getListsMembers", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationTokenLong" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ListsIdMembersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists" + ], + "summary" : "Add List member", + "description" : "Adds a User to a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/post-lists-id-members" + }, + "operationId" : "addListsMember", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List for which to add a member.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListAddUserRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListMutateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/lists/{id}/members/{user_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists" + ], + "summary" : "Remove List member", + "description" : "Removes a User from a specific List by its ID and the User’s ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/delete-lists-id-members-user_id" + }, + "operationId" : "removeListsMemberByUserId", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List to remove a member.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + }, + { + "name" : "user_id", + "in" : "path", + "description" : "The ID of User that will be removed from the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListMutateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/lists/{id}/tweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Lists", + "Tweets" + ], + "summary" : "Get List Posts", + "description" : "Retrieves a list of Posts associated with a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-tweets/api-reference/get-lists-id-tweets" + }, + "operationId" : "getListsPosts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2ListsIdTweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Get Media by media keys", + "description" : "Retrieves details of Media files by their media keys.", + "externalDocs" : { + "url" : "https://developer.x.com" + }, + "operationId" : "getMediaByMediaKeys", + "parameters" : [ + { + "name" : "media_keys", + "in" : "query", + "description" : "A comma separated list of Media Keys. Up to 100 are allowed in a single request.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "$ref" : "#/components/schemas/MediaKey" + } + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2MediaResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/analytics" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Get Media analytics", + "description" : "Retrieves analytics data for media.", + "operationId" : "getMediaAnalytics", + "parameters" : [ + { + "name" : "media_keys", + "in" : "query", + "description" : "A comma separated list of Media Keys. Up to 100 are allowed in a single request.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "$ref" : "#/components/schemas/MediaKey" + } + }, + "explode" : false, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The UTC timestamp representing the end of the time range.", + "required" : true, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The UTC timestamp representing the start of the time range.", + "required" : true, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "granularity", + "in" : "query", + "description" : "The granularity for the search counts results.", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ + "hourly", + "daily", + "total" + ], + "default" : "daily" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/MediaAnalyticsFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaAnalytics" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/metadata" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Create Media metadata", + "description" : "Creates metadata for a Media file.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-metadata-create#metadata-create" + }, + "operationId" : "createMediaMetadata", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MetadataCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MetadataCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/subtitles" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Delete Media subtitles", + "description" : "Deletes subtitles for a specific Media file.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-subtitles-delete" + }, + "operationId" : "deleteMediaSubtitles", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubtitlesDeleteRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubtitlesDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Create Media subtitles", + "description" : "Creates subtitles for a specific Media file.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-subtitles-create" + }, + "operationId" : "createMediaSubtitles", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubtitlesCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SubtitlesCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/upload" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Get Media upload status", + "description" : "Retrieves the status of a Media upload by its ID.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-upload-status#media-upload-status" + }, + "operationId" : "getMediaUploadStatus", + "parameters" : [ + { + "name" : "media_id", + "in" : "query", + "description" : "Media id for the requested media upload status.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/MediaId" + }, + "style" : "form" + }, + { + "name" : "command", + "in" : "query", + "description" : "The command for the media upload request.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "STATUS" + ] + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Upload media", + "description" : "Uploads a media file for use in posts or other content.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-upload" + }, + "operationId" : "mediaUpload", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadRequestOneShot" + } + }, + "multipart/form-data" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadRequestOneShot" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/upload/initialize" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Initialize media upload", + "description" : "Initializes a media upload.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-upload" + }, + "operationId" : "initializeMediaUpload", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadConfigRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/upload/{id}/append" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Append Media upload", + "description" : "Appends data to a Media upload request.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-upload" + }, + "operationId" : "appendMediaUpload", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The media identifier for the media to perform the append operation.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/MediaId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadAppendRequest" + } + }, + "multipart/form-data" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadAppendRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadAppendResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/upload/{id}/finalize" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "media.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Finalize Media upload", + "description" : "Finalizes a Media upload request.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/media/media-upload" + }, + "operationId" : "finalizeMediaUpload", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The media id of the targeted media to finalize.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/MediaId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MediaUploadResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/media/{media_key}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Media" + ], + "summary" : "Get Media by media key", + "description" : "Retrieves details of a specific Media file by its media key.", + "externalDocs" : { + "url" : "https://developer.x.com" + }, + "operationId" : "getMediaByMediaKey", + "parameters" : [ + { + "name" : "media_key", + "in" : "path", + "description" : "A single Media Key.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/MediaKey" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2MediaMediaKeyResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/news/search" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "News" + ], + "summary" : "Search News", + "description" : "Retrieves a list of News stories matching the specified search query.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/news/introduction" + }, + "operationId" : "searchNews", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "The search query.", + "required" : true, + "example" : "crypto", + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 2048, + "example" : "crypto" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The number of results to return.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "max_age_hours", + "in" : "query", + "description" : "The maximum age of the News story to search for.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 720, + "format" : "int32", + "default" : 168 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/NewsFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2NewsSearchResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/news/{id}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "News" + ], + "summary" : "Get news stories by ID", + "description" : "Retrieves news story by its ID.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/news/introduction" + }, + "operationId" : "getNews", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the news story.", + "required" : true, + "example" : "119929381293", + "schema" : { + "$ref" : "#/components/schemas/NewsId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/NewsFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2NewsIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/notes" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Community Notes" + ], + "summary" : "Create a Community Note", + "description" : "Creates a community note endpoint for LLM use case.", + "externalDocs" : { + "url" : "https://communitynotes.x.com/guide/api/overview" + }, + "operationId" : "createCommunityNotes", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateNoteRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/CreateNoteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/notes/search/notes_written" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Community Notes" + ], + "summary" : "Search for Community Notes Written", + "description" : "Returns all the community notes written by the user.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/community-notes/search-for-community-notes-written" + }, + "operationId" : "searchCommunityNotesWritten", + "parameters" : [ + { + "name" : "test_mode", + "in" : "query", + "description" : "If true, return the notes the caller wrote for the test. If false, return the notes the caller wrote on the product.", + "required" : true, + "schema" : { + "type" : "boolean" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "Pagination token to get next set of posts eligible for notes.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "Max results to return.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/NoteFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2NotesSearchNotesWrittenResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/notes/search/posts_eligible_for_notes" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Community Notes" + ], + "summary" : "Search for Posts Eligible for Community Notes", + "description" : "Returns all the posts that are eligible for community notes.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/community-notes/search-for-posts-eligible-for-community-notes" + }, + "operationId" : "searchEligiblePosts", + "parameters" : [ + { + "name" : "test_mode", + "in" : "query", + "description" : "If true, return a list of posts that are for the test. If false, return a list of posts that the bots can write proposed notes on the product.", + "required" : true, + "schema" : { + "type" : "boolean" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "Pagination token to get next set of posts eligible for notes.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "Max results to return.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "post_selection", + "in" : "query", + "description" : "The selection of posts to return. Valid values are 'feed_size: small' and 'feed_size: large'. Default is 'feed_size: small', only top AI writers have access to large size feed.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2NotesSearchPostsEligibleForNotesResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/notes/{id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.write" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Community Notes" + ], + "summary" : "Delete a Community Note", + "description" : "Deletes a community note.", + "externalDocs" : { + "url" : "https://communitynotes.x.com/guide/api/overview" + }, + "operationId" : "deleteCommunityNotes", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The community note id to delete.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/NoteId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/DeleteNoteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/openapi.json" : { + "get" : { + "tags" : [ + "General" + ], + "summary" : "Get OpenAPI Spec.", + "description" : "Retrieves the full OpenAPI Specification in JSON format. (See https://github.com/OAI/OpenAPI-Specification/blob/master/README.md)", + "operationId" : "getOpenApiSpec", + "parameters" : [ ], + "responses" : { + "200" : { + "description" : "The request was successful", + "content" : { + "application/json" : { + "schema" : { + "type" : "object" + } + } + } + } + } + } + }, + "/2/spaces" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "space.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Spaces" + ], + "summary" : "Get Spaces by IDs", + "description" : "Retrieves details of multiple Spaces by their IDs.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces" + }, + "operationId" : "getSpacesByIds", + "parameters" : [ + { + "name" : "ids", + "in" : "query", + "description" : "The list of Space IDs to return.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "type" : "string", + "description" : "The unique identifier of this Space.", + "pattern" : "^[a-zA-Z0-9]{1,13}$", + "example" : "1SLjjRYNejbKM" + } + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/SpaceFieldsParameter" + }, + { + "$ref" : "#/components/parameters/SpaceExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TopicFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2SpacesResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/spaces/by/creator_ids" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "space.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Spaces" + ], + "summary" : "Get Spaces by creator IDs", + "description" : "Retrieves details of Spaces created by specified User IDs.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-by-creator-ids" + }, + "operationId" : "getSpacesByCreatorIds", + "parameters" : [ + { + "name" : "user_ids", + "in" : "query", + "description" : "The IDs of Users to search through.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/SpaceFieldsParameter" + }, + { + "$ref" : "#/components/parameters/SpaceExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TopicFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2SpacesByCreatorIdsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/spaces/search" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "space.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Spaces" + ], + "summary" : "Search Spaces", + "description" : "Retrieves a list of Spaces matching the specified search query.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces/search/api-reference/get-spaces-search" + }, + "operationId" : "searchSpaces", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "The search query.", + "required" : true, + "example" : "crypto", + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 2048, + "example" : "crypto" + }, + "style" : "form" + }, + { + "name" : "state", + "in" : "query", + "description" : "The state of Spaces to search for.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "live", + "scheduled", + "all" + ], + "default" : "all" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The number of results to return.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/SpaceFieldsParameter" + }, + { + "$ref" : "#/components/parameters/SpaceExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TopicFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2SpacesSearchResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/spaces/{id}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "space.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Spaces" + ], + "summary" : "Get space by ID", + "description" : "Retrieves details of a specific space by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id" + }, + "operationId" : "getSpacesById", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the Space to be retrieved.", + "required" : true, + "example" : "1YqKDqWqdPLsV", + "schema" : { + "type" : "string", + "description" : "The unique identifier of this Space.", + "pattern" : "^[a-zA-Z0-9]{1,13}$", + "example" : "1SLjjRYNejbKM" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/SpaceFieldsParameter" + }, + { + "$ref" : "#/components/parameters/SpaceExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TopicFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2SpacesIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/spaces/{id}/buyers" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "space.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Spaces", + "Tweets" + ], + "summary" : "Get Space ticket buyers", + "description" : "Retrieves a list of Users who purchased tickets to a specific Space by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-buyers" + }, + "operationId" : "getSpacesBuyers", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the Space to be retrieved.", + "required" : true, + "example" : "1YqKDqWqdPLsV", + "schema" : { + "type" : "string", + "description" : "The unique identifier of this Space.", + "pattern" : "^[a-zA-Z0-9]{1,13}$", + "example" : "1SLjjRYNejbKM" + }, + "style" : "simple" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2SpacesIdBuyersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/spaces/{id}/tweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "space.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Spaces", + "Tweets" + ], + "summary" : "Get Space Posts", + "description" : "Retrieves a list of Posts shared in a specific Space by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces/lookup/api-reference/get-spaces-id-tweets" + }, + "operationId" : "getSpacesPosts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the Space to be retrieved.", + "required" : true, + "example" : "1YqKDqWqdPLsV", + "schema" : { + "type" : "string", + "description" : "The unique identifier of this Space.", + "pattern" : "^[a-zA-Z0-9]{1,13}$", + "example" : "1SLjjRYNejbKM" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The number of Posts to fetch from the provided space. If not provided, the value will default to the maximum of 100.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100, + "example" : 25 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2SpacesIdTweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/trends/by/woeid/{woeid}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Trends" + ], + "summary" : "Get Trends by WOEID", + "description" : "Retrieves trending topics for a specific location identified by its WOEID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/trends/api-reference/get-trends-by-woeid" + }, + "operationId" : "getTrendsByWoeid", + "parameters" : [ + { + "name" : "woeid", + "in" : "path", + "description" : "The WOEID of the place to lookup a trend for.", + "required" : true, + "example" : "2244994945", + "schema" : { + "type" : "integer", + "format" : "int32" + }, + "style" : "simple" + }, + { + "name" : "max_trends", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 50, + "format" : "int32", + "default" : 20 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TrendFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TrendsByWoeidWoeidResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get Posts by IDs", + "description" : "Retrieves details of multiple Posts by their IDs.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets" + }, + "operationId" : "getPostsByIds", + "parameters" : [ + { + "name" : "ids", + "in" : "query", + "description" : "A comma separated list of Post IDs. Up to 100 are allowed in a single request.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "tweet.write", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Create or Edit Post", + "description" : "Creates a new Post for the authenticated user, or edits an existing Post when edit_options are provided.", + "externalDocs" : { + "url" : "https://developer.x.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/post-tweets" + }, + "operationId" : "createPosts", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetCreateRequest" + } + } + }, + "required" : true + }, + "responses" : { + "201" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/analytics" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get Post analytics", + "description" : "Retrieves analytics data for specified Posts within a defined time range.", + "operationId" : "getPostsAnalytics", + "parameters" : [ + { + "name" : "ids", + "in" : "query", + "description" : "A comma separated list of Post IDs. Up to 100 are allowed in a single request.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "explode" : false, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The UTC timestamp representing the end of the time range.", + "required" : true, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The UTC timestamp representing the start of the time range.", + "required" : true, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "granularity", + "in" : "query", + "description" : "The granularity for the search counts results.", + "required" : true, + "schema" : { + "type" : "string", + "enum" : [ + "hourly", + "daily", + "weekly", + "total" + ], + "default" : "total" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/AnalyticsFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Analytics" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/compliance/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Compliance" + ], + "summary" : "Stream Posts compliance data", + "description" : "Streams all compliance data related to Posts.", + "operationId" : "streamPostsCompliance", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 4, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Post Compliance events will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Post Compliance events will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetComplianceStreamResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/counts/all" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get count of all Posts", + "description" : "Retrieves the count of Posts matching a search query from the full archive.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all" + }, + "operationId" : "getPostsCountsAll", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "One query/rule/filter for matching Posts. Refer to https://t.co/rulelength to identify the max query length.", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 4096, + "example" : "(from:TwitterDev OR from:TwitterAPI) has:media -is:retweet" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The oldest UTC timestamp from which the Posts will be provided. Timestamp is in second granularity and is inclusive (i.e. 12:00:01 includes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The newest, most recent UTC timestamp to which the Posts will be provided. Timestamp is in second granularity and is exclusive (i.e. 12:00:01 excludes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "Returns results with a Post ID greater than (that is, more recent than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "Returns results with a Post ID less than (that is, older than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "next_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "granularity", + "in" : "query", + "description" : "The granularity for the search counts results.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "minute", + "hour", + "day" + ], + "default" : "hour" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/SearchCountFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsCountsAllResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/counts/recent" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get count of recent Posts", + "description" : "Retrieves the count of Posts from the last 7 days matching a search query.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/counts/api-reference/get-tweets-counts-recent" + }, + "operationId" : "getPostsCountsRecent", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "One query/rule/filter for matching Posts. Refer to https://t.co/rulelength to identify the max query length.", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 4096, + "example" : "(from:TwitterDev OR from:TwitterAPI) has:media -is:retweet" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The oldest UTC timestamp (from most recent 7 days) from which the Posts will be provided. Timestamp is in second granularity and is inclusive (i.e. 12:00:01 includes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The newest, most recent UTC timestamp to which the Posts will be provided. Timestamp is in second granularity and is exclusive (i.e. 12:00:01 excludes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "Returns results with a Post ID greater than (that is, more recent than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "Returns results with a Post ID less than (that is, older than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "next_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "granularity", + "in" : "query", + "description" : "The granularity for the search counts results.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "minute", + "hour", + "day" + ], + "default" : "hour" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/SearchCountFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsCountsRecentResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/firehose/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream all Posts", + "description" : "Streams all public Posts in real-time.", + "operationId" : "streamPostsFirehose", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 20, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/firehose/stream/lang/en" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream English Posts", + "description" : "Streams all public English-language Posts in real-time.", + "operationId" : "streamPostsFirehoseEn", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 8, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/firehose/stream/lang/ja" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream Japanese Posts", + "description" : "Streams all public Japanese-language Posts in real-time.", + "operationId" : "streamPostsFirehoseJa", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 2, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/firehose/stream/lang/ko" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream Korean Posts", + "description" : "Streams all public Korean-language Posts in real-time.", + "operationId" : "streamPostsFirehoseKo", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 2, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/firehose/stream/lang/pt" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream Portuguese Posts", + "description" : "Streams all public Portuguese-language Posts in real-time.", + "operationId" : "streamPostsFirehosePt", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 2, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/label/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Compliance" + ], + "summary" : "Stream Post labels", + "description" : "Streams all labeling events applied to Posts.", + "operationId" : "streamLabelsCompliance", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Post labels will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp from which the Post labels will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetLabelStreamResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/sample/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream sampled Posts", + "description" : "Streams a 1% sample of public Posts in real-time.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/volume-streams/api-reference/get-tweets-sample-stream" + }, + "operationId" : "streamPostsSample", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/sample10/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream 10% sampled Posts", + "description" : "Streams a 10% sample of public Posts in real-time.", + "operationId" : "streamPostsSample10", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 2, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsSample10StreamResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/search/all" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Search all Posts", + "description" : "Retrieves Posts from the full archive matching a search query.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-all" + }, + "operationId" : "searchPostsAll", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "One query/rule/filter for matching Posts. Refer to https://t.co/rulelength to identify the max query length.", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 4096, + "example" : "(from:TwitterDev OR from:TwitterAPI) has:media -is:retweet" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The oldest UTC timestamp from which the Posts will be provided. Timestamp is in second granularity and is inclusive (i.e. 12:00:01 includes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The newest, most recent UTC timestamp to which the Posts will be provided. Timestamp is in second granularity and is exclusive (i.e. 12:00:01 excludes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "Returns results with a Post ID greater than (that is, more recent than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "Returns results with a Post ID less than (that is, older than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of search results to be returned by a request.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 10, + "maximum" : 500, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "next_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "sort_order", + "in" : "query", + "description" : "This order in which to return results.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "recency", + "relevancy" + ] + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsSearchAllResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/search/recent" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Search recent Posts", + "description" : "Retrieves Posts from the last 7 days matching a search query.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent" + }, + "operationId" : "searchPostsRecent", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "One query/rule/filter for matching Posts. Refer to https://t.co/rulelength to identify the max query length.", + "required" : true, + "schema" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 4096, + "example" : "(from:TwitterDev OR from:TwitterAPI) has:media -is:retweet" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The oldest UTC timestamp from which the Posts will be provided. Timestamp is in second granularity and is inclusive (i.e. 12:00:01 includes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The newest, most recent UTC timestamp to which the Posts will be provided. Timestamp is in second granularity and is exclusive (i.e. 12:00:01 excludes the first second of the minute).", + "required" : false, + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "Returns results with a Post ID greater than (that is, more recent than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "Returns results with a Post ID less than (that is, older than) the specified ID.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of search results to be returned by a request.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 10, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "next_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "sort_order", + "in" : "query", + "description" : "This order in which to return results.", + "required" : false, + "schema" : { + "type" : "string", + "enum" : [ + "recency", + "relevancy" + ] + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsSearchRecentResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/search/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Stream filtered Posts", + "description" : "Streams Posts in real-time matching the active rule set.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream" + }, + "operationId" : "streamPosts", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Posts will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/FilteredStreamingTweetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/tweets/search/stream/rules" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Get stream rules", + "description" : "Retrieves the active rule set or a subset of rules for the filtered stream.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream-rules" + }, + "operationId" : "getRules", + "parameters" : [ + { + "name" : "ids", + "in" : "query", + "description" : "A comma-separated list of Rule IDs.", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/RuleId" + } + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 1000, + "format" : "int32", + "default" : 1000 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This value is populated by passing the 'next_token' returned in a request to paginate through results.", + "required" : false, + "schema" : { + "type" : "string", + "minLength" : 16, + "maxLength" : 16 + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/RulesLookupResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Update stream rules", + "description" : "Adds or deletes rules from the active rule set for the filtered stream.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/post-tweets-search-stream-rules" + }, + "operationId" : "updateRules", + "parameters" : [ + { + "name" : "dry_run", + "in" : "query", + "description" : "Dry Run can be used with both the add and delete action, with the expected result given, but without actually taking any action in the system (meaning the end state will always be as it was when the request was submitted). This is particularly useful to validate rule changes.", + "required" : false, + "schema" : { + "type" : "boolean" + }, + "style" : "form" + }, + { + "name" : "delete_all", + "in" : "query", + "description" : "Delete All can be used to delete all of the rules associated this client app, it should be specified with no other parameters. Once deleted, rules cannot be recovered.", + "required" : false, + "schema" : { + "type" : "boolean" + }, + "style" : "form" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AddOrDeleteRulesRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/AddOrDeleteRulesResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/search/stream/rules/counts" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Tweets" + ], + "summary" : "Get stream rule counts", + "description" : "Retrieves the count of rules in the active rule set for the filtered stream.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/api-reference/get-tweets-search-stream-rules-counts" + }, + "operationId" : "getRuleCounts", + "parameters" : [ + { + "$ref" : "#/components/parameters/RulesCountFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsSearchStreamRulesCountsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/search/webhooks" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Webhooks", + "Stream" + ], + "summary" : "Get stream links", + "description" : "Get a list of webhook links associated with a filtered stream ruleset.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "getWebhooksStreamLinks", + "parameters" : [ ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookLinksGetResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/search/webhooks/{webhook_id}" : { + "delete" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Webhooks", + "Stream" + ], + "summary" : "Delete stream link", + "description" : "Deletes a link from FilteredStream events to the given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "deleteWebhooksStreamLink", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The webhook ID to link to your FilteredStream ruleset.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookLinksDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Webhooks", + "Stream" + ], + "summary" : "Create stream link", + "description" : "Creates a link to deliver FilteredStream events to the given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "createWebhooksStreamLink", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The webhook ID to link to your FilteredStream ruleset.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + }, + { + "name" : "tweet.fields", + "in" : "query", + "description" : "A comma separated list of Tweet fields to display.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "media.fields", + "in" : "query", + "description" : "A comma separated list of Media fields to display.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "poll.fields", + "in" : "query", + "description" : "A comma separated list of Poll fields to display.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "user.fields", + "in" : "query", + "description" : "A comma separated list of User fields to display.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + }, + { + "name" : "place.fields", + "in" : "query", + "description" : "A comma separated list of Place fields to display.", + "required" : false, + "schema" : { + "type" : "string" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookLinksCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/{id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "tweet.write", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Delete Post", + "description" : "Deletes a specific Post by its ID, if owned by the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/api-reference/delete-tweets-id" + }, + "operationId" : "deletePosts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the Post to be deleted.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get Post by ID", + "description" : "Retrieves details of a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/lookup/api-reference/get-tweets-id" + }, + "operationId" : "getPostsById", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "A single Post ID.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/{id}/liking_users" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "like.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets", + "Users" + ], + "summary" : "Get Liking Users", + "description" : "Retrieves a list of Users who liked a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-tweets-id-liking_users" + }, + "operationId" : "getPostsLikingUsers", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "A single Post ID.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsIdLikingUsersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/{id}/quote_tweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get Quoted Posts", + "description" : "Retrieves a list of Posts that quote a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/quote-tweets/api-reference/get-tweets-id-quote_tweets" + }, + "operationId" : "getPostsQuotedPosts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "A single Post ID.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results to be returned.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 10, + "maximum" : 100, + "format" : "int32", + "default" : 10 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "exclude", + "in" : "query", + "description" : "The set of entities to exclude (e.g. 'replies' or 'retweets').", + "required" : false, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "replies", + "retweets" + ] + }, + "example" : [ + "replies", + "retweets" + ] + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsIdQuoteTweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/{id}/retweeted_by" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets", + "Users" + ], + "summary" : "Get Reposted by", + "description" : "Retrieves a list of Users who reposted a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweeted_by" + }, + "operationId" : "getPostsRepostedBy", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "A single Post ID.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsIdRetweetedByResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/{id}/retweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Get Reposts", + "description" : "Retrieves a list of Posts that repost a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/get-tweets-id-retweets" + }, + "operationId" : "getPostsReposts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "A single Post ID.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2TweetsIdRetweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/tweets/{tweet_id}/hidden" : { + "put" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.moderate.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Tweets" + ], + "summary" : "Hide reply", + "description" : "Hides or unhides a reply to a conversation owned by the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/hide-replies/api-reference/put-tweets-id-hidden" + }, + "operationId" : "hidePostsReply", + "parameters" : [ + { + "name" : "tweet_id", + "in" : "path", + "description" : "The ID of the reply that you want to hide or unhide.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetHideRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/TweetHideResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/usage/tweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Usage" + ], + "summary" : "Get usage", + "description" : "Retrieves usage statistics for Posts over a specified number of days.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/usage/tweets/api-reference/get-usage-tweets" + }, + "operationId" : "getUsage", + "parameters" : [ + { + "name" : "days", + "in" : "query", + "description" : "The number of days for which you need usage for.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 90, + "format" : "int32", + "default" : 7 + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UsageFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsageTweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get Users by IDs", + "description" : "Retrieves details of multiple Users by their IDs.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users" + }, + "operationId" : "getUsersByIds", + "parameters" : [ + { + "name" : "ids", + "in" : "query", + "description" : "A list of User IDs, comma-separated. You can specify up to 100 IDs.", + "required" : true, + "example" : "2244994945,6253282,12", + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/by" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get Users by usernames", + "description" : "Retrieves details of multiple Users by their usernames.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by" + }, + "operationId" : "getUsersByUsernames", + "parameters" : [ + { + "name" : "usernames", + "in" : "query", + "description" : "A list of usernames, comma-separated.", + "required" : true, + "schema" : { + "type" : "array", + "minItems" : 1, + "maxItems" : 100, + "items" : { + "type" : "string", + "description" : "The X handle (screen name) of this User.", + "pattern" : "^[A-Za-z0-9_]{1,15}$" + }, + "example" : "TwitterDev,TwitterAPI" + }, + "explode" : false, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersByResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/by/username/{username}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get User by username", + "description" : "Retrieves details of a specific User by their username.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by-username-username" + }, + "operationId" : "getUsersByUsername", + "parameters" : [ + { + "name" : "username", + "in" : "path", + "description" : "A username.", + "required" : true, + "example" : "TwitterDev", + "schema" : { + "type" : "string", + "pattern" : "^[A-Za-z0-9_]{1,15}$" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersByUsernameUsernameResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/compliance/stream" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Stream", + "Compliance" + ], + "summary" : "Stream Users compliance data", + "description" : "Streams all compliance data related to Users.", + "operationId" : "streamUsersCompliance", + "parameters" : [ + { + "name" : "backfill_minutes", + "in" : "query", + "description" : "The number of minutes of backfill requested.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 0, + "maximum" : 5, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "partition", + "in" : "query", + "description" : "The partition number.", + "required" : true, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 4, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the User Compliance events will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp from which the User Compliance events will be provided.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UserComplianceStreamResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + }, + "x-twitter-streaming" : true + } + }, + "/2/users/me" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get my User", + "description" : "Retrieves details of the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me" + }, + "operationId" : "getUsersMe", + "parameters" : [ + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersMeResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/personalized_trends" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Trends" + ], + "summary" : "Get personalized Trends", + "description" : "Retrieves personalized trending topics for the authenticated user.", + "externalDocs" : { + "url" : "https://developer.x.com/" + }, + "operationId" : "getTrendsPersonalizedTrends", + "parameters" : [ + { + "$ref" : "#/components/parameters/PersonalizedTrendFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersPersonalizedTrendsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/reposts_of_me" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "timeline.read", + "tweet.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get Reposts of me", + "description" : "Retrieves a list of Posts that repost content from the authenticated user.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/posts/retweets/quickstart/retweets-of-me#retweets-of-me" + }, + "operationId" : "getUsersRepostsOfMe", + "parameters" : [ + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersRepostsOfMeResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/search" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Search Users", + "description" : "Retrieves a list of Users matching a search query.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-search" + }, + "operationId" : "searchUsers", + "parameters" : [ + { + "name" : "query", + "in" : "query", + "description" : "TThe the query string by which to query for users.", + "required" : true, + "example" : "someXUser", + "schema" : { + "$ref" : "#/components/schemas/UserSearchQueryVnext" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 1000, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "next_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results. The value used with the parameter is pulled directly from the response provided by the API, and should not be modified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersSearchResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get User by ID", + "description" : "Retrieves details of a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id" + }, + "operationId" : "getUsersById", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/blocking" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "block.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get blocking", + "description" : "Retrieves a list of Users blocked by the specified User ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/blocks/api-reference/get-users-blocking" + }, + "operationId" : "getUsersBlocking", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 1000, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdBlockingResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/bookmarks" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "bookmark.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Users", + "Bookmarks" + ], + "summary" : "Get Bookmarks", + "description" : "Retrieves a list of Posts bookmarked by the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/get-users-id-bookmarks" + }, + "operationId" : "getUsersBookmarks", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdBookmarksResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "bookmark.write", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Users", + "Bookmarks" + ], + "summary" : "Create Bookmark", + "description" : "Adds a post to the authenticated user’s bookmarks.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/post-users-id-bookmarks" + }, + "operationId" : "createUsersBookmark", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to add bookmarks.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookmarkAddRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookmarkMutationResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/bookmarks/folders" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "bookmark.read", + "users.read" + ] + } + ], + "tags" : [ + "Users", + "Bookmarks" + ], + "summary" : "Get Bookmark folders", + "description" : "Retrieves a list of Bookmark folders created by the authenticated user.", + "externalDocs" : { + "url" : "https://developer.x.com" + }, + "operationId" : "getUsersBookmarkFolders", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookmarkFoldersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/bookmarks/folders/{folder_id}" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "bookmark.read", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Users", + "Bookmarks" + ], + "summary" : "Get Bookmarks by folder ID", + "description" : "Retrieves Posts in a specific Bookmark folder by its ID for the authenticated user.", + "externalDocs" : { + "url" : "https://developer.x.com" + }, + "operationId" : "getUsersBookmarksByFolderId", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "folder_id", + "in" : "path", + "description" : "The ID of the Bookmark Folder that the authenticated User is trying to fetch Posts for.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/BookmarkFolderId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookmarkFolderPostsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/bookmarks/{tweet_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "bookmark.write", + "tweet.read", + "users.read" + ] + } + ], + "tags" : [ + "Users", + "Bookmarks" + ], + "summary" : "Delete Bookmark", + "description" : "Removes a Post from the authenticated user’s Bookmarks by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/bookmarks/api-reference/delete-users-id-bookmarks-tweet_id" + }, + "operationId" : "deleteUsersBookmark", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User whose bookmark is to be removed.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "tweet_id", + "in" : "path", + "description" : "The ID of the Post that the source User is removing from bookmarks.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/BookmarkMutationResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/dm/block" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Block DMs", + "description" : "Blocks direct messages to or from a specific User by their ID for the authenticated user.", + "externalDocs" : { + "url" : "https://developer.x.com/" + }, + "operationId" : "blockUsersDms", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the target User that the authenticated user requesting to block dms for.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersDMBlockCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/dm/unblock" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "dm.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Unblock DMs", + "description" : "Unblocks direct messages to or from a specific User by their ID for the authenticated user.", + "externalDocs" : { + "url" : "https://developer.x.com/" + }, + "operationId" : "unblockUsersDms", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the target User that the authenticated user requesting to unblock dms for.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersDMUnBlockCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/followed_lists" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Get followed Lists", + "description" : "Retrieves a list of Lists followed by a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/get-users-id-followed_lists" + }, + "operationId" : "getUsersFollowedLists", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationTokenLong" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/ListFieldsParameter" + }, + { + "$ref" : "#/components/parameters/ListExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdFollowedListsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Follow List", + "description" : "Causes the authenticated user to follow a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/post-users-id-followed-lists" + }, + "operationId" : "followList", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that will follow the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListFollowedRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListFollowedResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/followed_lists/{list_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Unfollow List", + "description" : "Causes the authenticated user to unfollow a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-follows/api-reference/delete-users-id-followed-lists-list_id" + }, + "operationId" : "unfollowList", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that will unfollow the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "list_id", + "in" : "path", + "description" : "The ID of the List to unfollow.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListFollowedResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/followers" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "follows.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get followers", + "description" : "Retrieves a list of Users who follow a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-followers" + }, + "operationId" : "getUsersFollowers", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 1000, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdFollowersResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/following" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "follows.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get following", + "description" : "Retrieves a list of Users followed by a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following" + }, + "operationId" : "getUsersFollowing", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 1000, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken32" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdFollowingResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "follows.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Follow User", + "description" : "Causes the authenticated user to follow a specific user by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/post-users-source_user_id-following" + }, + "operationId" : "followUser", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to follow the target User.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersFollowingCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersFollowingCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/liked_tweets" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "like.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Get liked Posts", + "description" : "Retrieves a list of Posts liked by a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/get-users-id-liked_tweets" + }, + "operationId" : "getUsersLikedPosts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 5, + "maximum" : 100, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdLikedTweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/likes" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "like.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Like Post", + "description" : "Causes the authenticated user to Like a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/post-users-id-likes" + }, + "operationId" : "likePost", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to like the Post.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersLikesCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersLikesCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/likes/{tweet_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "like.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Unlike Post", + "description" : "Causes the authenticated user to Unlike a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/likes/api-reference/delete-users-id-likes-tweet_id" + }, + "operationId" : "unlikePost", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to unlike the Post.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "tweet_id", + "in" : "path", + "description" : "The ID of the Post that the User is requesting to unlike.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersLikesDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/list_memberships" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Get List memberships", + "description" : "Retrieves a list of Lists that a specific User is a member of by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-members/api-reference/get-users-id-list_memberships" + }, + "operationId" : "getUsersListMemberships", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationTokenLong" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/ListFieldsParameter" + }, + { + "$ref" : "#/components/parameters/ListExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdListMembershipsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/mentions" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Get mentions", + "description" : "Retrieves a list of Posts that mention a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-mentions" + }, + "operationId" : "getUsersMentions", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "The minimum Post ID to be included in the result set. This parameter takes precedence over start_time if both are specified.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "The maximum Post ID to be included in the result set. This parameter takes precedence over end_time if both are specified.", + "required" : false, + "example" : "1346889436626259968", + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 5, + "maximum" : 100, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Posts will be provided. The since_id parameter takes precedence if it is also specified.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided. The until_id parameter takes precedence if it is also specified.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdMentionsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/muting" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "mute.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Get muting", + "description" : "Retrieves a list of Users muted by the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/get-users-muting" + }, + "operationId" : "getUsersMuting", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 1000, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationTokenLong" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdMutingResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "mute.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Mute User", + "description" : "Causes the authenticated user to mute a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/post-users-user_id-muting" + }, + "operationId" : "muteUser", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to mute the target User.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MuteUserRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MuteUserMutationResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/owned_lists" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Get owned Lists", + "description" : "Retrieves a list of Lists owned by a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/list-lookup/api-reference/get-users-id-owned_lists" + }, + "operationId" : "getUsersOwnedLists", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32", + "default" : 100 + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get a specified 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationTokenLong" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/ListFieldsParameter" + }, + { + "$ref" : "#/components/parameters/ListExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdOwnedListsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/pinned_lists" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.read", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Get pinned Lists", + "description" : "Retrieves a list of Lists pinned by the authenticated user.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/get-users-id-pinned_lists" + }, + "operationId" : "getUsersPinnedLists", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "$ref" : "#/components/parameters/ListFieldsParameter" + }, + { + "$ref" : "#/components/parameters/ListExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdPinnedListsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Pin List", + "description" : "Causes the authenticated user to pin a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/post-users-id-pinned-lists" + }, + "operationId" : "pinList", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that will pin the List.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListPinnedRequest" + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListPinnedResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/pinned_lists/{list_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "list.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Lists" + ], + "summary" : "Unpin List", + "description" : "Causes the authenticated user to unpin a specific List by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists/pinned-lists/api-reference/delete-users-id-pinned-lists-list_id" + }, + "operationId" : "unpinList", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User for whom to return results.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "list_id", + "in" : "path", + "description" : "The ID of the List to unpin.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/ListId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ListUnpinResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/retweets" : { + "post" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "tweet.write", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Repost Post", + "description" : "Causes the authenticated user to repost a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/post-users-id-retweets" + }, + "operationId" : "repostPost", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to repost the Post.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + } + ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersRetweetsCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersRetweetsCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/retweets/{source_tweet_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "tweet.write", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Unrepost Post", + "description" : "Causes the authenticated user to unrepost a specific Post by its ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/retweets/api-reference/delete-users-id-retweets-tweet_id" + }, + "operationId" : "unrepostPost", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to repost the Post.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "source_tweet_id", + "in" : "path", + "description" : "The ID of the Post that the User is requesting to unretweet.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersRetweetsDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/timelines/reverse_chronological" : { + "get" : { + "security" : [ + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Get Timeline", + "description" : "Retrieves a reverse chronological list of Posts in the authenticated User’s Timeline.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-reverse-chronological" + }, + "operationId" : "getUsersTimeline", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the authenticated source User to list Reverse Chronological Timeline Posts of.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "The minimum Post ID to be included in the result set. This parameter takes precedence over start_time if both are specified.", + "required" : false, + "example" : "791775337160081409", + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "The maximum Post ID to be included in the result set. This parameter takes precedence over end_time if both are specified.", + "required" : false, + "example" : "1346889436626259968", + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 1, + "maximum" : 100, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "exclude", + "in" : "query", + "description" : "The set of entities to exclude (e.g. 'replies' or 'retweets').", + "required" : false, + "schema" : { + "type" : "array", + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "replies", + "retweets" + ] + }, + "example" : [ + "replies", + "retweets" + ] + }, + "explode" : false, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Posts will be provided. The since_id parameter takes precedence if it is also specified.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided. The until_id parameter takes precedence if it is also specified.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdTimelinesReverseChronologicalResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{id}/tweets" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "OAuth2UserToken" : [ + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users", + "Tweets" + ], + "summary" : "Get Posts", + "description" : "Retrieves a list of posts authored by a specific User by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/timelines/api-reference/get-users-id-tweets" + }, + "operationId" : "getUsersPosts", + "parameters" : [ + { + "name" : "id", + "in" : "path", + "description" : "The ID of the User to lookup.", + "required" : true, + "example" : "2244994945", + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + }, + { + "name" : "since_id", + "in" : "query", + "description" : "The minimum Post ID to be included in the result set. This parameter takes precedence over start_time if both are specified.", + "required" : false, + "example" : "791775337160081409", + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "until_id", + "in" : "query", + "description" : "The maximum Post ID to be included in the result set. This parameter takes precedence over end_time if both are specified.", + "required" : false, + "example" : "1346889436626259968", + "schema" : { + "$ref" : "#/components/schemas/TweetId" + }, + "style" : "form" + }, + { + "name" : "max_results", + "in" : "query", + "description" : "The maximum number of results.", + "required" : false, + "schema" : { + "type" : "integer", + "minimum" : 5, + "maximum" : 100, + "format" : "int32" + }, + "style" : "form" + }, + { + "name" : "pagination_token", + "in" : "query", + "description" : "This parameter is used to get the next 'page' of results.", + "required" : false, + "schema" : { + "$ref" : "#/components/schemas/PaginationToken36" + }, + "style" : "form" + }, + { + "name" : "exclude", + "in" : "query", + "description" : "The set of entities to exclude (e.g. 'replies' or 'retweets').", + "required" : false, + "schema" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "replies", + "retweets" + ] + }, + "example" : [ + "replies", + "retweets" + ] + }, + "explode" : false, + "style" : "form" + }, + { + "name" : "start_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The earliest UTC timestamp from which the Posts will be provided. The since_id parameter takes precedence if it is also specified.", + "required" : false, + "example" : "2021-02-01T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "name" : "end_time", + "in" : "query", + "description" : "YYYY-MM-DDTHH:mm:ssZ. The latest UTC timestamp to which the Posts will be provided. The until_id parameter takes precedence if it is also specified.", + "required" : false, + "example" : "2021-02-14T18:40:40.000Z", + "schema" : { + "type" : "string", + "format" : "date-time" + }, + "style" : "form" + }, + { + "$ref" : "#/components/parameters/TweetFieldsParameter" + }, + { + "$ref" : "#/components/parameters/TweetExpansionsParameter" + }, + { + "$ref" : "#/components/parameters/MediaFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PollFieldsParameter" + }, + { + "$ref" : "#/components/parameters/UserFieldsParameter" + }, + { + "$ref" : "#/components/parameters/PlaceFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2UsersIdTweetsResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{source_user_id}/following/{target_user_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "follows.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Unfollow User", + "description" : "Causes the authenticated user to unfollow a specific user by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/delete-users-source_id-following" + }, + "operationId" : "unfollowUser", + "parameters" : [ + { + "name" : "source_user_id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to unfollow the target User.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "target_user_id", + "in" : "path", + "description" : "The ID of the User that the source User is requesting to unfollow.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/UsersFollowingDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/users/{source_user_id}/muting/{target_user_id}" : { + "delete" : { + "security" : [ + { + "OAuth2UserToken" : [ + "mute.write", + "tweet.read", + "users.read" + ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Users" + ], + "summary" : "Unmute User", + "description" : "Causes the authenticated user to unmute a specific user by their ID.", + "externalDocs" : { + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/mutes/api-reference/delete-users-user_id-muting" + }, + "operationId" : "unmuteUser", + "parameters" : [ + { + "name" : "source_user_id", + "in" : "path", + "description" : "The ID of the authenticated source User that is requesting to unmute the target User.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserIdMatchesAuthenticatedUser" + }, + "style" : "simple" + }, + { + "name" : "target_user_id", + "in" : "path", + "description" : "The ID of the User that the source User is requesting to unmute.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/UserId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/MuteUserMutationResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/webhooks" : { + "get" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Webhooks" + ], + "summary" : "Get webhook", + "description" : "Get a list of webhook configs associated with a client app.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "getWebhooks", + "parameters" : [ + { + "$ref" : "#/components/parameters/WebhookConfigFieldsParameter" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Get2WebhooksResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "post" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Webhooks" + ], + "summary" : "Create webhook", + "description" : "Creates a new webhook configuration.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "createWebhooks", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/webhooks/replay" : { + "post" : { + "security" : [ + { + "BearerToken" : [ ] + } + ], + "tags" : [ + "Webhooks" + ], + "summary" : "Create replay job for webhook", + "description" : "Creates a replay job to retrieve events from up to the past 24 hours for all events delivered or attempted to be delivered to the webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "createWebhookReplayJob", + "parameters" : [ ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookReplayCreateRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReplayJobCreateResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + }, + "/2/webhooks/{webhook_id}" : { + "delete" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Webhooks" + ], + "summary" : "Delete webhook", + "description" : "Deletes an existing webhook configuration.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "deleteWebhooks", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The ID of the webhook to delete.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigDeleteResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + }, + "put" : { + "security" : [ + { + "BearerToken" : [ ] + }, + { + "UserToken" : [ ] + } + ], + "tags" : [ + "Webhooks" + ], + "summary" : "Validate webhook", + "description" : "Triggers a CRC check for a given webhook.", + "externalDocs" : { + "url" : "https://docs.x.com/x-api/webhooks/introduction" + }, + "operationId" : "validateWebhooks", + "parameters" : [ + { + "name" : "webhook_id", + "in" : "path", + "description" : "The ID of the webhook to check.", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "style" : "simple" + } + ], + "responses" : { + "200" : { + "description" : "The request has succeeded.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/WebhookConfigPutResponse" + } + } + } + }, + "default" : { + "description" : "The request has failed.", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Error" + } + }, + "application/problem+json" : { + "schema" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + } + } + } + }, + "servers" : [ + { + "description" : "X API", + "url" : "https://api.x.com" + } + ], + "tags" : [ + { + "name" : "Account Activity", + "description" : "Endpoints relating to retrieving, managing AAA subscriptions", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://docs.x.com/x-api/enterprise-gnip-2.0/fundamentals/account-activity" + } + }, + { + "name" : "Bookmarks", + "description" : "Endpoints related to retrieving, managing bookmarks of a user", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/bookmarks" + } + }, + { + "name" : "Compliance", + "description" : "Endpoints related to keeping X data in your systems compliant", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/compliance/batch-tweet/introduction" + } + }, + { + "name" : "Connections", + "description" : "Endpoints related to streaming connections", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.x.com/en/docs/x-api/connections" + } + }, + { + "name" : "Direct Messages", + "description" : "Endpoints related to retrieving, managing Direct Messages", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/direct-messages" + } + }, + { + "name" : "General", + "description" : "Miscellaneous endpoints for general API functionality", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api" + } + }, + { + "name" : "Lists", + "description" : "Endpoints related to retrieving, managing Lists", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/lists" + } + }, + { + "name" : "Media", + "description" : "Endpoints related to Media", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.x.com" + } + }, + { + "name" : "MediaUpload", + "description" : "Endpoints related to uploading Media", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.x.com" + } + }, + { + "name" : "News", + "description" : "Endpoint for retrieving news stories", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/news" + } + }, + { + "name" : "Spaces", + "description" : "Endpoints related to retrieving, managing Spaces", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/spaces" + } + }, + { + "name" : "Stream", + "description" : "Endpoints related to streaming", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.x.com" + } + }, + { + "name" : "Tweets", + "description" : "Endpoints related to retrieving, searching, and modifying Tweets", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/tweets/lookup" + } + }, + { + "name" : "Users", + "description" : "Endpoints related to retrieving, managing relationships of Users", + "externalDocs" : { + "description" : "Find out more", + "url" : "https://developer.twitter.com/en/docs/twitter-api/users/lookup" + } + } + ], + "components" : { + "securitySchemes" : { + "BearerToken" : { + "type" : "http", + "scheme" : "bearer" + }, + "OAuth2UserToken" : { + "type" : "oauth2", + "flows" : { + "authorizationCode" : { + "authorizationUrl" : "https://api.x.com/2/oauth2/authorize", + "tokenUrl" : "https://api.x.com/2/oauth2/token", + "scopes" : { + "block.read" : "View accounts you have blocked.", + "bookmark.read" : "Read your bookmarked Posts.", + "bookmark.write" : "Create and delete your bookmarks.", + "dm.read" : "Read all your Direct Messages.", + "dm.write" : "Send and manage your Direct Messages.", + "follows.read" : "View accounts you follow and accounts following you.", + "follows.write" : "Follow and unfollow accounts on your behalf.", + "like.read" : "View Posts you have liked and likes you can see.", + "like.write" : "Like and unlike Posts on your behalf.", + "list.read" : "View Lists, members, and followers of Lists you created or are a member of, including private Lists.", + "list.write" : "Create and manage Lists on your behalf.", + "media.write" : "Upload media, such as photos and videos, on your behalf.", + "mute.read" : "View accounts you have muted.", + "mute.write" : "Mute and unmute accounts on your behalf.", + "offline.access" : "Request a refresh token for the app.", + "space.read" : "View all Spaces you have access to.", + "timeline.read" : "View all Custom Timelines you can see, including public Custom Timelines from other developers.", + "tweet.moderate.write" : "Hide and unhide replies to your Posts.", + "tweet.read" : "View all Posts you can see, including those from protected accounts.", + "tweet.write" : "Post and repost on your behalf.", + "users.read" : "View any account you can see, including protected accounts." + } + } + } + }, + "UserToken" : { + "type" : "http", + "scheme" : "OAuth" + } + }, + "schemas" : { + "ActivityEventId" : { + "type" : "string", + "description" : "The unique identifier of an Activity event.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "ActivityStreamingResponse" : { + "type" : "object", + "description" : "An activity event or error that can be returned by the x activity streaming API.", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "event_type" : { + "type" : "string" + }, + "event_uuid" : { + "$ref" : "#/components/schemas/ActivityEventId" + }, + "filter" : { + "$ref" : "#/components/schemas/ActivitySubscriptionFilter" + }, + "payload" : { + "$ref" : "#/components/schemas/ActivityStreamingResponsePayload" + }, + "tag" : { + "type" : "string" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ActivityStreamingResponsePayload" : { + "oneOf" : [ + { + "$ref" : "#/components/schemas/ProfileUpdateActivityResponsePayload" + }, + { + "$ref" : "#/components/schemas/NewsActivityResponsePayload" + }, + { + "$ref" : "#/components/schemas/FollowActivityResponsePayload" + } + ], + "discriminator" : { + "propertyName" : "../event_type", + "mapping" : { + "follow.follow" : "#/components/schemas/FollowActivityResponsePayload", + "follow.unfollow" : "#/components/schemas/FollowActivityResponsePayload", + "news.new" : "#/components/schemas/NewsActivityResponsePayload", + "profile.update.banner_picture" : "#/components/schemas/ProfileUpdateActivityResponsePayload", + "profile.update.bio" : "#/components/schemas/ProfileUpdateActivityResponsePayload", + "profile.update.geo" : "#/components/schemas/ProfileUpdateActivityResponsePayload", + "profile.update.profile_picture" : "#/components/schemas/ProfileUpdateActivityResponsePayload", + "profile.update.screenname" : "#/components/schemas/ProfileUpdateActivityResponsePayload", + "profile.update.url" : "#/components/schemas/ProfileUpdateActivityResponsePayload", + "profile.update.verified_badge" : "#/components/schemas/ProfileUpdateActivityResponsePayload" + } + } + }, + "ActivitySubscription" : { + "type" : "object", + "description" : "An XActivity subscription.", + "required" : [ + "subscription_id", + "event_type", + "filter", + "created_at", + "updated_at" + ], + "properties" : { + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "event_type" : { + "type" : "string" + }, + "filter" : { + "$ref" : "#/components/schemas/ActivitySubscriptionFilter" + }, + "subscription_id" : { + "$ref" : "#/components/schemas/ActivitySubscriptionId" + }, + "tag" : { + "type" : "string" + }, + "updated_at" : { + "type" : "string", + "format" : "date-time" + }, + "webhook_id" : { + "$ref" : "#/components/schemas/WebhookConfigId" + } + } + }, + "ActivitySubscriptionCreateRequest" : { + "type" : "object", + "required" : [ + "event_type", + "filter" + ], + "properties" : { + "event_type" : { + "type" : "string", + "enum" : [ + "profile.update.bio", + "profile.update.profile_picture", + "profile.update.banner_picture", + "profile.update.screenname", + "profile.update.geo", + "profile.update.url", + "profile.update.verified_badge", + "news.new", + "follow.follow", + "follow.unfollow", + "ProfileBioUpdate", + "ProfilePictureUpdate", + "ProfileBannerPictureUpdate", + "ProfileScreennameUpdate", + "ProfileGeoUpdate", + "ProfileUrlUpdate", + "ProfileVerifiedBadgeUpdate", + "NewsNew", + "FollowFollow", + "FollowUnfollow" + ] + }, + "filter" : { + "$ref" : "#/components/schemas/ActivitySubscriptionFilter" + }, + "tag" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 200 + }, + "webhook_id" : { + "$ref" : "#/components/schemas/WebhookConfigId" + } + }, + "additionalProperties" : false + }, + "ActivitySubscriptionCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "subscription" : { + "$ref" : "#/components/schemas/ActivitySubscription" + }, + "total_subscriptions_for_instance_id" : { + "type" : "integer" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "total_subscriptions" : { + "type" : "integer", + "description" : "Number of active subscriptions.", + "format" : "int32" + } + } + } + } + }, + "ActivitySubscriptionDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "total_subscriptions" : { + "type" : "integer", + "description" : "Number of active subscriptions remaining.", + "format" : "int32" + } + } + } + } + }, + "ActivitySubscriptionFilter" : { + "type" : "object", + "description" : "An XAA subscription.", + "properties" : { + "keyword" : { + "$ref" : "#/components/schemas/Keyword" + }, + "user_id" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "additionalProperties" : false + }, + "ActivitySubscriptionGetResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/ActivitySubscription" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "total_subscriptions" : { + "type" : "integer", + "description" : "Number of active subscriptions.", + "format" : "int32" + } + } + } + } + }, + "ActivitySubscriptionId" : { + "type" : "string", + "description" : "The unique identifier of this subscription.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "ActivitySubscriptionUpdateRequest" : { + "type" : "object", + "properties" : { + "tag" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 200 + }, + "webhook_id" : { + "$ref" : "#/components/schemas/WebhookConfigId" + } + }, + "additionalProperties" : false + }, + "ActivitySubscriptionUpdateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "subscription" : { + "$ref" : "#/components/schemas/ActivitySubscription" + }, + "total_subscriptions" : { + "type" : "integer", + "description" : "Number of active subscriptions.", + "format" : "int32" + } + } + } + } + }, + "AddOrDeleteRulesRequest" : { + "oneOf" : [ + { + "$ref" : "#/components/schemas/AddRulesRequest" + }, + { + "$ref" : "#/components/schemas/DeleteRulesRequest" + } + ] + }, + "AddOrDeleteRulesResponse" : { + "type" : "object", + "description" : "A response from modifying user-specified stream filtering rules.", + "required" : [ + "meta" + ], + "properties" : { + "data" : { + "type" : "array", + "description" : "All user-specified stream filtering rules that were created.", + "items" : { + "$ref" : "#/components/schemas/Rule" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "$ref" : "#/components/schemas/RulesResponseMetadata" + } + } + }, + "AddRulesRequest" : { + "type" : "object", + "description" : "A request to add a user-specified stream filtering rule.", + "required" : [ + "add" + ], + "properties" : { + "add" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/RuleNoId" + } + } + } + }, + "Aggregate" : { + "type" : "integer", + "description" : "The sum of results returned in this response.", + "format" : "int32" + }, + "AllProjectClientApps" : { + "type" : "array", + "description" : "Client App Rule Counts for all applications in the project", + "items" : { + "$ref" : "#/components/schemas/AppRulesCount" + } + }, + "AllowDownloadStatus" : { + "type" : "object", + "properties" : { + "allow_download" : { + "type" : "boolean", + "example" : true + } + } + }, + "AltText" : { + "type" : "object", + "required" : [ + "text" + ], + "properties" : { + "text" : { + "type" : "string", + "description" : "Description of media ( <= 1000 characters )", + "maxLength" : 1000, + "example" : "A dancing cat" + } + } + }, + "Analytics" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "timestamped_metrics" : { + "type" : "array", + "title" : "Timestamped Metrics", + "description" : "Array containing metrics data along with the timestamps of their recording.", + "items" : { + "$ref" : "#/components/schemas/TimestampedMetrics" + } + } + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "AnimatedGif" : { + "allOf" : [ + { + "$ref" : "#/components/schemas/Media" + }, + { + "type" : "object", + "properties" : { + "preview_image_url" : { + "type" : "string", + "format" : "uri" + }, + "variants" : { + "$ref" : "#/components/schemas/Variants" + } + } + } + ] + }, + "AppRulesCount" : { + "type" : "object", + "description" : "A count of user-provided stream filtering rules at the client application level.", + "properties" : { + "client_app_id" : { + "$ref" : "#/components/schemas/ClientAppId" + }, + "rule_count" : { + "type" : "integer", + "description" : "Number of rules for client application", + "format" : "int32" + } + } + }, + "AudiencePolicy" : { + "type" : "object", + "properties" : { + "creator_subscriptions" : { + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ + "Any" + ] + } + }, + "x_subscriptions" : { + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ + "Any" + ] + } + } + } + }, + "BookmarkAddRequest" : { + "type" : "object", + "required" : [ + "tweet_id" + ], + "properties" : { + "tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + }, + "BookmarkFolderId" : { + "type" : "string", + "description" : "The unique identifier of this Bookmark folder.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "BookmarkFolderPostsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + } + } + } + } + }, + "BookmarkFoldersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/BookmarkFolderId" + }, + "name" : { + "type" : "string" + } + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + } + } + } + } + }, + "BookmarkMutationResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "bookmarked" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "CashtagEntity" : { + "allOf" : [ + { + "$ref" : "#/components/schemas/EntityIndicesInclusiveExclusive" + }, + { + "$ref" : "#/components/schemas/CashtagFields" + } + ] + }, + "CashtagFields" : { + "type" : "object", + "description" : "Represent the portion of text recognized as a Cashtag, and its start and end position within the text.", + "required" : [ + "tag" + ], + "properties" : { + "tag" : { + "type" : "string", + "example" : "TWTR" + } + } + }, + "ClientAppId" : { + "type" : "string", + "description" : "The ID of the client application", + "minLength" : 1, + "maxLength" : 19 + }, + "ClientAppUsage" : { + "type" : "object", + "description" : "Usage per client app", + "properties" : { + "client_app_id" : { + "type" : "string", + "description" : "The unique identifier for this project", + "format" : "^[0-9]{1,19}$" + }, + "usage" : { + "type" : "array", + "description" : "The usage value", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UsageFields" + } + }, + "usage_result_count" : { + "type" : "integer", + "description" : "The number of results returned", + "format" : "int32" + } + } + }, + "ClientDisconnectedProblem" : { + "description" : "Your client has gone away.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "ClientForbiddenProblem" : { + "description" : "A problem that indicates your client is forbidden from making this request.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "properties" : { + "reason" : { + "type" : "string", + "enum" : [ + "official-client-forbidden", + "client-not-enrolled" + ] + }, + "registration_url" : { + "type" : "string", + "format" : "uri" + } + } + } + ] + }, + "Community" : { + "type" : "object", + "description" : "A X Community is a curated group of Posts.", + "required" : [ + "id", + "name" + ], + "properties" : { + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "id" : { + "$ref" : "#/components/schemas/CommunityId" + }, + "name" : { + "type" : "string", + "description" : "The name of this Community." + } + } + }, + "CommunityId" : { + "type" : "string", + "description" : "The unique identifier of this Community.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "ComplianceJob" : { + "type" : "object", + "required" : [ + "id", + "type", + "created_at", + "upload_url", + "download_url", + "upload_expires_at", + "download_expires_at", + "status" + ], + "properties" : { + "created_at" : { + "$ref" : "#/components/schemas/CreatedAt" + }, + "download_expires_at" : { + "$ref" : "#/components/schemas/DownloadExpiration" + }, + "download_url" : { + "$ref" : "#/components/schemas/DownloadUrl" + }, + "id" : { + "$ref" : "#/components/schemas/JobId" + }, + "name" : { + "$ref" : "#/components/schemas/ComplianceJobName" + }, + "status" : { + "$ref" : "#/components/schemas/ComplianceJobStatus" + }, + "type" : { + "$ref" : "#/components/schemas/ComplianceJobType" + }, + "upload_expires_at" : { + "$ref" : "#/components/schemas/UploadExpiration" + }, + "upload_url" : { + "$ref" : "#/components/schemas/UploadUrl" + } + } + }, + "ComplianceJobName" : { + "type" : "string", + "description" : "User-provided name for a compliance job.", + "maxLength" : 64, + "example" : "my-job" + }, + "ComplianceJobStatus" : { + "type" : "string", + "description" : "Status of a compliance job.", + "enum" : [ + "created", + "in_progress", + "failed", + "complete", + "expired" + ] + }, + "ComplianceJobType" : { + "type" : "string", + "description" : "Type of compliance job to list.", + "enum" : [ + "tweets", + "users" + ] + }, + "ConflictProblem" : { + "description" : "You cannot create a new job if one is already in progress.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "Connection" : { + "type" : "object", + "required" : [ + "connected_at", + "endpoint_name" + ], + "properties" : { + "client_ip" : { + "type" : "string", + "description" : "The IP address of the connected client." + }, + "connected_at" : { + "type" : "string", + "description" : "The timestamp when the connection was established.", + "format" : "date-time" + }, + "disconnect_reason" : { + "type" : "string", + "description" : "The reason for disconnection, if the connection is inactive.", + "example" : "operator_disconnect" + }, + "disconnected_at" : { + "type" : "string", + "description" : "The timestamp when the connection was disconnected, if applicable.", + "format" : "date-time" + }, + "endpoint_name" : { + "type" : "string", + "description" : "The name of the streaming endpoint.", + "example" : "sample_stream" + } + } + }, + "ConnectionExceptionProblem" : { + "description" : "A problem that indicates something is wrong with the connection.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "properties" : { + "connection_issue" : { + "type" : "string", + "enum" : [ + "TooManyConnections", + "ProvisioningSubscription", + "RuleConfigurationIssue", + "RulesInvalidIssue" + ] + } + } + } + ] + }, + "ContentExpiration" : { + "type" : "object", + "required" : [ + "timestamp_sec" + ], + "properties" : { + "timestamp_sec" : { + "type" : "number", + "description" : "Expiration time for content as a Unix timestamp in seconds", + "format" : "long", + "example" : 1740787200 + } + } + }, + "ContextAnnotation" : { + "type" : "object", + "description" : "Annotation inferred from the Tweet text.", + "required" : [ + "domain", + "entity" + ], + "properties" : { + "domain" : { + "$ref" : "#/components/schemas/ContextAnnotationDomainFields" + }, + "entity" : { + "$ref" : "#/components/schemas/ContextAnnotationEntityFields" + } + } + }, + "ContextAnnotationDomainFields" : { + "type" : "object", + "description" : "Represents the data for the context annotation domain.", + "required" : [ + "id" + ], + "properties" : { + "description" : { + "type" : "string", + "description" : "Description of the context annotation domain." + }, + "id" : { + "type" : "string", + "description" : "The unique id for a context annotation domain.", + "pattern" : "^[0-9]{1,19}$" + }, + "name" : { + "type" : "string", + "description" : "Name of the context annotation domain." + } + } + }, + "ContextAnnotationEntityFields" : { + "type" : "object", + "description" : "Represents the data for the context annotation entity.", + "required" : [ + "id" + ], + "properties" : { + "description" : { + "type" : "string", + "description" : "Description of the context annotation entity." + }, + "id" : { + "type" : "string", + "description" : "The unique id for a context annotation entity.", + "pattern" : "^[0-9]{1,19}$" + }, + "name" : { + "type" : "string", + "description" : "Name of the context annotation entity." + } + } + }, + "CountryCode" : { + "type" : "string", + "description" : "A two-letter ISO 3166-1 alpha-2 country code.", + "pattern" : "^[A-Z]{2}$", + "example" : "US" + }, + "CreateAttachmentsMessageRequest" : { + "type" : "object", + "required" : [ + "attachments" + ], + "properties" : { + "attachments" : { + "$ref" : "#/components/schemas/DmAttachments" + }, + "text" : { + "type" : "string", + "description" : "Text of the message.", + "minLength" : 1 + } + } + }, + "CreateComplianceJobRequest" : { + "type" : "object", + "description" : "A request to create a new batch compliance job.", + "required" : [ + "type" + ], + "properties" : { + "name" : { + "$ref" : "#/components/schemas/ComplianceJobName" + }, + "resumable" : { + "type" : "boolean", + "description" : "If true, this endpoint will return a pre-signed URL with resumable uploads enabled." + }, + "type" : { + "type" : "string", + "description" : "Type of compliance job to list.", + "enum" : [ + "tweets", + "users" + ] + } + } + }, + "CreateComplianceJobResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/ComplianceJob" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "CreateDmConversationRequest" : { + "type" : "object", + "required" : [ + "conversation_type", + "participant_ids", + "message" + ], + "properties" : { + "conversation_type" : { + "type" : "string", + "description" : "The conversation type that is being created.", + "enum" : [ + "Group" + ] + }, + "message" : { + "$ref" : "#/components/schemas/CreateMessageRequest" + }, + "participant_ids" : { + "$ref" : "#/components/schemas/DmParticipants" + } + }, + "additionalProperties" : false + }, + "CreateDmEventResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "dm_conversation_id", + "dm_event_id" + ], + "properties" : { + "dm_conversation_id" : { + "$ref" : "#/components/schemas/DmConversationId" + }, + "dm_event_id" : { + "$ref" : "#/components/schemas/DmEventId" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "CreateMessageRequest" : { + "anyOf" : [ + { + "$ref" : "#/components/schemas/CreateTextMessageRequest" + }, + { + "$ref" : "#/components/schemas/CreateAttachmentsMessageRequest" + } + ] + }, + "CreateNoteRequest" : { + "type" : "object", + "title" : "Note", + "required" : [ + "test_mode", + "post_id", + "info" + ], + "properties" : { + "info" : { + "$ref" : "#/components/schemas/NoteInfo" + }, + "post_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "test_mode" : { + "type" : "boolean", + "description" : "If true, the note being submitted is only for testing the capability of the bot, and won't be publicly visible. If false, the note being submitted will be a new proposed note on the product." + } + }, + "additionalProperties" : false + }, + "CreateNoteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/NoteId" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "CreateTextMessageRequest" : { + "type" : "object", + "required" : [ + "text" + ], + "properties" : { + "attachments" : { + "$ref" : "#/components/schemas/DmAttachments" + }, + "text" : { + "type" : "string", + "description" : "Text of the message.", + "minLength" : 1 + } + } + }, + "CreatedAt" : { + "type" : "string", + "description" : "Creation time of the compliance job.", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "DeleteDmResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "DeleteNoteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "deleted" + ], + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "DeleteRulesRequest" : { + "type" : "object", + "description" : "A response from deleting user-specified stream filtering rules.", + "required" : [ + "delete" + ], + "properties" : { + "delete" : { + "type" : "object", + "description" : "IDs and values of all deleted user-specified stream filtering rules.", + "properties" : { + "ids" : { + "type" : "array", + "description" : "IDs of all deleted user-specified stream filtering rules.", + "items" : { + "$ref" : "#/components/schemas/RuleId" + } + }, + "values" : { + "type" : "array", + "description" : "Values of all deleted user-specified stream filtering rules.", + "items" : { + "$ref" : "#/components/schemas/RuleValue" + } + } + } + } + } + }, + "DisallowedResourceProblem" : { + "description" : "A problem that indicates that the resource requested violates the precepts of this API.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "required" : [ + "resource_id", + "resource_type", + "section" + ], + "properties" : { + "resource_id" : { + "type" : "string" + }, + "resource_type" : { + "type" : "string", + "enum" : [ + "user", + "tweet", + "media", + "list", + "space" + ] + }, + "section" : { + "type" : "string", + "enum" : [ + "data", + "includes" + ] + } + } + } + ] + }, + "DisplayTextRange" : { + "type" : "array", + "description" : "Represent a boundary range (start and end zero-based indices) for the portion of text that is displayed for a post. `start` must be smaller than `end`. The start index is inclusive, the end index is exclusive.", + "minItems" : 2, + "maxItems" : 2, + "items" : { + "type" : "integer", + "minimum" : 0 + } + }, + "DmAttachments" : { + "type" : "array", + "description" : "Attachments to a DM Event.", + "items" : { + "$ref" : "#/components/schemas/DmMediaAttachment" + } + }, + "DmConversationId" : { + "type" : "string", + "description" : "Unique identifier of a DM conversation. This can either be a numeric string, or a pair of numeric strings separated by a '-' character in the case of one-on-one DM Conversations.", + "pattern" : "^([0-9]{1,19}-[0-9]{1,19}|[0-9]{15,19})$", + "example" : "123123123-456456456" + }, + "DmEvent" : { + "type" : "object", + "required" : [ + "id", + "event_type" + ], + "properties" : { + "attachments" : { + "type" : "object", + "description" : "Specifies the type of attachments (if any) present in this DM.", + "properties" : { + "card_ids" : { + "type" : "array", + "description" : "A list of card IDs (if cards are attached).", + "minItems" : 1, + "items" : { + "type" : "string" + } + }, + "media_keys" : { + "type" : "array", + "description" : "A list of Media Keys for each one of the media attachments (if media are attached).", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/MediaKey" + } + } + } + }, + "cashtags" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/CashtagEntity" + } + }, + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "dm_conversation_id" : { + "$ref" : "#/components/schemas/DmConversationId" + }, + "event_type" : { + "type" : "string", + "example" : "MessageCreate" + }, + "hashtags" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/HashtagEntity" + } + }, + "id" : { + "$ref" : "#/components/schemas/DmEventId" + }, + "mentions" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/MentionEntity" + } + }, + "participant_ids" : { + "type" : "array", + "description" : "A list of participants for a ParticipantsJoin or ParticipantsLeave event_type.", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "referenced_tweets" : { + "type" : "array", + "description" : "A list of Posts this DM refers to.", + "minItems" : 1, + "items" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + }, + "sender_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "text" : { + "type" : "string" + }, + "urls" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UrlEntityDm" + } + } + } + }, + "DmEventId" : { + "type" : "string", + "description" : "Unique identifier of a DM Event.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "DmMediaAttachment" : { + "type" : "object", + "required" : [ + "media_id" + ], + "properties" : { + "media_id" : { + "$ref" : "#/components/schemas/MediaId" + } + } + }, + "DmParticipants" : { + "type" : "array", + "description" : "Participants for the DM Conversation.", + "minItems" : 2, + "maxItems" : 49, + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "DomainRestrictions" : { + "type" : "object", + "required" : [ + "whitelist" + ], + "properties" : { + "whitelist" : { + "type" : "array", + "description" : "List of whitelisted domains", + "items" : { + "type" : "string" + } + } + } + }, + "DownloadExpiration" : { + "type" : "string", + "description" : "Expiration time of the download URL.", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "DownloadUrl" : { + "type" : "string", + "description" : "URL from which the user will retrieve their compliance results.", + "format" : "uri" + }, + "DuplicateRuleProblem" : { + "description" : "The rule you have submitted is a duplicate.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "properties" : { + "id" : { + "type" : "string" + }, + "value" : { + "type" : "string" + } + } + } + ] + }, + "End" : { + "type" : "string", + "description" : "The end time of the bucket.", + "format" : "date-time" + }, + "Engagement" : { + "type" : "object", + "description" : "An Engagement Api Response.", + "properties" : { + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "type" : "object", + "properties" : { + "error" : { + "type" : "string" + }, + "tweets" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + } + }, + "measurement" : { + "type" : "object", + "properties" : { + "metrics_time_series" : { + "type" : "array", + "minItems" : 1, + "items" : { + "type" : "object", + "properties" : { + "tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "value" : { + "type" : "object", + "properties" : { + "metric_values" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "metric_type" : { + "type" : "string" + }, + "metric_value" : { + "type" : "number" + } + } + } + }, + "timestamp" : { + "type" : "object", + "properties" : { + "iso8601_time" : { + "type" : "string" + } + } + } + } + } + } + } + }, + "metrics_total" : { + "type" : "array", + "minItems" : 1, + "items" : { + "type" : "object", + "properties" : { + "tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "value" : { + "type" : "array", + "minItems" : 1, + "items" : { + "type" : "object", + "properties" : { + "metric_type" : { + "type" : "string" + }, + "metric_value" : { + "type" : "number" + } + } + } + } + } + } + } + } + } + } + }, + "EntityIndicesInclusiveExclusive" : { + "type" : "object", + "description" : "Represent a boundary range (start and end index) for a recognized entity (for example a hashtag or a mention). `start` must be smaller than `end`. The start index is inclusive, the end index is exclusive.", + "required" : [ + "start", + "end" + ], + "properties" : { + "end" : { + "type" : "integer", + "description" : "Index (zero-based) at which position this entity ends. The index is exclusive.", + "minimum" : 0, + "example" : 61 + }, + "start" : { + "type" : "integer", + "description" : "Index (zero-based) at which position this entity starts. The index is inclusive.", + "minimum" : 0, + "example" : 50 + } + } + }, + "EntityIndicesInclusiveInclusive" : { + "type" : "object", + "description" : "Represent a boundary range (start and end index) for a recognized entity (for example a hashtag or a mention). `start` must be smaller than `end`. The start index is inclusive, the end index is inclusive.", + "required" : [ + "start", + "end" + ], + "properties" : { + "end" : { + "type" : "integer", + "description" : "Index (zero-based) at which position this entity ends. The index is inclusive.", + "minimum" : 0, + "example" : 61 + }, + "start" : { + "type" : "integer", + "description" : "Index (zero-based) at which position this entity starts. The index is inclusive.", + "minimum" : 0, + "example" : 50 + } + } + }, + "Error" : { + "type" : "object", + "required" : [ + "code", + "message" + ], + "properties" : { + "code" : { + "type" : "integer", + "format" : "int32" + }, + "message" : { + "type" : "string" + } + } + }, + "EvaluateNoteRequest" : { + "type" : "object", + "required" : [ + "post_id", + "note_text" + ], + "properties" : { + "note_text" : { + "type" : "string", + "description" : "Text for the community note." + }, + "post_id" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "additionalProperties" : false + }, + "EvaluateNoteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "claim_opinion_score" : { + "type" : "number", + "description" : "Claim opinion model score for the note.", + "format" : "double" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Expansions" : { + "type" : "object", + "properties" : { + "media" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Media" + } + }, + "places" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Place" + } + }, + "polls" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Poll" + } + }, + "topics" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Topic" + } + }, + "tweets" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "users" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + } + } + }, + "FieldUnauthorizedProblem" : { + "description" : "A problem that indicates that you are not allowed to see a particular field on a Tweet, User, etc.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "required" : [ + "resource_type", + "field", + "section" + ], + "properties" : { + "field" : { + "type" : "string" + }, + "resource_type" : { + "type" : "string", + "enum" : [ + "user", + "tweet", + "media", + "list", + "space" + ] + }, + "section" : { + "type" : "string", + "enum" : [ + "data", + "includes" + ] + } + } + } + ] + }, + "FilteredStreamingTweetResponse" : { + "type" : "object", + "description" : "A Tweet or error that can be returned by the streaming Tweet API. The values returned with a successful streamed Tweet includes the user provided rules that the Tweet matched.", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "matching_rules" : { + "type" : "array", + "description" : "The list of rules which matched the Tweet", + "items" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/RuleId" + }, + "tag" : { + "$ref" : "#/components/schemas/RuleTag" + } + } + } + } + } + }, + "FollowActivityResponsePayload" : { + "type" : "object", + "properties" : { + "source" : { + "$ref" : "#/components/schemas/User" + }, + "target" : { + "$ref" : "#/components/schemas/User" + } + }, + "additionalProperties" : false + }, + "FoundMediaOrigin" : { + "type" : "object", + "required" : [ + "provider", + "id" + ], + "properties" : { + "id" : { + "type" : "string", + "description" : "Unique Identifier of media within provider ( <= 24 characters ))", + "example" : "u5BzatR15TZ04" + }, + "provider" : { + "type" : "string", + "description" : "The media provider (e.g., 'giphy') that sourced the media ( <= 8 Characters )", + "example" : "giphy" + } + } + }, + "FullTextEntities" : { + "type" : "object", + "properties" : { + "annotations" : { + "type" : "array", + "minItems" : 1, + "items" : { + "description" : "Annotation for entities based on the Tweet text.", + "allOf" : [ + { + "$ref" : "#/components/schemas/EntityIndicesInclusiveInclusive" + }, + { + "type" : "object", + "description" : "Represents the data for the annotation.", + "properties" : { + "normalized_text" : { + "type" : "string", + "description" : "Text used to determine annotation.", + "example" : "Barack Obama" + }, + "probability" : { + "type" : "number", + "description" : "Confidence factor for annotation type.", + "minimum" : 0, + "maximum" : 1, + "format" : "double" + }, + "type" : { + "type" : "string", + "description" : "Annotation type.", + "example" : "Person" + } + } + } + ] + } + }, + "cashtags" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/CashtagEntity" + } + }, + "hashtags" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/HashtagEntity" + } + }, + "mentions" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/MentionEntity" + } + }, + "urls" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UrlEntity" + } + } + } + }, + "GenericProblem" : { + "description" : "A generic problem with no additional information beyond that provided by the HTTP status code.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "Geo" : { + "type" : "object", + "required" : [ + "type", + "bbox", + "properties" + ], + "properties" : { + "bbox" : { + "type" : "array", + "minItems" : 4, + "maxItems" : 4, + "items" : { + "type" : "number", + "minimum" : -180, + "maximum" : 180, + "format" : "double" + }, + "example" : [ + -105.193475, + 39.60973, + -105.053164, + 39.761974 + ] + }, + "geometry" : { + "$ref" : "#/components/schemas/Point" + }, + "properties" : { + "type" : "object" + }, + "type" : { + "type" : "string", + "enum" : [ + "Feature" + ] + } + } + }, + "GeoRestrictions" : { + "oneOf" : [ + { + "type" : "object", + "required" : [ + "whitelisted_country_codes", + "blacklisted_country_codes" + ], + "properties" : { + "blacklisted_country_codes" : { + "type" : "array", + "description" : "List of blacklisted country codes", + "minItems" : 0, + "maxItems" : 0, + "items" : { + "type" : "string", + "description" : "Country code in ISO 3166-1 alpha-2 format", + "pattern" : "^[a-zA-Z]{2}$", + "example" : "us" + } + }, + "whitelisted_country_codes" : { + "type" : "array", + "description" : "List of whitelisted country codes", + "minItems" : 1, + "items" : { + "type" : "string", + "description" : "Country code in ISO 3166-1 alpha-2 format", + "pattern" : "^[a-zA-Z]{2}$", + "example" : "us" + } + } + } + }, + { + "type" : "object", + "required" : [ + "whitelisted_country_codes", + "blacklisted_country_codes" + ], + "properties" : { + "blacklisted_country_codes" : { + "type" : "array", + "description" : "List of blacklisted country codes", + "minItems" : 1, + "items" : { + "type" : "string", + "description" : "Country code in ISO 3166-1 alpha-2 format", + "pattern" : "^[a-zA-Z]{2}$", + "example" : "us" + } + }, + "whitelisted_country_codes" : { + "type" : "array", + "description" : "List of whitelisted country codes", + "minItems" : 0, + "maxItems" : 0, + "items" : { + "type" : "string", + "description" : "Country code in ISO 3166-1 alpha-2 format", + "pattern" : "^[a-zA-Z]{2}$", + "example" : "us" + } + } + } + } + ] + }, + "Get2CommunitiesIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Community" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2CommunitiesSearchResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Community" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + } + } + } + } + }, + "Get2ComplianceJobsIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/ComplianceJob" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2ComplianceJobsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/ComplianceJob" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2ConnectionsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Connection" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2DmConversationsIdDmEventsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/DmEvent" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2DmConversationsWithParticipantIdDmEventsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/DmEvent" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2DmEventsEventIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/DmEvent" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2DmEventsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/DmEvent" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2FdxAccountsAccountidContactResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/PlaidAccountContact" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2FdxAccountsAccountidPayment-networksResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/PlaidAccountPaymentNetwork" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2FdxAccountsAccountidResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/PlaidAccount" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2FdxAccountsAccountidTransactionsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/PlaidAccountTransaction" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2FdxCustomersCurrentResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/PlaidCustomer" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2Insights28hrResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Engagement" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2InsightsHistoricalResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Engagement" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2LikesFirehoseStreamResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/LikeWithTweetAuthor" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2LikesSample10StreamResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/LikeWithTweetAuthor" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2ListsIdFollowersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2ListsIdMembersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2ListsIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/List" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2ListsIdTweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2MediaAnalyticsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/MediaAnalytics" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2MediaMediaKeyResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Media" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2MediaResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Media" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2NewsIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/News" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2NewsSearchResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/News" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2NotesSearchNotesWrittenResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Note" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2NotesSearchPostsEligibleForNotesResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2SpacesByCreatorIdsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Space" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2SpacesIdBuyersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2SpacesIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Space" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2SpacesIdTweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2SpacesResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Space" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2SpacesSearchResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Space" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TrendsByWoeidWoeidResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Trend" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2TweetsAnalyticsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Analytics" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2TweetsCountsAllResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/SearchCount" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "total_tweet_count" : { + "$ref" : "#/components/schemas/Aggregate" + } + } + } + } + }, + "Get2TweetsCountsRecentResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/SearchCount" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "total_tweet_count" : { + "$ref" : "#/components/schemas/Aggregate" + } + } + } + } + }, + "Get2TweetsFirehoseStreamLangEnResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsFirehoseStreamLangJaResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsFirehoseStreamLangKoResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsFirehoseStreamLangPtResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsFirehoseStreamResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsIdLikingUsersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TweetsIdQuoteTweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TweetsIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsIdRetweetedByResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TweetsIdRetweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsSample10StreamResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsSampleStreamResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsSearchAllResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TweetsSearchRecentResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2TweetsSearchStreamResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2TweetsSearchStreamRulesCountsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/RulesCount" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2UsageTweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Usage" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2UsersByResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2UsersByUsernameUsernameResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/User" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2UsersIdBlockingResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdBookmarksResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdFollowedListsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/List" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdFollowersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdFollowingResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdLikedTweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdListMembershipsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/List" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdMentionsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdMutingResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdOwnedListsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/List" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdPinnedListsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/List" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/User" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2UsersIdTimelinesReverseChronologicalResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersIdTweetsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "newest_id" : { + "$ref" : "#/components/schemas/NewestId" + }, + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "oldest_id" : { + "$ref" : "#/components/schemas/OldestId" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersMeResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/User" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2UsersPersonalizedTrendsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/PersonalizedTrend" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Get2UsersRepostsOfMeResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Tweet" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + }, + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "Get2UsersResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "Get2UsersSearchResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/User" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + }, + "meta" : { + "type" : "object", + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "previous_token" : { + "$ref" : "#/components/schemas/PreviousToken" + } + } + } + } + }, + "Get2WebhooksResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/WebhookConfig" + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "meta" : { + "type" : "object", + "properties" : { + "result_count" : { + "$ref" : "#/components/schemas/ResultCount" + } + } + } + } + }, + "HashtagEntity" : { + "allOf" : [ + { + "$ref" : "#/components/schemas/EntityIndicesInclusiveExclusive" + }, + { + "$ref" : "#/components/schemas/HashtagFields" + } + ] + }, + "HashtagFields" : { + "type" : "object", + "description" : "Represent the portion of text recognized as a Hashtag, and its start and end position within the text.", + "required" : [ + "tag" + ], + "properties" : { + "tag" : { + "type" : "string", + "description" : "The text of the Hashtag.", + "example" : "MondayMotivation" + } + } + }, + "HttpStatusCode" : { + "type" : "integer", + "description" : "HTTP Status Code.", + "minimum" : 100, + "maximum" : 599 + }, + "InvalidRequestProblem" : { + "description" : "A problem that indicates this request is invalid.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "properties" : { + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "type" : "object", + "properties" : { + "message" : { + "type" : "string" + }, + "parameters" : { + "type" : "object", + "additionalProperties" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + } + } + } + } + } + ] + }, + "InvalidRuleProblem" : { + "description" : "The rule you have submitted is invalid.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "JobId" : { + "type" : "string", + "description" : "Compliance Job ID.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1372966999991541762" + }, + "Keyword" : { + "type" : "string", + "description" : "A keyword to filter on.", + "minLength" : 1, + "maxLength" : 150, + "example" : "The President" + }, + "KillAllConnectionsResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "killed_connections" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "LikeComplianceSchema" : { + "type" : "object", + "required" : [ + "delete" + ], + "properties" : { + "delete" : { + "$ref" : "#/components/schemas/UnlikeComplianceSchema" + } + } + }, + "LikeId" : { + "type" : "string", + "description" : "The unique identifier of this Like.", + "pattern" : "^[A-Za-z0-9_]{1,40}$", + "example" : "8ba4f34e6235d905a46bac021d98e923" + }, + "LikeWithTweetAuthor" : { + "type" : "object", + "description" : "A Like event, with the tweet author user and the tweet being liked", + "properties" : { + "created_at" : { + "type" : "string", + "description" : "Creation time of the Tweet.", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "id" : { + "$ref" : "#/components/schemas/LikeId" + }, + "liked_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "timestamp_ms" : { + "type" : "integer", + "description" : "Timestamp in milliseconds of creation.", + "format" : "int32" + }, + "tweet_author_id" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "LikesComplianceStreamResponse" : { + "description" : "Likes compliance stream events.", + "oneOf" : [ + { + "type" : "object", + "description" : "Compliance event.", + "required" : [ + "data" + ], + "properties" : { + "data" : { + "$ref" : "#/components/schemas/LikeComplianceSchema" + } + } + }, + { + "type" : "object", + "required" : [ + "errors" + ], + "properties" : { + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + ] + }, + "List" : { + "type" : "object", + "description" : "A X List is a curated group of accounts.", + "required" : [ + "id", + "name" + ], + "properties" : { + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "description" : { + "type" : "string" + }, + "follower_count" : { + "type" : "integer" + }, + "id" : { + "$ref" : "#/components/schemas/ListId" + }, + "member_count" : { + "type" : "integer" + }, + "name" : { + "type" : "string", + "description" : "The name of this List." + }, + "owner_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "private" : { + "type" : "boolean" + } + } + }, + "ListAddUserRequest" : { + "type" : "object", + "required" : [ + "user_id" + ], + "properties" : { + "user_id" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "ListCreateRequest" : { + "type" : "object", + "required" : [ + "name" + ], + "properties" : { + "description" : { + "type" : "string", + "minLength" : 0, + "maxLength" : 100 + }, + "name" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 25 + }, + "private" : { + "type" : "boolean", + "default" : false + } + } + }, + "ListCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "description" : "A X List is a curated group of accounts.", + "required" : [ + "id", + "name" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/ListId" + }, + "name" : { + "type" : "string", + "description" : "The name of this List." + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ListDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ListFollowedRequest" : { + "type" : "object", + "required" : [ + "list_id" + ], + "properties" : { + "list_id" : { + "$ref" : "#/components/schemas/ListId" + } + } + }, + "ListFollowedResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "following" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ListId" : { + "type" : "string", + "description" : "The unique identifier of this List.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "ListMutateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "is_member" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ListPinnedRequest" : { + "type" : "object", + "required" : [ + "list_id" + ], + "properties" : { + "list_id" : { + "$ref" : "#/components/schemas/ListId" + } + } + }, + "ListPinnedResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "pinned" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ListUnpinResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "pinned" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ListUpdateRequest" : { + "type" : "object", + "properties" : { + "description" : { + "type" : "string", + "minLength" : 0, + "maxLength" : 100 + }, + "name" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 25 + }, + "private" : { + "type" : "boolean" + } + } + }, + "ListUpdateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "updated" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "ManagementInfo" : { + "type" : "object", + "required" : [ + "managed" + ], + "properties" : { + "managed" : { + "type" : "boolean", + "description" : "Indicates if the media is managed by Media Studio", + "example" : false + } + } + }, + "Media" : { + "type" : "object", + "required" : [ + "type" + ], + "properties" : { + "height" : { + "$ref" : "#/components/schemas/MediaHeight" + }, + "media_key" : { + "$ref" : "#/components/schemas/MediaKey" + }, + "type" : { + "type" : "string" + }, + "width" : { + "$ref" : "#/components/schemas/MediaWidth" + } + }, + "discriminator" : { + "propertyName" : "type", + "mapping" : { + "animated_gif" : "#/components/schemas/AnimatedGif", + "photo" : "#/components/schemas/Photo", + "video" : "#/components/schemas/Video" + } + } + }, + "MediaAnalytics" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "media_key" : { + "$ref" : "#/components/schemas/MediaKey" + }, + "timestamped_metrics" : { + "type" : "array", + "title" : "Timestamped Metrics", + "description" : "Array containing metrics data along with the timestamps of their recording.", + "items" : { + "$ref" : "#/components/schemas/MediaTimestampedMetrics" + } + } + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "MediaCategory" : { + "type" : "string", + "description" : "A string enum value which identifies a media use-case. This identifier is used to enforce use-case specific constraints (e.g. file size, video duration) and enable advanced features.", + "enum" : [ + "amplify_video", + "tweet_gif", + "tweet_image", + "tweet_video", + "dm_gif", + "dm_image", + "dm_video", + "subtitles" + ], + "example" : "tweet_video" + }, + "MediaCategoryOneShot" : { + "type" : "string", + "description" : "A string enum value which identifies a media use-case. This identifier is used to enforce use-case specific constraints (e.g. file size) and enable advanced features.", + "enum" : [ + "tweet_image", + "dm_image", + "subtitles" + ], + "example" : "tweet_image" + }, + "MediaCategorySubtitles" : { + "type" : "string", + "description" : "The media category of uploaded media to which subtitles should be added/deleted", + "enum" : [ + "AmplifyVideo", + "TweetVideo" + ], + "example" : "TweetVideo" + }, + "MediaHeight" : { + "type" : "integer", + "description" : "The height of the media in pixels.", + "minimum" : 0 + }, + "MediaId" : { + "type" : "string", + "description" : "The unique identifier of this Media.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "MediaKey" : { + "type" : "string", + "description" : "The Media Key identifier for this attachment.", + "pattern" : "^([0-9]+)_([0-9]+)$" + }, + "MediaMetrics" : { + "type" : "object", + "properties" : { + "cta_url_clicks" : { + "type" : "integer", + "title" : "CTA URL Clicks", + "description" : "Tracks the number of clicks on a call-to-action URL" + }, + "cta_watch_clicks" : { + "type" : "integer", + "title" : "CTA Watch Clicks", + "description" : "Tracks the number of clicks to watch a video or media content" + }, + "play_from_tap" : { + "type" : "integer", + "title" : "Play From Tap", + "description" : "Tracks the number of times a video or media is played from a user tap" + }, + "playback25" : { + "type" : "integer", + "title" : "Playback 25%", + "description" : "Tracks the number of times a video reaches 25% of its duration" + }, + "playback50" : { + "type" : "integer", + "title" : "Playback 50%", + "description" : "Tracks the number of times a video reaches 50% of its duration" + }, + "playback75" : { + "type" : "integer", + "title" : "Playback 75%", + "description" : "Tracks the number of times a video reaches 75% of its duration" + }, + "playback_complete" : { + "type" : "integer", + "title" : "Playback Complete", + "description" : "Tracks the number of times a video is played to completion" + }, + "playback_start" : { + "type" : "integer", + "title" : "Playback Start", + "description" : "Tracks the number of times a video playback is initiated" + }, + "video_views" : { + "type" : "integer", + "title" : "Video Views", + "description" : "Tracks the number of times a video is viewed" + }, + "watch_time_ms" : { + "type" : "integer", + "title" : "Watch Time (ms)", + "description" : "Tracks the total time spent watching a video, measured in milliseconds" + } + } + }, + "MediaPayloadBinary" : { + "type" : "string", + "description" : "The file to upload.", + "format" : "binary" + }, + "MediaPayloadByte" : { + "type" : "string", + "description" : "The file to upload.", + "format" : "byte" + }, + "MediaSegments" : { + "oneOf" : [ + { + "type" : "integer", + "description" : "An integer value representing the media upload segment.", + "minimum" : 0, + "maximum" : 999, + "format" : "int32" + }, + { + "type" : "string", + "description" : "An integer value representing the media upload segment.", + "pattern" : "^[0-9]{1,3}$", + "format" : "integer" + } + ] + }, + "MediaTimestampedMetrics" : { + "type" : "object", + "properties" : { + "metrics" : { + "$ref" : "#/components/schemas/MediaMetrics" + }, + "timestamp" : { + "type" : "string", + "title" : "Timestamp", + "description" : "ISO8601 Time", + "example" : "2025-03-17T06:30:00Z" + } + } + }, + "MediaUploadAppendRequest" : { + "anyOf" : [ + { + "type" : "object", + "required" : [ + "media", + "segment_index" + ], + "properties" : { + "media" : { + "$ref" : "#/components/schemas/MediaPayloadBinary" + }, + "segment_index" : { + "$ref" : "#/components/schemas/MediaSegments" + } + } + }, + { + "type" : "object", + "required" : [ + "media", + "segment_index" + ], + "properties" : { + "media" : { + "$ref" : "#/components/schemas/MediaPayloadByte" + }, + "segment_index" : { + "$ref" : "#/components/schemas/MediaSegments" + } + } + } + ] + }, + "MediaUploadAppendResponse" : { + "type" : "object", + "description" : "A response from getting a media upload request status.", + "required" : [ + "meta" + ], + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "expires_at" : { + "type" : "integer", + "description" : "Unix epoch time in seconds after when the upload session expires.", + "format" : "int64" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "MediaUploadConfigRequest" : { + "type" : "object", + "properties" : { + "additional_owners" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "media_category" : { + "$ref" : "#/components/schemas/MediaCategory" + }, + "media_type" : { + "type" : "string", + "description" : "The type of media.", + "enum" : [ + "video/mp4", + "video/webm", + "video/mp2t", + "video/quicktime", + "text/srt", + "text/vtt", + "image/jpeg", + "image/gif", + "image/bmp", + "image/png", + "image/webp", + "image/pjpeg", + "image/tiff", + "model/gltf-binary", + "model/vnd.usdz+zip" + ], + "example" : "video/mp4" + }, + "shared" : { + "type" : "boolean", + "description" : "Whether this media is shared or not." + }, + "total_bytes" : { + "type" : "integer", + "description" : "The total size of the media upload in bytes.", + "minimum" : 0, + "maximum" : 17179869184 + } + }, + "additionalProperties" : false + }, + "MediaUploadRequestOneShot" : { + "type" : "object", + "required" : [ + "media", + "media_category" + ], + "properties" : { + "additional_owners" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "media" : { + "anyOf" : [ + { + "$ref" : "#/components/schemas/MediaPayloadBinary" + }, + { + "$ref" : "#/components/schemas/MediaPayloadByte" + } + ] + }, + "media_category" : { + "$ref" : "#/components/schemas/MediaCategoryOneShot" + }, + "media_type" : { + "type" : "string", + "description" : "The type of image or subtitle.", + "enum" : [ + "text/srt", + "text/vtt", + "image/jpeg", + "image/bmp", + "image/png", + "image/webp", + "image/pjpeg", + "image/tiff" + ], + "example" : "image/png" + }, + "shared" : { + "type" : "boolean", + "description" : "Whether this media is shared or not.", + "default" : false + } + }, + "additionalProperties" : false + }, + "MediaUploadResponse" : { + "type" : "object", + "description" : "A response from getting a media upload request status.", + "required" : [ + "meta" + ], + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "id", + "media_key" + ], + "properties" : { + "expires_after_secs" : { + "type" : "integer", + "description" : "Number of seconds after which upload session expires.", + "format" : "int32" + }, + "id" : { + "$ref" : "#/components/schemas/MediaId" + }, + "media_key" : { + "$ref" : "#/components/schemas/MediaKey" + }, + "processing_info" : { + "$ref" : "#/components/schemas/ProcessingInfo" + }, + "size" : { + "type" : "integer", + "description" : "Size of the upload", + "format" : "int32" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "MediaWidth" : { + "type" : "integer", + "description" : "The width of the media in pixels.", + "minimum" : 0 + }, + "MentionEntity" : { + "allOf" : [ + { + "$ref" : "#/components/schemas/EntityIndicesInclusiveExclusive" + }, + { + "$ref" : "#/components/schemas/MentionFields" + } + ] + }, + "MentionFields" : { + "type" : "object", + "description" : "Represent the portion of text recognized as a User mention, and its start and end position within the text.", + "required" : [ + "username" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/UserId" + }, + "username" : { + "$ref" : "#/components/schemas/UserName" + } + } + }, + "MetadataCreateRequest" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/MediaId" + }, + "metadata" : { + "type" : "object", + "properties" : { + "allow_download_status" : { + "$ref" : "#/components/schemas/AllowDownloadStatus" + }, + "alt_text" : { + "$ref" : "#/components/schemas/AltText" + }, + "audience_policy" : { + "$ref" : "#/components/schemas/AudiencePolicy" + }, + "content_expiration" : { + "$ref" : "#/components/schemas/ContentExpiration" + }, + "domain_restrictions" : { + "$ref" : "#/components/schemas/DomainRestrictions" + }, + "found_media_origin" : { + "$ref" : "#/components/schemas/FoundMediaOrigin" + }, + "geo_restrictions" : { + "$ref" : "#/components/schemas/GeoRestrictions" + }, + "management_info" : { + "$ref" : "#/components/schemas/ManagementInfo" + }, + "preview_image" : { + "$ref" : "#/components/schemas/PreviewImage" + }, + "sensitive_media_warning" : { + "$ref" : "#/components/schemas/SensitiveMediaWarning" + }, + "shared_info" : { + "$ref" : "#/components/schemas/SharedInfo" + }, + "sticker_info" : { + "$ref" : "#/components/schemas/StickerInfo" + }, + "upload_source" : { + "$ref" : "#/components/schemas/UploadSource" + } + } + } + } + }, + "MetadataCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "associated_metadata" : { + "type" : "object", + "properties" : { + "allow_download_status" : { + "$ref" : "#/components/schemas/AllowDownloadStatus" + }, + "alt_text" : { + "$ref" : "#/components/schemas/AltText" + }, + "audience_policy" : { + "$ref" : "#/components/schemas/AudiencePolicy" + }, + "content_expiration" : { + "$ref" : "#/components/schemas/ContentExpiration" + }, + "domain_restrictions" : { + "$ref" : "#/components/schemas/DomainRestrictions" + }, + "found_media_origin" : { + "$ref" : "#/components/schemas/FoundMediaOrigin" + }, + "geo_restrictions" : { + "$ref" : "#/components/schemas/GeoRestrictions" + }, + "management_info" : { + "$ref" : "#/components/schemas/ManagementInfo" + }, + "preview_image" : { + "$ref" : "#/components/schemas/PreviewImage" + }, + "sensitive_media_warning" : { + "$ref" : "#/components/schemas/SensitiveMediaWarning" + }, + "shared_info" : { + "$ref" : "#/components/schemas/SharedInfo" + }, + "sticker_info" : { + "$ref" : "#/components/schemas/StickerInfo" + }, + "upload_source" : { + "$ref" : "#/components/schemas/UploadSource" + } + } + }, + "id" : { + "$ref" : "#/components/schemas/MediaId" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Metrics" : { + "type" : "object", + "properties" : { + "app_install_attempts" : { + "type" : "integer", + "title" : "App Install Attempts", + "description" : "Tracks number of App Install Attempts" + }, + "app_opens" : { + "type" : "integer", + "title" : "App Opens", + "description" : "Tracks number of App opens" + }, + "detail_expands" : { + "type" : "integer", + "title" : "Detail Expands", + "description" : "Tracks number of Detail expands" + }, + "email_tweet" : { + "type" : "integer", + "title" : "Email Tweet", + "description" : "Tracks number of Email Tweet actions" + }, + "engagements" : { + "type" : "integer", + "title" : "Engagements", + "description" : "Tracks total Engagements" + }, + "follows" : { + "type" : "integer", + "title" : "Follows", + "description" : "Tracks number of Follows" + }, + "hashtag_clicks" : { + "type" : "integer", + "title" : "Hashtag Clicks", + "description" : "Tracks number of Hashtag clicks" + }, + "impressions" : { + "type" : "integer", + "title" : "Impressions", + "description" : "Tracks number of Impressions" + }, + "likes" : { + "type" : "integer", + "title" : "Likes", + "description" : "Tracks number of Likes" + }, + "link_clicks" : { + "type" : "integer", + "title" : "Link Clicks", + "description" : "Tracks number of Link clicks" + }, + "media_engagements" : { + "type" : "integer", + "title" : "Media Engagements", + "description" : "Tracks number of Media engagements" + }, + "media_views" : { + "type" : "integer", + "title" : "Media Views", + "description" : "Tracks number of Media views" + }, + "permalink_clicks" : { + "type" : "integer", + "title" : "Permalink Clicks", + "description" : "Tracks number of Permalink clicks" + }, + "profile_visits" : { + "type" : "integer", + "title" : "Profile Visits", + "description" : "Tracks number of Profile visits" + }, + "quote_tweets" : { + "type" : "integer", + "title" : "Quote Tweets", + "description" : "Tracks number of Quote Tweets" + }, + "replies" : { + "type" : "integer", + "title" : "Replies", + "description" : "Tracks number of Replies" + }, + "retweets" : { + "type" : "integer", + "title" : "Retweets", + "description" : "Tracks number of Retweets" + }, + "url_clicks" : { + "type" : "integer", + "title" : "URL Clicks", + "description" : "Tracks number of URL clicks" + }, + "user_profile_clicks" : { + "type" : "integer", + "title" : "User Profile Clicks", + "description" : "Tracks number of User Profile clicks" + } + } + }, + "MisleadingTags" : { + "type" : "string", + "description" : "Community Note misleading tags type.", + "enum" : [ + "disputed_claim_as_fact", + "factual_error", + "manipulated_media", + "misinterpreted_satire", + "missing_important_context", + "other", + "outdated_information" + ] + }, + "MuteUserMutationResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "muting" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "MuteUserRequest" : { + "type" : "object", + "required" : [ + "target_user_id" + ], + "properties" : { + "target_user_id" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "NewestId" : { + "type" : "string", + "description" : "The newest id in this response." + }, + "News" : { + "type" : "object", + "description" : "An AI generated news story.", + "required" : [ + "rest_id" + ], + "properties" : { + "category" : { + "type" : "string", + "description" : "The news category." + }, + "cluster_posts_results" : { + "type" : "array", + "items" : { + "type" : "object", + "properties" : { + "post_id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + }, + "contexts" : { + "type" : "object", + "properties" : { + "entities" : { + "type" : "object", + "properties" : { + "events" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "organizations" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "people" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "places" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "products" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "finance" : { + "type" : "object", + "properties" : { + "tickers" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "sports" : { + "type" : "object", + "properties" : { + "teams" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "topics" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "disclaimer" : { + "type" : "string" + }, + "hook" : { + "type" : "string", + "description" : "The news hook." + }, + "keywords" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "last_updated_at_ms" : { + "type" : "string", + "format" : "date-time", + "example" : "2025-7-14T04:35:55Z" + }, + "name" : { + "type" : "string", + "description" : "The headline." + }, + "rest_id" : { + "$ref" : "#/components/schemas/NewsId" + }, + "summary" : { + "type" : "string", + "description" : "The news summary." + } + } + }, + "NewsActivityResponsePayload" : { + "type" : "object", + "properties" : { + "category" : { + "type" : "string" + }, + "headline" : { + "type" : "string" + }, + "hook" : { + "type" : "string" + }, + "summary" : { + "type" : "string" + } + }, + "additionalProperties" : false + }, + "NewsId" : { + "type" : "string", + "description" : "Unique identifier of news story.", + "pattern" : "^[0-9]{1,19}$", + "example" : "2244994945" + }, + "NextToken" : { + "type" : "string", + "description" : "The next token.", + "minLength" : 1 + }, + "NonCompliantRulesProblem" : { + "description" : "A problem that indicates the user's rule set is not compliant.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "Note" : { + "type" : "object", + "description" : "A X Community Note is a note on a Post.", + "required" : [ + "id", + "post_id", + "note_info" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/NoteId" + }, + "info" : { + "$ref" : "#/components/schemas/NoteInfo" + }, + "post_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "status" : { + "$ref" : "#/components/schemas/NoteRatingStatus" + }, + "test_result" : { + "$ref" : "#/components/schemas/NoteTestResult" + } + } + }, + "NoteClassification" : { + "type" : "string", + "description" : "Community Note classification type.", + "enum" : [ + "misinformed_or_potentially_misleading", + "not_misleading" + ] + }, + "NoteId" : { + "type" : "string", + "description" : "The unique identifier of this Community Note.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "NoteInfo" : { + "type" : "object", + "description" : "A X Community Note is a note on a Post.", + "required" : [ + "text", + "classification", + "misleading_tags", + "trustworthy_sources" + ], + "properties" : { + "classification" : { + "$ref" : "#/components/schemas/NoteClassification" + }, + "misleading_tags" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/MisleadingTags" + } + }, + "text" : { + "type" : "string", + "description" : "The text summary in the Community Note.", + "pattern" : "^(?=[\\s\\S]*https?://\\S+)[\\s\\S]+$" + }, + "trustworthy_sources" : { + "type" : "boolean", + "description" : "Whether the note provided trustworthy links." + } + }, + "additionalProperties" : false + }, + "NoteRatingStatus" : { + "type" : "string", + "description" : "Community Note rating status", + "enum" : [ + "currently_rated_helpful", + "currently_rated_not_helpful", + "firm_reject", + "insufficient_consensus", + "minimum_ratings_not_met", + "needs_more_ratings", + "needs_your_help" + ] + }, + "NoteTestResult" : { + "type" : "object", + "description" : "The evaluation result of a community note.", + "properties" : { + "evaluator_score_bucket" : { + "type" : "string", + "description" : "Score bucket from the evaluator result." + }, + "evaluator_type" : { + "type" : "string", + "description" : "The type of the evaluator." + } + } + }, + "NoteTweetText" : { + "type" : "string", + "description" : "The note content of the Tweet.", + "example" : "Learn how to use the user Tweet timeline and user mention timeline endpoints in the X API v2 to explore Tweet\\u2026 https:\\/\\/t.co\\/56a0vZUx7i" + }, + "Oauth1PermissionsProblem" : { + "description" : "A problem that indicates your client application does not have the required OAuth1 permissions for the requested endpoint.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "OldestId" : { + "type" : "string", + "description" : "The oldest id in this response." + }, + "OperationalDisconnectProblem" : { + "description" : "You have been disconnected for operational reasons.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "properties" : { + "disconnect_type" : { + "type" : "string", + "enum" : [ + "OperationalDisconnect", + "UpstreamOperationalDisconnect", + "ForceDisconnect", + "UpstreamUncleanDisconnect", + "SlowReader", + "InternalError", + "ClientApplicationStateDegraded", + "InvalidRules" + ] + } + } + } + ] + }, + "PaginationToken32" : { + "type" : "string", + "description" : "A base32 pagination token.", + "minLength" : 16 + }, + "PaginationToken36" : { + "type" : "string", + "description" : "A base36 pagination token.", + "minLength" : 1 + }, + "PaginationTokenLong" : { + "type" : "string", + "description" : "A 'long' pagination token.", + "minLength" : 1, + "maxLength" : 19 + }, + "PersonalizedTrend" : { + "type" : "object", + "description" : "A trend.", + "properties" : { + "category" : { + "type" : "string", + "description" : "Category of this trend." + }, + "post_count" : { + "type" : "integer", + "description" : "Number of posts pertaining to this trend." + }, + "trend_name" : { + "type" : "string", + "description" : "Name of the trend." + }, + "trending_since" : { + "type" : "string", + "description" : "Time since this is trending." + } + } + }, + "Photo" : { + "allOf" : [ + { + "$ref" : "#/components/schemas/Media" + }, + { + "type" : "object", + "properties" : { + "alt_text" : { + "type" : "string" + }, + "url" : { + "type" : "string", + "format" : "uri" + } + } + } + ] + }, + "Place" : { + "type" : "object", + "required" : [ + "id", + "full_name" + ], + "properties" : { + "contained_within" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/PlaceId" + } + }, + "country" : { + "type" : "string", + "description" : "The full name of the county in which this place exists.", + "example" : "United States" + }, + "country_code" : { + "$ref" : "#/components/schemas/CountryCode" + }, + "full_name" : { + "type" : "string", + "description" : "The full name of this place.", + "example" : "Lakewood, CO" + }, + "geo" : { + "$ref" : "#/components/schemas/Geo" + }, + "id" : { + "$ref" : "#/components/schemas/PlaceId" + }, + "name" : { + "type" : "string", + "description" : "The human readable name of this place.", + "example" : "Lakewood" + }, + "place_type" : { + "$ref" : "#/components/schemas/PlaceType" + } + } + }, + "PlaceId" : { + "type" : "string", + "description" : "The identifier for this place.", + "example" : "f7eb2fa2fea288b1" + }, + "PlaceType" : { + "type" : "string", + "enum" : [ + "poi", + "neighborhood", + "city", + "admin", + "country", + "unknown" + ], + "example" : "city" + }, + "PlaidAccount" : { + "type" : "object", + "description" : "Descriptor for a Plaid account.", + "required" : [ + "accountId", + "accountCategory", + "accountNumberDisplay", + "accountType", + "currency", + "productName", + "status" + ], + "properties" : { + "accountCategory" : { + "type" : "string", + "description" : "The category of the account (e.g., personal, business)." + }, + "accountId" : { + "type" : "string", + "description" : "The Plaid account ID." + }, + "accountNumberDisplay" : { + "type" : "string", + "description" : "The last 2-4 digits of the account number." + }, + "accountType" : { + "type" : "string", + "description" : "The type of the account (e.g., checking, savings)." + }, + "availableBalance" : { + "type" : "number", + "description" : "The available balance of the account." + }, + "currency" : { + "$ref" : "#/components/schemas/PlaidCurrency" + }, + "currentBalance" : { + "type" : "number", + "description" : "The current balance of the account." + }, + "nickname" : { + "type" : "string", + "description" : "The nickname of the account." + }, + "productName" : { + "type" : "string", + "description" : "The name of the product associated with the account." + }, + "status" : { + "type" : "string", + "description" : "The status of the account." + } + } + }, + "PlaidAccountContact" : { + "type" : "object", + "description" : "Contact information associated with a Plaid account.", + "required" : [ + "name", + "addresses", + "emails", + "telephones" + ], + "properties" : { + "addresses" : { + "type" : "array", + "description" : "List of addresses associated with the account holder.", + "items" : { + "$ref" : "#/components/schemas/PlaidAddress" + } + }, + "emails" : { + "type" : "array", + "description" : "List of email addresses associated with the account holder.", + "items" : { + "type" : "string" + } + }, + "name" : { + "$ref" : "#/components/schemas/PlaidName" + }, + "relationship" : { + "type" : "string", + "description" : "Relationship of the contact to the account." + }, + "telephones" : { + "type" : "array", + "description" : "List of telephone numbers associated with the account holder.", + "items" : { + "$ref" : "#/components/schemas/PlaidTelephone" + } + } + } + }, + "PlaidAccountPaymentNetwork" : { + "type" : "object", + "description" : "Payment network details associated with the account.", + "required" : [ + "identifier", + "type", + "transferIn", + "transferOut", + "bankId" + ], + "properties" : { + "bankId" : { + "type" : "string", + "description" : "The bank ID associated with the account." + }, + "identifier" : { + "type" : "string", + "description" : "The payment network identifier." + }, + "transferIn" : { + "type" : "boolean", + "description" : "Indicates if transfers into the account are supported." + }, + "transferOut" : { + "type" : "boolean", + "description" : "Indicates if transfers out of the account are supported." + }, + "type" : { + "type" : "string", + "description" : "The type of payment network (e.g., ACH, SEPA)." + } + } + }, + "PlaidAccountTransaction" : { + "type" : "object", + "description" : "Descriptor for a Plaid account.", + "required" : [ + "accountCategory", + "amount", + "debitCreditMemo", + "description", + "status", + "transactionId", + "transactionTimestamp" + ], + "properties" : { + "accountCategory" : { + "type" : "string", + "description" : "The category of the account (e.g., personal, business)." + }, + "amount" : { + "type" : "number", + "description" : "The amount transacted." + }, + "debitCreditMemo" : { + "type" : "string", + "description" : "Memo for transaction (e.g. CREDIT)" + }, + "description" : { + "type" : "string", + "description" : "The transaction description" + }, + "postedTimestamp" : { + "type" : "string", + "description" : "The timestamp when the transaction was posted." + }, + "status" : { + "type" : "string", + "description" : "The status of the transaction." + }, + "transactionId" : { + "type" : "string", + "description" : "The identifier for the transaction." + }, + "transactionTimestamp" : { + "type" : "string", + "description" : "The timestamp when the transaction occurred." + } + } + }, + "PlaidAddress" : { + "type" : "object", + "description" : "Address information for the account holder.", + "required" : [ + "city", + "country", + "line1" + ], + "properties" : { + "city" : { + "type" : "string", + "description" : "The city of the address." + }, + "country" : { + "type" : "string", + "description" : "The country of the address (ISO 3166-1 alpha-2 code)." + }, + "line1" : { + "type" : "string", + "description" : "The first line of the address." + }, + "line2" : { + "type" : "string", + "description" : "The second line of the address." + }, + "postalCode" : { + "type" : "string", + "description" : "The postal code of the address." + }, + "region" : { + "type" : "string", + "description" : "The region or state of the address." + } + } + }, + "PlaidCurrency" : { + "type" : "object", + "description" : "Currency information.", + "required" : [ + "currencyCode" + ], + "properties" : { + "currencyCode" : { + "type" : "string", + "description" : "The ISO 4217 currency code." + } + } + }, + "PlaidCustomer" : { + "type" : "object", + "description" : "A user id for the plaid customer", + "properties" : { + "customerId" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "PlaidName" : { + "type" : "object", + "description" : "Name information for the account holder.", + "required" : [ + "first", + "last" + ], + "properties" : { + "first" : { + "type" : "string", + "description" : "The first name of the account holder." + }, + "last" : { + "type" : "string", + "description" : "The last name of the account holder." + } + } + }, + "PlaidTelephone" : { + "type" : "object", + "description" : "Telephone information for the account holder.", + "required" : [ + "country", + "number", + "type" + ], + "properties" : { + "country" : { + "type" : "string", + "description" : "The country code for the phone number (e.g., '+1')." + }, + "number" : { + "type" : "string", + "description" : "The phone number." + }, + "type" : { + "type" : "string", + "description" : "The type of phone number (e.g., 'mobile')." + } + } + }, + "Point" : { + "type" : "object", + "description" : "A [GeoJson Point](https://tools.ietf.org/html/rfc7946#section-3.1.2) geometry object.", + "required" : [ + "type", + "coordinates" + ], + "properties" : { + "coordinates" : { + "$ref" : "#/components/schemas/Position" + }, + "type" : { + "type" : "string", + "enum" : [ + "Point" + ], + "example" : "Point" + } + } + }, + "Poll" : { + "type" : "object", + "description" : "Represent a Poll attached to a Tweet.", + "required" : [ + "id", + "options" + ], + "properties" : { + "duration_minutes" : { + "type" : "integer", + "minimum" : 5, + "maximum" : 10080, + "format" : "int32" + }, + "end_datetime" : { + "type" : "string", + "format" : "date-time" + }, + "id" : { + "$ref" : "#/components/schemas/PollId" + }, + "options" : { + "type" : "array", + "minItems" : 2, + "maxItems" : 4, + "items" : { + "$ref" : "#/components/schemas/PollOption" + } + }, + "voting_status" : { + "type" : "string", + "enum" : [ + "open", + "closed" + ] + } + } + }, + "PollId" : { + "type" : "string", + "description" : "Unique identifier of this poll.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1365059861688410112" + }, + "PollOption" : { + "type" : "object", + "description" : "Describes a choice in a Poll object.", + "required" : [ + "position", + "label", + "votes" + ], + "properties" : { + "label" : { + "$ref" : "#/components/schemas/PollOptionLabel" + }, + "position" : { + "type" : "integer", + "description" : "Position of this choice in the poll." + }, + "votes" : { + "type" : "integer", + "description" : "Number of users who voted for this choice." + } + } + }, + "PollOptionLabel" : { + "type" : "string", + "description" : "The text of a poll choice.", + "minLength" : 1, + "maxLength" : 25 + }, + "Position" : { + "type" : "array", + "description" : "A [GeoJson Position](https://tools.ietf.org/html/rfc7946#section-3.1.1) in the format `[longitude,latitude]`.", + "minItems" : 2, + "maxItems" : 2, + "items" : { + "type" : "number" + }, + "example" : [ + -105.18816086351444, + 40.247749999999996 + ] + }, + "PreviewImage" : { + "type" : "object", + "required" : [ + "media_key" + ], + "properties" : { + "media_key" : { + "type" : "object", + "properties" : { + "media" : { + "$ref" : "#/components/schemas/MediaId" + }, + "media_category" : { + "type" : "string", + "description" : "The media category of media", + "enum" : [ + "TweetImage" + ], + "default" : "TweetImage", + "example" : "TweetImage" + } + } + } + } + }, + "PreviousToken" : { + "type" : "string", + "description" : "The previous token.", + "minLength" : 1 + }, + "Problem" : { + "type" : "object", + "description" : "An HTTP Problem Details object, as defined in IETF RFC 7807 (https://tools.ietf.org/html/rfc7807).", + "required" : [ + "type", + "title" + ], + "properties" : { + "detail" : { + "type" : "string" + }, + "status" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "type" : { + "type" : "string" + } + }, + "discriminator" : { + "propertyName" : "type", + "mapping" : { + "about:blank" : "#/components/schemas/GenericProblem", + "https://api.twitter.com/2/problems/client-disconnected" : "#/components/schemas/ClientDisconnectedProblem", + "https://api.twitter.com/2/problems/client-forbidden" : "#/components/schemas/ClientForbiddenProblem", + "https://api.twitter.com/2/problems/conflict" : "#/components/schemas/ConflictProblem", + "https://api.twitter.com/2/problems/disallowed-resource" : "#/components/schemas/DisallowedResourceProblem", + "https://api.twitter.com/2/problems/duplicate-rules" : "#/components/schemas/DuplicateRuleProblem", + "https://api.twitter.com/2/problems/invalid-request" : "#/components/schemas/InvalidRequestProblem", + "https://api.twitter.com/2/problems/invalid-rules" : "#/components/schemas/InvalidRuleProblem", + "https://api.twitter.com/2/problems/noncompliant-rules" : "#/components/schemas/NonCompliantRulesProblem", + "https://api.twitter.com/2/problems/not-authorized-for-field" : "#/components/schemas/FieldUnauthorizedProblem", + "https://api.twitter.com/2/problems/not-authorized-for-resource" : "#/components/schemas/ResourceUnauthorizedProblem", + "https://api.twitter.com/2/problems/operational-disconnect" : "#/components/schemas/OperationalDisconnectProblem", + "https://api.twitter.com/2/problems/resource-not-found" : "#/components/schemas/ResourceNotFoundProblem", + "https://api.twitter.com/2/problems/resource-unavailable" : "#/components/schemas/ResourceUnavailableProblem", + "https://api.twitter.com/2/problems/rule-cap" : "#/components/schemas/RulesCapProblem", + "https://api.twitter.com/2/problems/streaming-connection" : "#/components/schemas/ConnectionExceptionProblem", + "https://api.twitter.com/2/problems/unsupported-authentication" : "#/components/schemas/UnsupportedAuthenticationProblem", + "https://api.twitter.com/2/problems/usage-capped" : "#/components/schemas/UsageCapExceededProblem" + } + } + }, + "ProcessingInfo" : { + "type" : "object", + "required" : [ + "type" + ], + "properties" : { + "check_after_secs" : { + "type" : "integer", + "description" : "Number of seconds to check again for status", + "format" : "int32" + }, + "progress_percent" : { + "type" : "integer", + "description" : "Percent of upload progress", + "format" : "int32" + }, + "state" : { + "type" : "string", + "description" : "State of upload", + "enum" : [ + "succeeded", + "in_progress", + "pending", + "failed" + ] + } + } + }, + "ProfileUpdateActivityResponsePayload" : { + "type" : "object", + "properties" : { + "after" : { + "type" : "string" + }, + "before" : { + "type" : "string" + } + }, + "additionalProperties" : false + }, + "ReplayJobCreateResponse" : { + "type" : "object", + "description" : "Confirmation that the replay job request was accepted.", + "required" : [ + "job_id", + "created_at" + ], + "properties" : { + "created_at" : { + "type" : "string", + "description" : "The UTC timestamp indicating when the replay job was created.", + "format" : "date-time", + "example" : "2025-04-24T20:57:15.242Z" + }, + "job_id" : { + "type" : "string", + "description" : "The unique identifier for the initiated replay job.", + "example" : "1915510368169844736" + } + } + }, + "ReplySettings" : { + "type" : "string", + "description" : "Shows who can reply a Tweet. Fields returned are everyone, mentioned_users, and following.", + "pattern" : "^[A-Za-z]{1,12}$", + "enum" : [ + "everyone", + "mentionedUsers", + "following", + "other" + ] + }, + "ReplySettingsWithVerifiedUsers" : { + "type" : "string", + "description" : "Shows who can reply a Tweet. Fields returned are everyone, mentioned_users, subscribers, verified and following.", + "pattern" : "^[A-Za-z]{1,12}$", + "enum" : [ + "everyone", + "mentionedUsers", + "following", + "other", + "subscribers", + "verified" + ] + }, + "ResourceNotFoundProblem" : { + "description" : "A problem that indicates that a given Tweet, User, etc. does not exist.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "required" : [ + "parameter", + "value", + "resource_id", + "resource_type" + ], + "properties" : { + "parameter" : { + "type" : "string", + "minLength" : 1 + }, + "resource_id" : { + "type" : "string" + }, + "resource_type" : { + "type" : "string", + "enum" : [ + "user", + "tweet", + "media", + "list", + "space" + ] + }, + "value" : { + "type" : "string", + "description" : "Value will match the schema of the field." + } + } + } + ] + }, + "ResourceUnauthorizedProblem" : { + "description" : "A problem that indicates you are not allowed to see a particular Tweet, User, etc.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "required" : [ + "value", + "resource_id", + "resource_type", + "section", + "parameter" + ], + "properties" : { + "parameter" : { + "type" : "string" + }, + "resource_id" : { + "type" : "string" + }, + "resource_type" : { + "type" : "string", + "enum" : [ + "user", + "tweet", + "media", + "list", + "space" + ] + }, + "section" : { + "type" : "string", + "enum" : [ + "data", + "includes" + ] + }, + "value" : { + "type" : "string" + } + } + } + ] + }, + "ResourceUnavailableProblem" : { + "description" : "A problem that indicates a particular Tweet, User, etc. is not available to you.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "required" : [ + "parameter", + "resource_id", + "resource_type" + ], + "properties" : { + "parameter" : { + "type" : "string", + "minLength" : 1 + }, + "resource_id" : { + "type" : "string" + }, + "resource_type" : { + "type" : "string", + "enum" : [ + "user", + "tweet", + "media", + "list", + "space" + ] + } + } + } + ] + }, + "ResultCount" : { + "type" : "integer", + "description" : "The number of results returned in this response.", + "format" : "int32" + }, + "Rule" : { + "type" : "object", + "description" : "A user-provided stream filtering rule.", + "required" : [ + "value" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/RuleId" + }, + "tag" : { + "$ref" : "#/components/schemas/RuleTag" + }, + "value" : { + "$ref" : "#/components/schemas/RuleValue" + } + } + }, + "RuleId" : { + "type" : "string", + "description" : "Unique identifier of this rule.", + "pattern" : "^[0-9]{1,19}$", + "example" : "120897978112909812" + }, + "RuleNoId" : { + "type" : "object", + "description" : "A user-provided stream filtering rule.", + "required" : [ + "value" + ], + "properties" : { + "tag" : { + "$ref" : "#/components/schemas/RuleTag" + }, + "value" : { + "$ref" : "#/components/schemas/RuleValue" + } + } + }, + "RuleTag" : { + "type" : "string", + "description" : "A tag meant for the labeling of user provided rules.", + "example" : "Non-retweeted coffee Posts" + }, + "RuleValue" : { + "type" : "string", + "description" : "The filterlang value of the rule.", + "example" : "coffee -is:retweet" + }, + "RulesCapProblem" : { + "description" : "You have exceeded the maximum number of rules.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "RulesCount" : { + "type" : "object", + "description" : "A count of user-provided stream filtering rules at the application and project levels.", + "properties" : { + "all_project_client_apps" : { + "$ref" : "#/components/schemas/AllProjectClientApps" + }, + "cap_per_client_app" : { + "type" : "integer", + "description" : "Cap of number of rules allowed per client application", + "format" : "int32" + }, + "cap_per_project" : { + "type" : "integer", + "description" : "Cap of number of rules allowed per project", + "format" : "int32" + }, + "client_app_rules_count" : { + "$ref" : "#/components/schemas/AppRulesCount" + }, + "project_rules_count" : { + "type" : "integer", + "description" : "Number of rules for project", + "format" : "int32" + } + } + }, + "RulesLookupResponse" : { + "type" : "object", + "required" : [ + "meta" + ], + "properties" : { + "data" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/Rule" + } + }, + "meta" : { + "$ref" : "#/components/schemas/RulesResponseMetadata" + } + } + }, + "RulesRequestSummary" : { + "oneOf" : [ + { + "type" : "object", + "description" : "A summary of the results of the addition of user-specified stream filtering rules.", + "required" : [ + "created", + "not_created", + "valid", + "invalid" + ], + "properties" : { + "created" : { + "type" : "integer", + "description" : "Number of user-specified stream filtering rules that were created.", + "format" : "int32", + "example" : 1 + }, + "invalid" : { + "type" : "integer", + "description" : "Number of invalid user-specified stream filtering rules.", + "format" : "int32", + "example" : 1 + }, + "not_created" : { + "type" : "integer", + "description" : "Number of user-specified stream filtering rules that were not created.", + "format" : "int32", + "example" : 1 + }, + "valid" : { + "type" : "integer", + "description" : "Number of valid user-specified stream filtering rules.", + "format" : "int32", + "example" : 1 + } + } + }, + { + "type" : "object", + "required" : [ + "deleted", + "not_deleted" + ], + "properties" : { + "deleted" : { + "type" : "integer", + "description" : "Number of user-specified stream filtering rules that were deleted.", + "format" : "int32" + }, + "not_deleted" : { + "type" : "integer", + "description" : "Number of user-specified stream filtering rules that were not deleted.", + "format" : "int32" + } + } + } + ] + }, + "RulesResponseMetadata" : { + "type" : "object", + "required" : [ + "sent" + ], + "properties" : { + "next_token" : { + "$ref" : "#/components/schemas/NextToken" + }, + "result_count" : { + "type" : "integer", + "description" : "Number of Rules in result set.", + "format" : "int32" + }, + "sent" : { + "type" : "string" + }, + "summary" : { + "$ref" : "#/components/schemas/RulesRequestSummary" + } + } + }, + "SearchCount" : { + "type" : "object", + "description" : "Represent a Search Count Result.", + "required" : [ + "end", + "start", + "tweet_count" + ], + "properties" : { + "end" : { + "$ref" : "#/components/schemas/End" + }, + "start" : { + "$ref" : "#/components/schemas/Start" + }, + "tweet_count" : { + "$ref" : "#/components/schemas/TweetCount" + } + } + }, + "SensitiveMediaWarning" : { + "type" : "object", + "properties" : { + "adult_content" : { + "type" : "boolean", + "description" : "Indicates if the content contains adult material", + "example" : true + }, + "graphic_violence" : { + "type" : "boolean", + "description" : "Indicates if the content depicts graphic violence", + "example" : true + }, + "other" : { + "type" : "boolean", + "description" : "Indicates if the content has other sensitive characteristics", + "example" : false + } + } + }, + "SharedInfo" : { + "type" : "object", + "required" : [ + "shared" + ], + "properties" : { + "shared" : { + "type" : "boolean", + "description" : "Indicates if the media is shared in direct messages", + "example" : false + } + } + }, + "Space" : { + "type" : "object", + "description" : "", + "required" : [ + "id", + "state" + ], + "properties" : { + "created_at" : { + "type" : "string", + "description" : "Creation time of the Space.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "creator_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "ended_at" : { + "type" : "string", + "description" : "End time of the Space.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "host_ids" : { + "type" : "array", + "description" : "The user ids for the hosts of the Space.", + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "id" : { + "$ref" : "#/components/schemas/SpaceId" + }, + "invited_user_ids" : { + "type" : "array", + "description" : "An array of user ids for people who were invited to a Space.", + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "is_ticketed" : { + "type" : "boolean", + "description" : "Denotes if the Space is a ticketed Space.", + "example" : "false" + }, + "lang" : { + "type" : "string", + "description" : "The language of the Space.", + "example" : "en" + }, + "participant_count" : { + "type" : "integer", + "description" : "The number of participants in a Space.", + "format" : "int32", + "example" : 10 + }, + "scheduled_start" : { + "type" : "string", + "description" : "A date time stamp for when a Space is scheduled to begin.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "speaker_ids" : { + "type" : "array", + "description" : "An array of user ids for people who were speakers in a Space.", + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "started_at" : { + "type" : "string", + "description" : "When the Space was started as a date string.", + "format" : "date-time", + "example" : "2021-7-14T04:35:55Z" + }, + "state" : { + "type" : "string", + "description" : "The current state of the Space.", + "enum" : [ + "live", + "scheduled", + "ended" + ], + "example" : "live" + }, + "subscriber_count" : { + "type" : "integer", + "description" : "The number of people who have either purchased a ticket or set a reminder for this Space.", + "format" : "int32", + "example" : 10 + }, + "title" : { + "type" : "string", + "description" : "The title of the Space.", + "example" : "Spaces are Awesome" + }, + "topics" : { + "type" : "array", + "description" : "The topics of a Space, as selected by its creator.", + "items" : { + "type" : "object", + "description" : "The X Topic object.", + "required" : [ + "id", + "name" + ], + "properties" : { + "description" : { + "type" : "string", + "description" : "The description of the given topic." + }, + "id" : { + "type" : "string", + "description" : "An ID suitable for use in the REST API." + }, + "name" : { + "type" : "string", + "description" : "The name of the given topic." + } + }, + "example" : { + "description" : "All about technology", + "id" : "848920371311001600", + "name" : "Technology" + } + } + }, + "updated_at" : { + "type" : "string", + "description" : "When the Space was last updated.", + "format" : "date-time", + "example" : "2021-7-14T04:35:55Z" + } + } + }, + "SpaceId" : { + "type" : "string", + "description" : "The unique identifier of this Space.", + "pattern" : "^[a-zA-Z0-9]{1,13}$", + "example" : "1SLjjRYNejbKM" + }, + "Start" : { + "type" : "string", + "description" : "The start time of the bucket.", + "format" : "date-time" + }, + "Sticker" : { + "type" : "object", + "properties" : { + "aspect_ratio" : { + "type" : "number", + "description" : "width-to-height ratio of the media", + "format" : "double", + "example" : 1.78 + }, + "group_annotation_id" : { + "type" : "number", + "description" : "A unique identifier for the group of annotations associated with the media", + "format" : "long", + "example" : 987654321098765 + }, + "id" : { + "type" : "string", + "description" : "Unique identifier for sticker", + "example" : "12345" + }, + "sticker_set_annotation_id" : { + "type" : "number", + "description" : "A unique identifier for the sticker set associated with the media", + "format" : "long", + "example" : 123456789012345 + }, + "transform_a" : { + "type" : "number", + "description" : "Scale or rotate the media on the x-axis", + "format" : "double", + "example" : 1.0 + }, + "transform_b" : { + "type" : "number", + "description" : "Skew the media on the x-axis", + "format" : "double", + "example" : 0.0 + }, + "transform_c" : { + "type" : "number", + "description" : "Skew the media on the y-axis", + "format" : "double", + "example" : 0.0 + }, + "transform_d" : { + "type" : "number", + "description" : "Scale or rotate the media on the y-axis", + "format" : "double", + "example" : 1.0 + }, + "transform_tx" : { + "type" : "number", + "description" : "Scale or rotate the media on the x-axis", + "format" : "double", + "example" : 10.5 + }, + "transform_ty" : { + "type" : "number", + "description" : "The vertical translation (shift) value for the media", + "format" : "double", + "example" : -5.2 + } + } + }, + "StickerInfo" : { + "type" : "object", + "required" : [ + "stickers" + ], + "properties" : { + "stickers" : { + "type" : "array", + "description" : "Stickers list must not be empty and should not exceed 25", + "items" : { + "$ref" : "#/components/schemas/Sticker" + } + } + } + }, + "StreamingLikeResponseV2" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/LikeWithTweetAuthor" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "StreamingTweetResponse" : { + "type" : "object", + "properties" : { + "data" : { + "$ref" : "#/components/schemas/Tweet" + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + }, + "includes" : { + "$ref" : "#/components/schemas/Expansions" + } + } + }, + "SubscriptionsCountGetResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "description" : "The count of active subscriptions across all webhooks", + "required" : [ + "account_name", + "provisioned_count", + "subscriptions_count_all", + "subscriptions_count_direct_messages" + ], + "properties" : { + "account_name" : { + "type" : "string", + "description" : "The account name" + }, + "provisioned_count" : { + "type" : "string", + "description" : "The limit for subscriptions for this app" + }, + "subscriptions_count_all" : { + "type" : "string", + "description" : "The number of active subscriptions across all webhooks" + }, + "subscriptions_count_direct_messages" : { + "type" : "string", + "description" : "The number of active direct message subscriptions" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "SubscriptionsCreateRequest" : { + "type" : "object" + }, + "SubscriptionsCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "subscribed" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "SubscriptionsDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "subscribed" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "SubscriptionsGetResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "subscribed" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "SubscriptionsListGetResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "description" : "The list of active subscriptions for a specified webhook", + "required" : [ + "application_id", + "webhook_id", + "webhook_url", + "subscriptions" + ], + "properties" : { + "application_id" : { + "type" : "string", + "description" : "The application ID" + }, + "subscriptions" : { + "type" : "array", + "description" : "List of active subscriptions for the webhook", + "items" : { + "type" : "object", + "properties" : { + "user_id" : { + "type" : "string", + "description" : "The ID of the user the webhook is subscribed to" + } + } + } + }, + "webhook_id" : { + "type" : "string", + "description" : "The associated webhook ID" + }, + "webhook_url" : { + "type" : "string", + "description" : "The url for the associated webhook" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "SubtitleLanguageCode" : { + "type" : "string", + "description" : "The language code should be a BCP47 code (e.g. 'EN\", \"SP\")", + "pattern" : "^[A-Z]{2}$", + "example" : "EN" + }, + "Subtitles" : { + "type" : "object", + "properties" : { + "display_name" : { + "type" : "string", + "description" : "Language name in a human readable form", + "example" : "English" + }, + "id" : { + "$ref" : "#/components/schemas/MediaId" + }, + "language_code" : { + "$ref" : "#/components/schemas/SubtitleLanguageCode" + } + } + }, + "SubtitlesCreateRequest" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/MediaId" + }, + "media_category" : { + "$ref" : "#/components/schemas/MediaCategorySubtitles" + }, + "subtitles" : { + "$ref" : "#/components/schemas/Subtitles" + } + } + }, + "SubtitlesCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "id", + "media_category", + "associated_subtitles" + ], + "properties" : { + "associated_subtitles" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Subtitles" + } + }, + "id" : { + "$ref" : "#/components/schemas/MediaId" + }, + "media_category" : { + "$ref" : "#/components/schemas/MediaCategorySubtitles" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "SubtitlesDeleteRequest" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/MediaId" + }, + "language_code" : { + "$ref" : "#/components/schemas/SubtitleLanguageCode" + }, + "media_category" : { + "$ref" : "#/components/schemas/MediaCategorySubtitles" + } + } + }, + "SubtitlesDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "deleted" + ], + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "TimestampedMetrics" : { + "type" : "object", + "properties" : { + "metrics" : { + "$ref" : "#/components/schemas/Metrics" + }, + "timestamp" : { + "type" : "string", + "title" : "Timestamp", + "description" : "ISO8601 Time", + "example" : "2025-03-17T06:30:00Z" + } + } + }, + "Topic" : { + "type" : "object", + "description" : "The topic of a Space, as selected by its creator.", + "required" : [ + "id", + "name" + ], + "properties" : { + "description" : { + "type" : "string", + "description" : "The description of the given topic.", + "example" : "All about technology" + }, + "id" : { + "$ref" : "#/components/schemas/TopicId" + }, + "name" : { + "type" : "string", + "description" : "The name of the given topic.", + "example" : "Technology" + } + } + }, + "TopicId" : { + "type" : "string", + "description" : "Unique identifier of this Topic." + }, + "Trend" : { + "type" : "object", + "description" : "A trend.", + "properties" : { + "trend_name" : { + "type" : "string", + "description" : "Name of the trend." + }, + "tweet_count" : { + "type" : "integer", + "description" : "Number of Posts in this trend.", + "format" : "int32" + } + } + }, + "Tweet" : { + "type" : "object", + "properties" : { + "attachments" : { + "type" : "object", + "description" : "Specifies the type of attachments (if any) present in this Tweet.", + "properties" : { + "media_keys" : { + "type" : "array", + "description" : "A list of Media Keys for each one of the media attachments (if media are attached).", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/MediaKey" + } + }, + "media_source_tweet_id" : { + "type" : "array", + "description" : "A list of Posts the media on this Tweet was originally posted in. For example, if the media on a tweet is re-used in another Tweet, this refers to the original, source Tweet..", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "poll_ids" : { + "type" : "array", + "description" : "A list of poll IDs (if polls are attached).", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/PollId" + } + } + } + }, + "author_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "community_id" : { + "$ref" : "#/components/schemas/CommunityId" + }, + "context_annotations" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/ContextAnnotation" + } + }, + "conversation_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "created_at" : { + "type" : "string", + "description" : "Creation time of the Tweet.", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "display_text_range" : { + "$ref" : "#/components/schemas/DisplayTextRange" + }, + "edit_controls" : { + "type" : "object", + "required" : [ + "is_edit_eligible", + "editable_until", + "edits_remaining" + ], + "properties" : { + "editable_until" : { + "type" : "string", + "description" : "Time when Tweet is no longer editable.", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "edits_remaining" : { + "type" : "integer", + "description" : "Number of times this Tweet can be edited." + }, + "is_edit_eligible" : { + "type" : "boolean", + "description" : "Indicates if this Tweet is eligible to be edited.", + "example" : false + } + } + }, + "edit_history_tweet_ids" : { + "type" : "array", + "description" : "A list of Tweet Ids in this Tweet chain.", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "entities" : { + "$ref" : "#/components/schemas/FullTextEntities" + }, + "geo" : { + "type" : "object", + "description" : "The location tagged on the Tweet, if the user provided one.", + "properties" : { + "coordinates" : { + "$ref" : "#/components/schemas/Point" + }, + "place_id" : { + "$ref" : "#/components/schemas/PlaceId" + } + } + }, + "id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "in_reply_to_user_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "lang" : { + "type" : "string", + "description" : "Language of the Tweet, if detected by X. Returned as a BCP47 language tag.", + "example" : "en" + }, + "non_public_metrics" : { + "type" : "object", + "description" : "Nonpublic engagement metrics for the Tweet at the time of the request.", + "properties" : { + "impression_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been viewed.", + "format" : "int32" + } + } + }, + "note_tweet" : { + "type" : "object", + "description" : "The full-content of the Tweet, including text beyond 280 characters.", + "properties" : { + "entities" : { + "type" : "object", + "properties" : { + "cashtags" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/CashtagEntity" + } + }, + "hashtags" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/HashtagEntity" + } + }, + "mentions" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/MentionEntity" + } + }, + "urls" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UrlEntity" + } + } + } + }, + "text" : { + "$ref" : "#/components/schemas/NoteTweetText" + } + } + }, + "organic_metrics" : { + "type" : "object", + "description" : "Organic nonpublic engagement metrics for the Tweet at the time of the request.", + "required" : [ + "impression_count", + "retweet_count", + "reply_count", + "like_count" + ], + "properties" : { + "impression_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been viewed." + }, + "like_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been liked." + }, + "reply_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been replied to." + }, + "retweet_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been Retweeted." + } + } + }, + "possibly_sensitive" : { + "type" : "boolean", + "description" : "Indicates if this Tweet contains URLs marked as sensitive, for example content suitable for mature audiences.", + "example" : false + }, + "promoted_metrics" : { + "type" : "object", + "description" : "Promoted nonpublic engagement metrics for the Tweet at the time of the request.", + "properties" : { + "impression_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been viewed.", + "format" : "int32" + }, + "like_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been liked.", + "format" : "int32" + }, + "reply_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been replied to.", + "format" : "int32" + }, + "retweet_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been Retweeted.", + "format" : "int32" + } + } + }, + "public_metrics" : { + "type" : "object", + "description" : "Engagement metrics for the Tweet at the time of the request.", + "required" : [ + "retweet_count", + "reply_count", + "like_count", + "impression_count", + "bookmark_count" + ], + "properties" : { + "bookmark_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been bookmarked.", + "format" : "int32" + }, + "impression_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been viewed.", + "format" : "int32" + }, + "like_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been liked." + }, + "quote_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been quoted." + }, + "reply_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been replied to." + }, + "retweet_count" : { + "type" : "integer", + "description" : "Number of times this Tweet has been Retweeted." + } + } + }, + "referenced_tweets" : { + "type" : "array", + "description" : "A list of Posts this Tweet refers to. For example, if the parent Tweet is a Retweet, a Quoted Tweet or a Reply, it will include the related Tweet referenced to by its parent.", + "minItems" : 1, + "items" : { + "type" : "object", + "required" : [ + "type", + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "type" : { + "type" : "string", + "enum" : [ + "retweeted", + "quoted", + "replied_to" + ] + } + } + } + }, + "reply_settings" : { + "$ref" : "#/components/schemas/ReplySettingsWithVerifiedUsers" + }, + "scopes" : { + "type" : "object", + "description" : "The scopes for this tweet", + "properties" : { + "followers" : { + "type" : "boolean", + "description" : "Indicates if this Tweet is viewable by followers without the Tweet ID", + "example" : false + } + } + }, + "source" : { + "type" : "string", + "description" : "This is deprecated." + }, + "suggested_source_links" : { + "type" : "array", + "minItems" : 0, + "items" : { + "$ref" : "#/components/schemas/UrlEntity" + } + }, + "suggested_source_links_with_counts" : { + "type" : "object", + "description" : "Suggested source links and the number of requests that included each link.", + "properties" : { + "count" : { + "type" : "integer", + "description" : "Number of note requests that included the source link." + }, + "url" : { + "$ref" : "#/components/schemas/UrlEntity" + } + } + }, + "text" : { + "$ref" : "#/components/schemas/TweetText" + }, + "username" : { + "$ref" : "#/components/schemas/UserName" + }, + "withheld" : { + "$ref" : "#/components/schemas/TweetWithheld" + } + }, + "example" : { + "author_id" : "2244994945", + "created_at" : "Wed Jan 06 18:40:40 +0000 2021", + "id" : "1346889436626259968", + "text" : "Learn how to use the user Tweet timeline and user mention timeline endpoints in the X API v2 to explore Tweet\\u2026 https:\\/\\/t.co\\/56a0vZUx7i", + "username" : "XDevelopers" + } + }, + "TweetComplianceData" : { + "description" : "Tweet compliance data.", + "oneOf" : [ + { + "$ref" : "#/components/schemas/TweetDeleteComplianceSchema" + }, + { + "$ref" : "#/components/schemas/TweetWithheldComplianceSchema" + }, + { + "$ref" : "#/components/schemas/TweetDropComplianceSchema" + }, + { + "$ref" : "#/components/schemas/TweetUndropComplianceSchema" + }, + { + "$ref" : "#/components/schemas/TweetEditComplianceSchema" + } + ] + }, + "TweetComplianceSchema" : { + "type" : "object", + "required" : [ + "tweet", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "quote_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "tweet" : { + "type" : "object", + "required" : [ + "id", + "author_id" + ], + "properties" : { + "author_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + } + }, + "TweetComplianceStreamResponse" : { + "description" : "Tweet compliance stream events.", + "oneOf" : [ + { + "type" : "object", + "description" : "Compliance event.", + "required" : [ + "data" + ], + "properties" : { + "data" : { + "$ref" : "#/components/schemas/TweetComplianceData" + } + } + }, + { + "type" : "object", + "required" : [ + "errors" + ], + "properties" : { + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + ] + }, + "TweetCount" : { + "type" : "integer", + "description" : "The count for the bucket." + }, + "TweetCreateRequest" : { + "type" : "object", + "properties" : { + "card_uri" : { + "type" : "string", + "description" : "Card Uri Parameter. This is mutually exclusive from Quote Tweet Id, Poll, Media, and Direct Message Deep Link." + }, + "community_id" : { + "$ref" : "#/components/schemas/CommunityId" + }, + "direct_message_deep_link" : { + "type" : "string", + "description" : "Link to take the conversation from the public timeline to a private Direct Message." + }, + "edit_options" : { + "type" : "object", + "description" : "Options for editing an existing Post. When provided, this request will edit the specified Post instead of creating a new one.", + "required" : [ + "previous_post_id" + ], + "properties" : { + "previous_post_id" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "additionalProperties" : false + }, + "for_super_followers_only" : { + "type" : "boolean", + "description" : "Exclusive Tweet for super followers.", + "default" : false + }, + "geo" : { + "type" : "object", + "description" : "Place ID being attached to the Tweet for geo location.", + "properties" : { + "place_id" : { + "type" : "string" + } + }, + "additionalProperties" : false + }, + "media" : { + "type" : "object", + "description" : "Media information being attached to created Tweet. This is mutually exclusive from Quote Tweet Id, Poll, and Card URI.", + "required" : [ + "media_ids" + ], + "properties" : { + "media_ids" : { + "type" : "array", + "description" : "A list of Media Ids to be attached to a created Tweet.", + "minItems" : 1, + "maxItems" : 4, + "items" : { + "$ref" : "#/components/schemas/MediaId" + } + }, + "tagged_user_ids" : { + "type" : "array", + "description" : "A list of User Ids to be tagged in the media for created Tweet.", + "minItems" : 0, + "maxItems" : 10, + "items" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "additionalProperties" : false + }, + "nullcast" : { + "type" : "boolean", + "description" : "Nullcasted (promoted-only) Posts do not appear in the public timeline and are not served to followers.", + "default" : false + }, + "poll" : { + "type" : "object", + "description" : "Poll options for a Tweet with a poll. This is mutually exclusive from Media, Quote Tweet Id, and Card URI.", + "required" : [ + "options", + "duration_minutes" + ], + "properties" : { + "duration_minutes" : { + "type" : "integer", + "description" : "Duration of the poll in minutes.", + "minimum" : 5, + "maximum" : 10080, + "format" : "int32" + }, + "options" : { + "type" : "array", + "minItems" : 2, + "maxItems" : 4, + "items" : { + "type" : "string", + "description" : "The text of a poll choice.", + "minLength" : 1, + "maxLength" : 25 + } + }, + "reply_settings" : { + "type" : "string", + "description" : "Settings to indicate who can reply to the Tweet.", + "enum" : [ + "following", + "mentionedUsers", + "subscribers", + "verified" + ] + } + }, + "additionalProperties" : false + }, + "quote_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "reply" : { + "type" : "object", + "description" : "Tweet information of the Tweet being replied to.", + "required" : [ + "in_reply_to_tweet_id" + ], + "properties" : { + "auto_populate_reply_metadata" : { + "type" : "boolean", + "description" : "If set to true, reply metadata will be automatically populated." + }, + "exclude_reply_user_ids" : { + "type" : "array", + "description" : "A list of User Ids to be excluded from the reply Tweet.", + "items" : { + "$ref" : "#/components/schemas/UserId" + } + }, + "in_reply_to_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "additionalProperties" : false + }, + "reply_settings" : { + "type" : "string", + "description" : "Settings to indicate who can reply to the Tweet.", + "enum" : [ + "following", + "mentionedUsers", + "subscribers", + "verified" + ] + }, + "share_with_followers" : { + "type" : "boolean", + "description" : "Share community post with followers too.", + "default" : false + }, + "text" : { + "$ref" : "#/components/schemas/TweetText" + } + }, + "additionalProperties" : false + }, + "TweetCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "id", + "text" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "text" : { + "$ref" : "#/components/schemas/TweetText" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "TweetDeleteComplianceSchema" : { + "type" : "object", + "required" : [ + "delete" + ], + "properties" : { + "delete" : { + "$ref" : "#/components/schemas/TweetComplianceSchema" + } + } + }, + "TweetDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "required" : [ + "deleted" + ], + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "TweetDropComplianceSchema" : { + "type" : "object", + "required" : [ + "drop" + ], + "properties" : { + "drop" : { + "$ref" : "#/components/schemas/TweetComplianceSchema" + } + } + }, + "TweetEditComplianceObjectSchema" : { + "type" : "object", + "required" : [ + "tweet", + "event_at", + "initial_tweet_id", + "edit_tweet_ids" + ], + "properties" : { + "edit_tweet_ids" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "initial_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "tweet" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + } + }, + "TweetEditComplianceSchema" : { + "type" : "object", + "required" : [ + "tweet_edit" + ], + "properties" : { + "tweet_edit" : { + "$ref" : "#/components/schemas/TweetEditComplianceObjectSchema" + } + } + }, + "TweetHideRequest" : { + "type" : "object", + "required" : [ + "hidden" + ], + "properties" : { + "hidden" : { + "type" : "boolean" + } + } + }, + "TweetHideResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "hidden" : { + "type" : "boolean" + } + } + } + } + }, + "TweetId" : { + "type" : "string", + "description" : "Unique identifier of this Tweet. This is returned as a string in order to avoid complications with languages and tools that cannot handle large integers.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1346889436626259968" + }, + "TweetLabelData" : { + "description" : "Tweet label data.", + "oneOf" : [ + { + "$ref" : "#/components/schemas/TweetNoticeSchema" + }, + { + "$ref" : "#/components/schemas/TweetUnviewableSchema" + } + ] + }, + "TweetLabelStreamResponse" : { + "description" : "Tweet label stream events.", + "oneOf" : [ + { + "type" : "object", + "description" : "Tweet Label event.", + "required" : [ + "data" + ], + "properties" : { + "data" : { + "$ref" : "#/components/schemas/TweetLabelData" + } + } + }, + { + "type" : "object", + "required" : [ + "errors" + ], + "properties" : { + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + ] + }, + "TweetNotice" : { + "type" : "object", + "required" : [ + "tweet", + "event_type", + "event_at", + "application" + ], + "properties" : { + "application" : { + "type" : "string", + "description" : "If the label is being applied or removed. Possible values are ā€˜apply’ or ā€˜remove’.", + "example" : "apply" + }, + "details" : { + "type" : "string", + "description" : "Information shown on the Tweet label" + }, + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "event_type" : { + "type" : "string", + "description" : "The type of label on the Tweet", + "example" : "misleading" + }, + "extended_details_url" : { + "type" : "string", + "description" : "Link to more information about this kind of label" + }, + "label_title" : { + "type" : "string", + "description" : "Title/header of the Tweet label" + }, + "tweet" : { + "type" : "object", + "required" : [ + "id", + "author_id" + ], + "properties" : { + "author_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + } + }, + "TweetNoticeSchema" : { + "type" : "object", + "required" : [ + "public_tweet_notice" + ], + "properties" : { + "public_tweet_notice" : { + "$ref" : "#/components/schemas/TweetNotice" + } + } + }, + "TweetTakedownComplianceSchema" : { + "type" : "object", + "required" : [ + "tweet", + "withheld_in_countries", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "quote_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "tweet" : { + "type" : "object", + "required" : [ + "id", + "author_id" + ], + "properties" : { + "author_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + }, + "withheld_in_countries" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/CountryCode" + } + } + } + }, + "TweetText" : { + "type" : "string", + "description" : "The content of the Tweet.", + "example" : "Learn how to use the user Tweet timeline and user mention timeline endpoints in the X API v2 to explore Tweet\\u2026 https:\\/\\/t.co\\/56a0vZUx7i" + }, + "TweetUndropComplianceSchema" : { + "type" : "object", + "required" : [ + "undrop" + ], + "properties" : { + "undrop" : { + "$ref" : "#/components/schemas/TweetComplianceSchema" + } + } + }, + "TweetUnviewable" : { + "type" : "object", + "required" : [ + "tweet", + "event_at", + "application" + ], + "properties" : { + "application" : { + "type" : "string", + "description" : "If the label is being applied or removed. Possible values are ā€˜apply’ or ā€˜remove’.", + "example" : "apply" + }, + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "tweet" : { + "type" : "object", + "required" : [ + "id", + "author_id" + ], + "properties" : { + "author_id" : { + "$ref" : "#/components/schemas/UserId" + }, + "id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + } + } + }, + "TweetUnviewableSchema" : { + "type" : "object", + "required" : [ + "public_tweet_unviewable" + ], + "properties" : { + "public_tweet_unviewable" : { + "$ref" : "#/components/schemas/TweetUnviewable" + } + } + }, + "TweetWithheld" : { + "type" : "object", + "description" : "Indicates withholding details for [withheld content](https://help.twitter.com/en/rules-and-policies/tweet-withheld-by-country).", + "required" : [ + "copyright", + "country_codes" + ], + "properties" : { + "copyright" : { + "type" : "boolean", + "description" : "Indicates if the content is being withheld for on the basis of copyright infringement." + }, + "country_codes" : { + "type" : "array", + "description" : "Provides a list of countries where this content is not available.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "$ref" : "#/components/schemas/CountryCode" + } + }, + "scope" : { + "type" : "string", + "description" : "Indicates whether the content being withheld is the `tweet` or a `user`.", + "enum" : [ + "tweet", + "user" + ] + } + } + }, + "TweetWithheldComplianceSchema" : { + "type" : "object", + "required" : [ + "withheld" + ], + "properties" : { + "withheld" : { + "$ref" : "#/components/schemas/TweetTakedownComplianceSchema" + } + } + }, + "UnlikeComplianceSchema" : { + "type" : "object", + "required" : [ + "favorite", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "favorite" : { + "type" : "object", + "required" : [ + "id", + "user_id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "user_id" : { + "$ref" : "#/components/schemas/UserId" + } + } + } + } + }, + "UnsupportedAuthenticationProblem" : { + "description" : "A problem that indicates that the authentication used is not supported.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + } + ] + }, + "UploadExpiration" : { + "type" : "string", + "description" : "Expiration time of the upload URL.", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "UploadSource" : { + "type" : "object", + "required" : [ + "upload_source" + ], + "properties" : { + "upload_source" : { + "type" : "string", + "description" : "Records the source (e.g., app, device) from which the media was uploaded", + "example" : "gallery" + } + } + }, + "UploadUrl" : { + "type" : "string", + "description" : "URL to which the user will upload their Tweet or user IDs.", + "format" : "uri" + }, + "Url" : { + "type" : "string", + "description" : "A validly formatted URL.", + "format" : "uri", + "example" : "https://developer.twitter.com/en/docs/twitter-api" + }, + "UrlEntity" : { + "description" : "Represent the portion of text recognized as a URL, and its start and end position within the text.", + "allOf" : [ + { + "$ref" : "#/components/schemas/EntityIndicesInclusiveExclusive" + }, + { + "$ref" : "#/components/schemas/UrlFields" + } + ] + }, + "UrlEntityDm" : { + "description" : "Represent the portion of text recognized as a URL, and its start and end position within the text.", + "allOf" : [ + { + "$ref" : "#/components/schemas/EntityIndicesInclusiveExclusive" + }, + { + "$ref" : "#/components/schemas/UrlFields" + } + ] + }, + "UrlFields" : { + "type" : "object", + "description" : "Represent the portion of text recognized as a URL.", + "required" : [ + "url" + ], + "properties" : { + "description" : { + "type" : "string", + "description" : "Description of the URL landing page.", + "example" : "This is a description of the website." + }, + "display_url" : { + "type" : "string", + "description" : "The URL as displayed in the X client.", + "example" : "twittercommunity.com/t/introducing-…" + }, + "expanded_url" : { + "$ref" : "#/components/schemas/Url" + }, + "images" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UrlImage" + } + }, + "media_key" : { + "$ref" : "#/components/schemas/MediaKey" + }, + "status" : { + "$ref" : "#/components/schemas/HttpStatusCode" + }, + "title" : { + "type" : "string", + "description" : "Title of the page the URL points to.", + "example" : "Introducing the v2 follow lookup endpoints" + }, + "unwound_url" : { + "type" : "string", + "description" : "Fully resolved url.", + "format" : "uri", + "example" : "https://twittercommunity.com/t/introducing-the-v2-follow-lookup-endpoints/147118" + }, + "url" : { + "$ref" : "#/components/schemas/Url" + } + } + }, + "UrlImage" : { + "type" : "object", + "description" : "Represent the information for the URL image.", + "properties" : { + "height" : { + "$ref" : "#/components/schemas/MediaHeight" + }, + "url" : { + "$ref" : "#/components/schemas/Url" + }, + "width" : { + "$ref" : "#/components/schemas/MediaWidth" + } + } + }, + "Usage" : { + "type" : "object", + "description" : "Usage per client app", + "properties" : { + "cap_reset_day" : { + "type" : "integer", + "description" : "Number of days left for the Tweet cap to reset", + "format" : "int32" + }, + "daily_client_app_usage" : { + "type" : "array", + "description" : "The daily usage breakdown for each Client Application a project", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/ClientAppUsage" + } + }, + "daily_project_usage" : { + "type" : "object", + "description" : "The daily usage breakdown for a project", + "properties" : { + "project_id" : { + "type" : "integer", + "description" : "The unique identifier for this project", + "format" : "int32" + }, + "usage" : { + "type" : "array", + "description" : "The usage value", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UsageFields" + } + } + } + }, + "project_cap" : { + "type" : "integer", + "description" : "Total number of Posts that can be read in this project per month", + "format" : "int32" + }, + "project_id" : { + "type" : "string", + "description" : "The unique identifier for this project", + "format" : "^[0-9]{1,19}$" + }, + "project_usage" : { + "type" : "integer", + "description" : "The number of Posts read in this project", + "format" : "int32" + } + } + }, + "UsageCapExceededProblem" : { + "description" : "A problem that indicates that a usage cap has been exceeded.", + "allOf" : [ + { + "$ref" : "#/components/schemas/Problem" + }, + { + "type" : "object", + "properties" : { + "period" : { + "type" : "string", + "enum" : [ + "Daily", + "Monthly" + ] + }, + "scope" : { + "type" : "string", + "enum" : [ + "Account", + "Product" + ] + } + } + } + ] + }, + "UsageFields" : { + "type" : "object", + "description" : "Represents the data for Usage", + "properties" : { + "date" : { + "type" : "string", + "description" : "The time period for the usage", + "format" : "date-time", + "example" : "2021-01-06T18:40:40.000Z" + }, + "usage" : { + "type" : "integer", + "description" : "The usage value", + "format" : "int32" + } + } + }, + "User" : { + "type" : "object", + "description" : "The X User object.", + "required" : [ + "id", + "name", + "username" + ], + "properties" : { + "affiliation" : { + "type" : "object", + "description" : "Metadata about a user's affiliation.", + "properties" : { + "badge_url" : { + "type" : "string", + "description" : "The badge URL corresponding to the affiliation.", + "format" : "uri" + }, + "description" : { + "type" : "string", + "description" : "The description of the affiliation." + }, + "url" : { + "type" : "string", + "description" : "The URL, if available, to details about an affiliation.", + "format" : "uri" + }, + "user_id" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UserId" + } + } + } + }, + "connection_status" : { + "type" : "array", + "description" : "Returns detailed information about the relationship between two users.", + "minItems" : 0, + "items" : { + "type" : "string", + "description" : "Type of connection between users.", + "enum" : [ + "follow_request_received", + "follow_request_sent", + "blocking", + "followed_by", + "following", + "muting" + ] + } + }, + "created_at" : { + "type" : "string", + "description" : "Creation time of this User.", + "format" : "date-time" + }, + "description" : { + "type" : "string", + "description" : "The text of this User's profile description (also known as bio), if the User provided one." + }, + "entities" : { + "type" : "object", + "description" : "A list of metadata found in the User's profile description.", + "properties" : { + "description" : { + "$ref" : "#/components/schemas/FullTextEntities" + }, + "url" : { + "type" : "object", + "description" : "Expanded details for the URL specified in the User's profile, with start and end indices.", + "properties" : { + "urls" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/UrlEntity" + } + } + } + } + } + }, + "id" : { + "$ref" : "#/components/schemas/UserId" + }, + "location" : { + "type" : "string", + "description" : "The location specified in the User's profile, if the User provided one. As this is a freeform value, it may not indicate a valid location, but it may be fuzzily evaluated when performing searches with location queries." + }, + "most_recent_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "name" : { + "type" : "string", + "description" : "The friendly name of this User, as shown on their profile." + }, + "pinned_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "profile_banner_url" : { + "type" : "string", + "description" : "The URL to the profile banner for this User.", + "format" : "uri" + }, + "profile_image_url" : { + "type" : "string", + "description" : "The URL to the profile image for this User.", + "format" : "uri" + }, + "protected" : { + "type" : "boolean", + "description" : "Indicates if this User has chosen to protect their Posts (in other words, if this User's Posts are private)." + }, + "public_metrics" : { + "type" : "object", + "description" : "A list of metrics for this User.", + "required" : [ + "followers_count", + "following_count", + "tweet_count", + "listed_count" + ], + "properties" : { + "followers_count" : { + "type" : "integer", + "description" : "Number of Users who are following this User." + }, + "following_count" : { + "type" : "integer", + "description" : "Number of Users this User is following." + }, + "like_count" : { + "type" : "integer", + "description" : "The number of likes created by this User." + }, + "listed_count" : { + "type" : "integer", + "description" : "The number of lists that include this User." + }, + "tweet_count" : { + "type" : "integer", + "description" : "The number of Posts (including Retweets) posted by this User." + } + } + }, + "receives_your_dm" : { + "type" : "boolean", + "description" : "Indicates if you can send a DM to this User" + }, + "subscription_type" : { + "type" : "string", + "description" : "The X Blue subscription type of the user, eg: Basic, Premium, PremiumPlus or None.", + "enum" : [ + "Basic", + "Premium", + "PremiumPlus", + "None" + ] + }, + "url" : { + "type" : "string", + "description" : "The URL specified in the User's profile." + }, + "username" : { + "$ref" : "#/components/schemas/UserName" + }, + "verified" : { + "type" : "boolean", + "description" : "Indicate if this User is a verified X User." + }, + "verified_type" : { + "type" : "string", + "description" : "The X Blue verified type of the user, eg: blue, government, business or none.", + "enum" : [ + "blue", + "government", + "business", + "none" + ] + }, + "withheld" : { + "$ref" : "#/components/schemas/UserWithheld" + } + }, + "example" : { + "created_at" : "2013-12-14T04:35:55Z", + "id" : "2244994945", + "name" : "X Dev", + "protected" : false, + "username" : "TwitterDev" + } + }, + "UserComplianceData" : { + "description" : "User compliance data.", + "oneOf" : [ + { + "$ref" : "#/components/schemas/UserProtectComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserUnprotectComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserDeleteComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserUndeleteComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserSuspendComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserUnsuspendComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserWithheldComplianceSchema" + }, + { + "$ref" : "#/components/schemas/UserScrubGeoSchema" + }, + { + "$ref" : "#/components/schemas/UserProfileModificationComplianceSchema" + } + ] + }, + "UserComplianceSchema" : { + "type" : "object", + "required" : [ + "user", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "user" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/UserId" + } + } + } + } + }, + "UserComplianceStreamResponse" : { + "description" : "User compliance stream events.", + "oneOf" : [ + { + "type" : "object", + "description" : "User compliance event.", + "required" : [ + "data" + ], + "properties" : { + "data" : { + "$ref" : "#/components/schemas/UserComplianceData" + } + } + }, + { + "type" : "object", + "required" : [ + "errors" + ], + "properties" : { + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + } + ] + }, + "UserDeleteComplianceSchema" : { + "type" : "object", + "required" : [ + "user_delete" + ], + "properties" : { + "user_delete" : { + "$ref" : "#/components/schemas/UserComplianceSchema" + } + } + }, + "UserId" : { + "type" : "string", + "description" : "Unique identifier of this User. This is returned as a string in order to avoid complications with languages and tools that cannot handle large integers.", + "pattern" : "^[0-9]{1,19}$", + "example" : "2244994945" + }, + "UserIdMatchesAuthenticatedUser" : { + "type" : "string", + "description" : "Unique identifier of this User. The value must be the same as the authenticated user.", + "example" : "2244994945" + }, + "UserName" : { + "type" : "string", + "description" : "The X handle (screen name) of this user.", + "pattern" : "^[A-Za-z0-9_]{1,15}$" + }, + "UserProfileModificationComplianceSchema" : { + "type" : "object", + "required" : [ + "user_profile_modification" + ], + "properties" : { + "user_profile_modification" : { + "$ref" : "#/components/schemas/UserProfileModificationObjectSchema" + } + } + }, + "UserProfileModificationObjectSchema" : { + "type" : "object", + "required" : [ + "user", + "profile_field", + "new_value", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "new_value" : { + "type" : "string" + }, + "profile_field" : { + "type" : "string" + }, + "user" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/UserId" + } + } + } + } + }, + "UserProtectComplianceSchema" : { + "type" : "object", + "required" : [ + "user_protect" + ], + "properties" : { + "user_protect" : { + "$ref" : "#/components/schemas/UserComplianceSchema" + } + } + }, + "UserScrubGeoObjectSchema" : { + "type" : "object", + "required" : [ + "user", + "up_to_tweet_id", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "up_to_tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "user" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/UserId" + } + } + } + } + }, + "UserScrubGeoSchema" : { + "type" : "object", + "required" : [ + "scrub_geo" + ], + "properties" : { + "scrub_geo" : { + "$ref" : "#/components/schemas/UserScrubGeoObjectSchema" + } + } + }, + "UserSearchQueryVnext" : { + "type" : "string", + "description" : "The the search string by which to query for users.", + "pattern" : "^[A-Za-z0-9_' ]{1,50}$" + }, + "UserSuspendComplianceSchema" : { + "type" : "object", + "required" : [ + "user_suspend" + ], + "properties" : { + "user_suspend" : { + "$ref" : "#/components/schemas/UserComplianceSchema" + } + } + }, + "UserTakedownComplianceSchema" : { + "type" : "object", + "required" : [ + "user", + "withheld_in_countries", + "event_at" + ], + "properties" : { + "event_at" : { + "type" : "string", + "description" : "Event time.", + "format" : "date-time", + "example" : "2021-07-06T18:40:40.000Z" + }, + "user" : { + "type" : "object", + "required" : [ + "id" + ], + "properties" : { + "id" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "withheld_in_countries" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/CountryCode" + } + } + } + }, + "UserUndeleteComplianceSchema" : { + "type" : "object", + "required" : [ + "user_undelete" + ], + "properties" : { + "user_undelete" : { + "$ref" : "#/components/schemas/UserComplianceSchema" + } + } + }, + "UserUnprotectComplianceSchema" : { + "type" : "object", + "required" : [ + "user_unprotect" + ], + "properties" : { + "user_unprotect" : { + "$ref" : "#/components/schemas/UserComplianceSchema" + } + } + }, + "UserUnsuspendComplianceSchema" : { + "type" : "object", + "required" : [ + "user_unsuspend" + ], + "properties" : { + "user_unsuspend" : { + "$ref" : "#/components/schemas/UserComplianceSchema" + } + } + }, + "UserWithheld" : { + "type" : "object", + "description" : "Indicates withholding details for [withheld content](https://help.twitter.com/en/rules-and-policies/tweet-withheld-by-country).", + "required" : [ + "country_codes" + ], + "properties" : { + "country_codes" : { + "type" : "array", + "description" : "Provides a list of countries where this content is not available.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "$ref" : "#/components/schemas/CountryCode" + } + }, + "scope" : { + "type" : "string", + "description" : "Indicates that the content being withheld is a `user`.", + "enum" : [ + "user" + ] + } + } + }, + "UserWithheldComplianceSchema" : { + "type" : "object", + "required" : [ + "user_withheld" + ], + "properties" : { + "user_withheld" : { + "$ref" : "#/components/schemas/UserTakedownComplianceSchema" + } + } + }, + "UsersDMBlockCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "blocked" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersDMUnBlockCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "blocked" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersFollowingCreateRequest" : { + "type" : "object", + "required" : [ + "target_user_id" + ], + "properties" : { + "target_user_id" : { + "$ref" : "#/components/schemas/UserId" + } + } + }, + "UsersFollowingCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "following" : { + "type" : "boolean" + }, + "pending_follow" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersFollowingDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "following" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersLikesCreateRequest" : { + "type" : "object", + "required" : [ + "tweet_id" + ], + "properties" : { + "tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + } + } + }, + "UsersLikesCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "liked" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersLikesDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "liked" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersRetweetsCreateRequest" : { + "type" : "object", + "required" : [ + "tweet_id" + ], + "properties" : { + "tweet_id" : { + "$ref" : "#/components/schemas/TweetId" + } + }, + "additionalProperties" : false + }, + "UsersRetweetsCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "id" : { + "$ref" : "#/components/schemas/TweetId" + }, + "retweeted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "UsersRetweetsDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "retweeted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "Variant" : { + "type" : "object", + "properties" : { + "bit_rate" : { + "type" : "integer", + "description" : "The bit rate of the media." + }, + "content_type" : { + "type" : "string", + "description" : "The content type of the media." + }, + "url" : { + "type" : "string", + "description" : "The url to the media.", + "format" : "uri" + } + } + }, + "Variants" : { + "type" : "array", + "description" : "An array of all available variants of the media.", + "items" : { + "$ref" : "#/components/schemas/Variant" + } + }, + "Video" : { + "allOf" : [ + { + "$ref" : "#/components/schemas/Media" + }, + { + "type" : "object", + "properties" : { + "duration_ms" : { + "type" : "integer" + }, + "non_public_metrics" : { + "type" : "object", + "description" : "Nonpublic engagement metrics for the Media at the time of the request.", + "properties" : { + "playback_0_count" : { + "type" : "integer", + "description" : "Number of users who made it through 0% of the video.", + "format" : "int32" + }, + "playback_100_count" : { + "type" : "integer", + "description" : "Number of users who made it through 100% of the video.", + "format" : "int32" + }, + "playback_25_count" : { + "type" : "integer", + "description" : "Number of users who made it through 25% of the video.", + "format" : "int32" + }, + "playback_50_count" : { + "type" : "integer", + "description" : "Number of users who made it through 50% of the video.", + "format" : "int32" + }, + "playback_75_count" : { + "type" : "integer", + "description" : "Number of users who made it through 75% of the video.", + "format" : "int32" + } + } + }, + "organic_metrics" : { + "type" : "object", + "description" : "Organic nonpublic engagement metrics for the Media at the time of the request.", + "properties" : { + "playback_0_count" : { + "type" : "integer", + "description" : "Number of users who made it through 0% of the video.", + "format" : "int32" + }, + "playback_100_count" : { + "type" : "integer", + "description" : "Number of users who made it through 100% of the video.", + "format" : "int32" + }, + "playback_25_count" : { + "type" : "integer", + "description" : "Number of users who made it through 25% of the video.", + "format" : "int32" + }, + "playback_50_count" : { + "type" : "integer", + "description" : "Number of users who made it through 50% of the video.", + "format" : "int32" + }, + "playback_75_count" : { + "type" : "integer", + "description" : "Number of users who made it through 75% of the video.", + "format" : "int32" + }, + "view_count" : { + "type" : "integer", + "description" : "Number of times this video has been viewed.", + "format" : "int32" + } + } + }, + "preview_image_url" : { + "type" : "string", + "format" : "uri" + }, + "promoted_metrics" : { + "type" : "object", + "description" : "Promoted nonpublic engagement metrics for the Media at the time of the request.", + "properties" : { + "playback_0_count" : { + "type" : "integer", + "description" : "Number of users who made it through 0% of the video.", + "format" : "int32" + }, + "playback_100_count" : { + "type" : "integer", + "description" : "Number of users who made it through 100% of the video.", + "format" : "int32" + }, + "playback_25_count" : { + "type" : "integer", + "description" : "Number of users who made it through 25% of the video.", + "format" : "int32" + }, + "playback_50_count" : { + "type" : "integer", + "description" : "Number of users who made it through 50% of the video.", + "format" : "int32" + }, + "playback_75_count" : { + "type" : "integer", + "description" : "Number of users who made it through 75% of the video.", + "format" : "int32" + }, + "view_count" : { + "type" : "integer", + "description" : "Number of times this video has been viewed.", + "format" : "int32" + } + } + }, + "public_metrics" : { + "type" : "object", + "description" : "Engagement metrics for the Media at the time of the request.", + "properties" : { + "view_count" : { + "type" : "integer", + "description" : "Number of times this video has been viewed.", + "format" : "int32" + } + } + }, + "variants" : { + "$ref" : "#/components/schemas/Variants" + } + } + } + ] + }, + "WebhookConfig" : { + "type" : "object", + "description" : "A Webhook Configuration", + "required" : [ + "id", + "url", + "valid", + "created_at" + ], + "properties" : { + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "id" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "url" : { + "type" : "string", + "description" : "The callback URL of the webhook." + }, + "valid" : { + "type" : "boolean" + } + } + }, + "WebhookConfigCreateRequest" : { + "type" : "object", + "required" : [ + "url" + ], + "properties" : { + "url" : { + "type" : "string", + "minLength" : 1, + "maxLength" : 200 + } + } + }, + "WebhookConfigCreateResponse" : { + "type" : "object", + "description" : "A Webhook Configuration", + "required" : [ + "id", + "url", + "valid", + "created_at" + ], + "properties" : { + "created_at" : { + "type" : "string", + "format" : "date-time" + }, + "id" : { + "$ref" : "#/components/schemas/WebhookConfigId" + }, + "url" : { + "type" : "string", + "description" : "The callback URL of the webhook." + }, + "valid" : { + "type" : "boolean" + } + } + }, + "WebhookConfigDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "WebhookConfigId" : { + "type" : "string", + "description" : "The unique identifier of this webhook config.", + "pattern" : "^[0-9]{1,19}$", + "example" : "1146654567674912769" + }, + "WebhookConfigPutResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "attempted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "WebhookLinksCreateResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "provisioned" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "WebhookLinksDeleteResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "properties" : { + "deleted" : { + "type" : "boolean" + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "WebhookLinksGetResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "object", + "description" : "The list of active webhook links for a given stream", + "required" : [ + "links" + ], + "properties" : { + "links" : { + "type" : "array", + "description" : "list of links", + "items" : { + "type" : "object", + "properties" : { + "application_id" : { + "type" : "string", + "description" : "The application ID" + }, + "business_user_id" : { + "type" : "string", + "description" : "The user ID" + }, + "created_at" : { + "type" : "string", + "description" : "The datetime the webhook was linked to the stream", + "format" : "data-time" + }, + "fields" : { + "type" : "array", + "description" : "Requested fields to be rendered", + "items" : { + "type" : "string", + "description" : "A query-parameter formatted field or expansion, e.g., 'expansions=author_id' or 'user.fields=name,username'" + } + }, + "instance_id" : { + "type" : "string", + "description" : "The stream ID associated with the FilteredStream instance" + }, + "webhook_id" : { + "type" : "string", + "description" : "The unique identifier for the webhook" + } + } + } + } + } + }, + "errors" : { + "type" : "array", + "minItems" : 1, + "items" : { + "$ref" : "#/components/schemas/Problem" + } + } + } + }, + "WebhookReplayCreateRequest" : { + "type" : "object", + "required" : [ + "webhook_id", + "from_date", + "to_date" + ], + "properties" : { + "from_date" : { + "type" : "string", + "description" : "The oldest (starting) UTC timestamp (inclusive) from which events will be provided, in yyyymmddhhmm format.", + "pattern" : "^[0-9]{12}$", + "example" : "202504242000" + }, + "to_date" : { + "type" : "string", + "description" : "The oldest (starting) UTC timestamp (inclusive) from which events will be provided, in yyyymmddhhmm format.", + "pattern" : "^[0-9]{12}$", + "example" : "202504242000" + }, + "webhook_id" : { + "$ref" : "#/components/schemas/WebhookConfigId" + } + } + } + }, + "parameters" : { + "AnalyticsFieldsParameter" : { + "name" : "analytics.fields", + "in" : "query", + "description" : "A comma separated list of Analytics fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Analytics object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "app_install_attempts", + "app_opens", + "bookmarks", + "detail_expands", + "email_tweet", + "engagements", + "follows", + "hashtag_clicks", + "id", + "impressions", + "likes", + "media_views", + "permalink_clicks", + "quote_tweets", + "replies", + "retweets", + "shares", + "timestamp", + "unfollows", + "unlikes", + "url_clicks", + "user_profile_clicks" + ] + }, + "example" : [ + "app_install_attempts", + "app_opens", + "bookmarks", + "detail_expands", + "email_tweet", + "engagements", + "follows", + "hashtag_clicks", + "id", + "impressions", + "likes", + "media_views", + "permalink_clicks", + "quote_tweets", + "replies", + "retweets", + "shares", + "timestamp", + "unfollows", + "unlikes", + "url_clicks", + "user_profile_clicks" + ] + }, + "explode" : false, + "style" : "form" + }, + "CommunityFieldsParameter" : { + "name" : "community.fields", + "in" : "query", + "description" : "A comma separated list of Community fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Community object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "access", + "created_at", + "description", + "id", + "join_policy", + "member_count", + "name" + ] + }, + "example" : [ + "access", + "created_at", + "description", + "id", + "join_policy", + "member_count", + "name" + ] + }, + "explode" : false, + "style" : "form" + }, + "ComplianceJobFieldsParameter" : { + "name" : "compliance_job.fields", + "in" : "query", + "description" : "A comma separated list of ComplianceJob fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a ComplianceJob object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "created_at", + "download_expires_at", + "download_url", + "id", + "name", + "resumable", + "status", + "type", + "upload_expires_at", + "upload_url" + ] + }, + "example" : [ + "created_at", + "download_expires_at", + "download_url", + "id", + "name", + "resumable", + "status", + "type", + "upload_expires_at", + "upload_url" + ] + }, + "explode" : false, + "style" : "form" + }, + "ConnectionFieldsParameter" : { + "name" : "connection.fields", + "in" : "query", + "description" : "A comma separated list of Connection fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Connection object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "client_ip", + "connected_at", + "disconnect_reason", + "disconnected_at", + "endpoint_name", + "id" + ] + }, + "example" : [ + "client_ip", + "connected_at", + "disconnect_reason", + "disconnected_at", + "endpoint_name", + "id" + ] + }, + "explode" : false, + "style" : "form" + }, + "DmConversationFieldsParameter" : { + "name" : "dm_conversation.fields", + "in" : "query", + "description" : "A comma separated list of DmConversation fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a DmConversation object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "id" + ] + }, + "example" : [ + "id" + ] + }, + "explode" : false, + "style" : "form" + }, + "DmEventExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [DmEvent](#DmEvent) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "attachments.media_keys", + "participant_ids", + "referenced_tweets.id", + "sender_id" + ] + }, + "example" : [ + "attachments.media_keys", + "participant_ids", + "referenced_tweets.id", + "sender_id" + ] + }, + "explode" : false, + "style" : "form" + }, + "DmEventFieldsParameter" : { + "name" : "dm_event.fields", + "in" : "query", + "description" : "A comma separated list of DmEvent fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a DmEvent object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "attachments", + "created_at", + "dm_conversation_id", + "entities", + "event_type", + "id", + "participant_ids", + "referenced_tweets", + "sender_id", + "text" + ] + }, + "example" : [ + "attachments", + "created_at", + "dm_conversation_id", + "entities", + "event_type", + "id", + "participant_ids", + "referenced_tweets", + "sender_id", + "text" + ] + }, + "explode" : false, + "style" : "form" + }, + "EngagementFieldsParameter" : { + "name" : "engagement.fields", + "in" : "query", + "description" : "A comma separated list of Engagement fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Engagement object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "errors", + "measurement" + ] + }, + "example" : [ + "errors", + "measurement" + ] + }, + "explode" : false, + "style" : "form" + }, + "LikeExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [Like](#Like) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "liked_tweet_id" + ] + }, + "example" : [ + "liked_tweet_id" + ] + }, + "explode" : false, + "style" : "form" + }, + "LikeFieldsParameter" : { + "name" : "like.fields", + "in" : "query", + "description" : "A comma separated list of Like fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Like object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "created_at", + "id", + "liked_tweet_id", + "timestamp_ms" + ] + }, + "example" : [ + "created_at", + "id", + "liked_tweet_id", + "timestamp_ms" + ] + }, + "explode" : false, + "style" : "form" + }, + "LikeWithTweetAuthorExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [LikeWithTweetAuthor](#LikeWithTweetAuthor) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "liked_tweet_author_id", + "liked_tweet_id" + ] + }, + "example" : [ + "liked_tweet_author_id", + "liked_tweet_id" + ] + }, + "explode" : false, + "style" : "form" + }, + "LikeWithTweetAuthorFieldsParameter" : { + "name" : "like_with_tweet_author.fields", + "in" : "query", + "description" : "A comma separated list of LikeWithTweetAuthor fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a LikeWithTweetAuthor object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "created_at", + "id", + "liked_tweet_author_id", + "liked_tweet_id", + "timestamp_ms" + ] + }, + "example" : [ + "created_at", + "id", + "liked_tweet_author_id", + "liked_tweet_id", + "timestamp_ms" + ] + }, + "explode" : false, + "style" : "form" + }, + "ListExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [List](#List) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "owner_id" + ] + }, + "example" : [ + "owner_id" + ] + }, + "explode" : false, + "style" : "form" + }, + "ListFieldsParameter" : { + "name" : "list.fields", + "in" : "query", + "description" : "A comma separated list of List fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a List object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "created_at", + "description", + "follower_count", + "id", + "member_count", + "name", + "owner_id", + "private" + ] + }, + "example" : [ + "created_at", + "description", + "follower_count", + "id", + "member_count", + "name", + "owner_id", + "private" + ] + }, + "explode" : false, + "style" : "form" + }, + "MediaAnalyticsFieldsParameter" : { + "name" : "media_analytics.fields", + "in" : "query", + "description" : "A comma separated list of MediaAnalytics fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a MediaAnalytics object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "cta_url_clicks", + "cta_watch_clicks", + "media_key", + "play_from_tap", + "playback25", + "playback50", + "playback75", + "playback_complete", + "playback_start", + "timestamp", + "video_views", + "watch_time_ms" + ] + }, + "example" : [ + "cta_url_clicks", + "cta_watch_clicks", + "media_key", + "play_from_tap", + "playback25", + "playback50", + "playback75", + "playback_complete", + "playback_start", + "timestamp", + "video_views", + "watch_time_ms" + ] + }, + "explode" : false, + "style" : "form" + }, + "MediaFieldsParameter" : { + "name" : "media.fields", + "in" : "query", + "description" : "A comma separated list of Media fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Media object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "alt_text", + "duration_ms", + "height", + "media_key", + "non_public_metrics", + "organic_metrics", + "preview_image_url", + "promoted_metrics", + "public_metrics", + "type", + "url", + "variants", + "width" + ] + }, + "example" : [ + "alt_text", + "duration_ms", + "height", + "media_key", + "non_public_metrics", + "organic_metrics", + "preview_image_url", + "promoted_metrics", + "public_metrics", + "type", + "url", + "variants", + "width" + ] + }, + "explode" : false, + "style" : "form" + }, + "NewsFieldsParameter" : { + "name" : "news.fields", + "in" : "query", + "description" : "A comma separated list of News fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a News object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "category", + "cluster_posts_results", + "contexts", + "disclaimer", + "hook", + "id", + "keywords", + "name", + "summary", + "updated_at" + ] + }, + "example" : [ + "category", + "cluster_posts_results", + "contexts", + "disclaimer", + "hook", + "id", + "keywords", + "name", + "summary", + "updated_at" + ] + }, + "explode" : false, + "style" : "form" + }, + "NoteFieldsParameter" : { + "name" : "note.fields", + "in" : "query", + "description" : "A comma separated list of Note fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Note object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "id", + "info", + "status", + "test_result" + ] + }, + "example" : [ + "id", + "info", + "status", + "test_result" + ] + }, + "explode" : false, + "style" : "form" + }, + "PersonalizedTrendFieldsParameter" : { + "name" : "personalized_trend.fields", + "in" : "query", + "description" : "A comma separated list of PersonalizedTrend fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a PersonalizedTrend object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "category", + "post_count", + "trend_name", + "trending_since" + ] + }, + "example" : [ + "category", + "post_count", + "trend_name", + "trending_since" + ] + }, + "explode" : false, + "style" : "form" + }, + "PlaceFieldsParameter" : { + "name" : "place.fields", + "in" : "query", + "description" : "A comma separated list of Place fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Place object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "contained_within", + "country", + "country_code", + "full_name", + "geo", + "id", + "name", + "place_type" + ] + }, + "example" : [ + "contained_within", + "country", + "country_code", + "full_name", + "geo", + "id", + "name", + "place_type" + ] + }, + "explode" : false, + "style" : "form" + }, + "PlaidAccountContactFieldsParameter" : { + "name" : "plaid_account_contact.fields", + "in" : "query", + "description" : "A comma separated list of PlaidAccountContact fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a PlaidAccountContact object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "addresses", + "emails", + "holders", + "telephones" + ] + }, + "example" : [ + "addresses", + "emails", + "holders", + "telephones" + ] + }, + "explode" : false, + "style" : "form" + }, + "PlaidAccountFieldsParameter" : { + "name" : "plaid_account.fields", + "in" : "query", + "description" : "A comma separated list of PlaidAccount fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a PlaidAccount object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "accountCategory", + "accountId", + "accountNumberDisplay", + "accountType", + "availableBalance", + "currency", + "currentBalance", + "nickname", + "productName", + "status" + ] + }, + "example" : [ + "accountCategory", + "accountId", + "accountNumberDisplay", + "accountType", + "availableBalance", + "currency", + "currentBalance", + "nickname", + "productName", + "status" + ] + }, + "explode" : false, + "style" : "form" + }, + "PlaidAccountPaymentNetworkFieldsParameter" : { + "name" : "plaid_account_payment_network.fields", + "in" : "query", + "description" : "A comma separated list of PlaidAccountPaymentNetwork fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a PlaidAccountPaymentNetwork object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "bankId", + "identifier", + "transferIn", + "transferOut", + "type" + ] + }, + "example" : [ + "bankId", + "identifier", + "transferIn", + "transferOut", + "type" + ] + }, + "explode" : false, + "style" : "form" + }, + "PlaidAccountTransactionFieldsParameter" : { + "name" : "plaid_account_transaction.fields", + "in" : "query", + "description" : "A comma separated list of PlaidAccountTransaction fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a PlaidAccountTransaction object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "accountCategory", + "amount", + "debitCreditMemo", + "description", + "postedTimestamp", + "status", + "transactionId", + "transactionTimestamp" + ] + }, + "example" : [ + "accountCategory", + "amount", + "debitCreditMemo", + "description", + "postedTimestamp", + "status", + "transactionId", + "transactionTimestamp" + ] + }, + "explode" : false, + "style" : "form" + }, + "PlaidCustomerFieldsParameter" : { + "name" : "plaid_customer.fields", + "in" : "query", + "description" : "A comma separated list of PlaidCustomer fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a PlaidCustomer object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "customerId" + ] + }, + "example" : [ + "customerId" + ] + }, + "explode" : false, + "style" : "form" + }, + "PollFieldsParameter" : { + "name" : "poll.fields", + "in" : "query", + "description" : "A comma separated list of Poll fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Poll object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "duration_minutes", + "end_datetime", + "id", + "options", + "voting_status" + ] + }, + "example" : [ + "duration_minutes", + "end_datetime", + "id", + "options", + "voting_status" + ] + }, + "explode" : false, + "style" : "form" + }, + "RulesCountFieldsParameter" : { + "name" : "rules_count.fields", + "in" : "query", + "description" : "A comma separated list of RulesCount fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a RulesCount object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "all_project_client_apps", + "cap_per_client_app", + "cap_per_project", + "client_app_rules_count", + "project_rules_count" + ] + }, + "example" : [ + "all_project_client_apps", + "cap_per_client_app", + "cap_per_project", + "client_app_rules_count", + "project_rules_count" + ] + }, + "explode" : false, + "style" : "form" + }, + "SearchCountFieldsParameter" : { + "name" : "search_count.fields", + "in" : "query", + "description" : "A comma separated list of SearchCount fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a SearchCount object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "end", + "start", + "tweet_count" + ] + }, + "example" : [ + "end", + "start", + "tweet_count" + ] + }, + "explode" : false, + "style" : "form" + }, + "SpaceExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [Space](#Space) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "creator_id", + "host_ids", + "invited_user_ids", + "speaker_ids", + "topic_ids" + ] + }, + "example" : [ + "creator_id", + "host_ids", + "invited_user_ids", + "speaker_ids", + "topic_ids" + ] + }, + "explode" : false, + "style" : "form" + }, + "SpaceFieldsParameter" : { + "name" : "space.fields", + "in" : "query", + "description" : "A comma separated list of Space fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Space object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "created_at", + "creator_id", + "ended_at", + "host_ids", + "id", + "invited_user_ids", + "is_ticketed", + "lang", + "participant_count", + "scheduled_start", + "speaker_ids", + "started_at", + "state", + "subscriber_count", + "title", + "topic_ids", + "updated_at" + ] + }, + "example" : [ + "created_at", + "creator_id", + "ended_at", + "host_ids", + "id", + "invited_user_ids", + "is_ticketed", + "lang", + "participant_count", + "scheduled_start", + "speaker_ids", + "started_at", + "state", + "subscriber_count", + "title", + "topic_ids", + "updated_at" + ] + }, + "explode" : false, + "style" : "form" + }, + "TopicFieldsParameter" : { + "name" : "topic.fields", + "in" : "query", + "description" : "A comma separated list of Topic fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Topic object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "description", + "id", + "name" + ] + }, + "example" : [ + "description", + "id", + "name" + ] + }, + "explode" : false, + "style" : "form" + }, + "TrendFieldsParameter" : { + "name" : "trend.fields", + "in" : "query", + "description" : "A comma separated list of Trend fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Trend object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "trend_name", + "tweet_count" + ] + }, + "example" : [ + "trend_name", + "tweet_count" + ] + }, + "explode" : false, + "style" : "form" + }, + "TweetExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [Tweet](#Tweet) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "article.cover_media", + "article.media_entities", + "attachments.media_keys", + "attachments.media_source_tweet", + "attachments.poll_ids", + "author_id", + "edit_history_tweet_ids", + "entities.mentions.username", + "geo.place_id", + "in_reply_to_user_id", + "entities.note.mentions.username", + "referenced_tweets.id", + "referenced_tweets.id.attachments.media_keys", + "referenced_tweets.id.author_id" + ] + }, + "example" : [ + "article.cover_media", + "article.media_entities", + "attachments.media_keys", + "attachments.media_source_tweet", + "attachments.poll_ids", + "author_id", + "edit_history_tweet_ids", + "entities.mentions.username", + "geo.place_id", + "in_reply_to_user_id", + "entities.note.mentions.username", + "referenced_tweets.id", + "referenced_tweets.id.attachments.media_keys", + "referenced_tweets.id.author_id" + ] + }, + "explode" : false, + "style" : "form" + }, + "TweetFieldsParameter" : { + "name" : "tweet.fields", + "in" : "query", + "description" : "A comma separated list of Tweet fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Tweet object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "article", + "attachments", + "author_id", + "card_uri", + "community_id", + "context_annotations", + "conversation_id", + "created_at", + "display_text_range", + "edit_controls", + "edit_history_tweet_ids", + "entities", + "geo", + "id", + "in_reply_to_user_id", + "lang", + "media_metadata", + "non_public_metrics", + "note_tweet", + "organic_metrics", + "possibly_sensitive", + "promoted_metrics", + "public_metrics", + "referenced_tweets", + "reply_settings", + "scopes", + "source", + "suggested_source_links", + "suggested_source_links_with_counts", + "text", + "withheld" + ] + }, + "example" : [ + "article", + "attachments", + "author_id", + "card_uri", + "community_id", + "context_annotations", + "conversation_id", + "created_at", + "display_text_range", + "edit_controls", + "edit_history_tweet_ids", + "entities", + "geo", + "id", + "in_reply_to_user_id", + "lang", + "media_metadata", + "non_public_metrics", + "note_tweet", + "organic_metrics", + "possibly_sensitive", + "promoted_metrics", + "public_metrics", + "referenced_tweets", + "reply_settings", + "scopes", + "source", + "suggested_source_links", + "suggested_source_links_with_counts", + "text", + "withheld" + ] + }, + "explode" : false, + "style" : "form" + }, + "UsageFieldsParameter" : { + "name" : "usage.fields", + "in" : "query", + "description" : "A comma separated list of Usage fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a Usage object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "cap_reset_day", + "daily_client_app_usage", + "daily_project_usage", + "project_cap", + "project_id", + "project_usage" + ] + }, + "example" : [ + "cap_reset_day", + "daily_client_app_usage", + "daily_project_usage", + "project_cap", + "project_id", + "project_usage" + ] + }, + "explode" : false, + "style" : "form" + }, + "UserExpansionsParameter" : { + "name" : "expansions", + "in" : "query", + "description" : "A comma separated list of fields to expand.", + "schema" : { + "type" : "array", + "description" : "The list of fields you can expand for a [User](#User) object. If the field has an ID, it can be expanded into a full object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "affiliation.user_id", + "most_recent_tweet_id", + "pinned_tweet_id" + ] + }, + "example" : [ + "affiliation.user_id", + "most_recent_tweet_id", + "pinned_tweet_id" + ] + }, + "explode" : false, + "style" : "form" + }, + "UserFieldsParameter" : { + "name" : "user.fields", + "in" : "query", + "description" : "A comma separated list of User fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a User object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "affiliation", + "confirmed_email", + "connection_status", + "created_at", + "description", + "entities", + "id", + "is_identity_verified", + "location", + "most_recent_tweet_id", + "name", + "parody", + "pinned_tweet_id", + "profile_banner_url", + "profile_image_url", + "protected", + "public_metrics", + "receives_your_dm", + "subscription", + "subscription_type", + "url", + "username", + "verified", + "verified_followers_count", + "verified_type", + "withheld" + ] + }, + "example" : [ + "affiliation", + "confirmed_email", + "connection_status", + "created_at", + "description", + "entities", + "id", + "is_identity_verified", + "location", + "most_recent_tweet_id", + "name", + "parody", + "pinned_tweet_id", + "profile_banner_url", + "profile_image_url", + "protected", + "public_metrics", + "receives_your_dm", + "subscription", + "subscription_type", + "url", + "username", + "verified", + "verified_followers_count", + "verified_type", + "withheld" + ] + }, + "explode" : false, + "style" : "form" + }, + "WebhookConfigFieldsParameter" : { + "name" : "webhook_config.fields", + "in" : "query", + "description" : "A comma separated list of WebhookConfig fields to display.", + "required" : false, + "schema" : { + "type" : "array", + "description" : "The fields available for a WebhookConfig object.", + "minItems" : 1, + "uniqueItems" : true, + "items" : { + "type" : "string", + "enum" : [ + "created_at", + "id", + "url", + "valid" + ] + }, + "example" : [ + "created_at", + "id", + "url", + "valid" + ] + }, + "explode" : false, + "style" : "form" + } + } + } +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f08fc5d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +fastmcp +httpx +python-dotenv +xai-sdk +fastapi +uvicorn +requests +tweepy diff --git a/server.py b/server.py new file mode 100644 index 0000000..4bdf935 --- /dev/null +++ b/server.py @@ -0,0 +1,273 @@ +import copy +import json +import logging +import os +from pathlib import Path + +import httpx +from fastmcp import FastMCP + +HTTP_METHODS = { + "get", + "post", + "put", + "patch", + "delete", + "options", + "head", + "trace", +} + +LOGGER = logging.getLogger("xmcp.x_api") + + +def is_truthy(value: str | None) -> bool: + if value is None: + return False + return value.strip().lower() in {"1", "true", "yes", "on"} + + +def parse_csv_env(key: str) -> set[str]: + raw = os.getenv(key, "") + if not raw.strip(): + return set() + return {item.strip() for item in raw.split(",") if item.strip()} + + +def should_join_query_param(param: dict) -> bool: + if param.get("in") != "query": + return False + schema = param.get("schema", {}) + if schema.get("type") != "array": + return False + return param.get("explode") is False + + +def collect_comma_params(spec: dict) -> set[str]: + comma_params: set[str] = set() + components = spec.get("components", {}).get("parameters", {}) + for param in components.values(): + if isinstance(param, dict) and should_join_query_param(param): + name = param.get("name") + if isinstance(name, str): + comma_params.add(name) + + for item in spec.get("paths", {}).values(): + if not isinstance(item, dict): + continue + for method, operation in item.items(): + if method.lower() not in HTTP_METHODS or not isinstance(operation, dict): + continue + for param in operation.get("parameters", []): + if not isinstance(param, dict) or "$ref" in param: + continue + if should_join_query_param(param): + name = param.get("name") + if isinstance(name, str): + comma_params.add(name) + + return comma_params + + +def load_openapi_spec() -> dict: + spec_path = Path(__file__).resolve().parent / "openapi.json" + with spec_path.open("r", encoding="utf-8") as handle: + return json.load(handle) + + +def load_env() -> None: + env_path = Path(__file__).resolve().parent / ".env" + if not env_path.exists(): + return + try: + from dotenv import load_dotenv + except ImportError: + return + load_dotenv(env_path) + + +def setup_logging() -> bool: + debug_enabled = is_truthy(os.getenv("X_API_DEBUG", "1")) + if debug_enabled: + logging.basicConfig(level=logging.INFO) + LOGGER.setLevel(logging.INFO) + return debug_enabled + + +def should_exclude_operation(path: str, operation: dict) -> bool: + if "/webhooks" in path or "/stream" in path: + return True + + tags = [tag.lower() for tag in operation.get("tags", []) if isinstance(tag, str)] + if "stream" in tags or "webhooks" in tags: + return True + + if operation.get("x-twitter-streaming") is True: + return True + + return False + + +def filter_openapi_spec(spec: dict) -> dict: + filtered = copy.deepcopy(spec) + paths = filtered.get("paths", {}) + new_paths = {} + allow_tags = {tag.lower() for tag in parse_csv_env("X_API_TOOL_TAGS")} + allow_ops = parse_csv_env("X_API_TOOL_ALLOWLIST") + deny_ops = parse_csv_env("X_API_TOOL_DENYLIST") + + for path, item in paths.items(): + if not isinstance(item, dict): + continue + + new_item = {} + for key, value in item.items(): + if key.lower() in HTTP_METHODS: + if should_exclude_operation(path, value): + continue + operation_id = value.get("operationId") + operation_tags = [ + tag.lower() + for tag in value.get("tags", []) + if isinstance(tag, str) + ] + if allow_tags and not (set(operation_tags) & allow_tags): + continue + if allow_ops and operation_id not in allow_ops: + continue + if deny_ops and operation_id in deny_ops: + continue + new_item[key] = value + else: + new_item[key] = value + + if any(method.lower() in HTTP_METHODS for method in new_item.keys()): + new_paths[path] = new_item + + filtered["paths"] = new_paths + return filtered + + +def print_tool_list(spec: dict) -> None: + tools: list[str] = [] + for path, item in spec.get("paths", {}).items(): + if not isinstance(item, dict): + continue + for method, operation in item.items(): + if method.lower() not in HTTP_METHODS or not isinstance(operation, dict): + continue + op_id = operation.get("operationId") + if op_id: + tools.append(op_id) + else: + tools.append(f"{method.upper()} {path}") + + tools.sort() + print(f"Loaded {len(tools)} tools from OpenAPI:") + for tool in tools: + print(f"- {tool}") + + +def get_auth_headers() -> dict: + oauth_token = os.getenv("X_OAUTH_ACCESS_TOKEN", "").strip() + bearer_token = os.getenv("X_BEARER_TOKEN", "").strip() + token = oauth_token or bearer_token + if not token: + raise RuntimeError( + "Set X_OAUTH_ACCESS_TOKEN or X_BEARER_TOKEN to authenticate with the X API." + ) + return {"Authorization": f"Bearer {token}"} + + +def create_mcp() -> FastMCP: + load_env() + debug_enabled = setup_logging() + parser_flag = os.getenv("FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER") + if parser_flag is not None: + os.environ["FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER"] = parser_flag + + base_url = os.getenv("X_API_BASE_URL", "https://api.x.com") + timeout = float(os.getenv("X_API_TIMEOUT", "30")) + + spec = load_openapi_spec() + filtered_spec = filter_openapi_spec(spec) + comma_params = collect_comma_params(filtered_spec) + print_tool_list(filtered_spec) + async def normalize_query_params(request: httpx.Request) -> None: + if not comma_params: + return + params = list(request.url.params.multi_items()) + grouped: dict[str, list[str]] = {} + ordered: list[str] = [] + normalized: list[tuple[str, str]] = [] + + for key, value in params: + if key in comma_params: + if key not in grouped: + ordered.append(key) + grouped.setdefault(key, []).append(value) + else: + normalized.append((key, value)) + + if not grouped: + return + + for key in ordered: + values: list[str] = [] + for raw in grouped[key]: + for part in raw.split(","): + part = part.strip() + if part and part not in values: + values.append(part) + if values: + normalized.append((key, ",".join(values))) + + request.url = request.url.copy_with(params=normalized) + + async def log_request(request: httpx.Request) -> None: + if not debug_enabled: + return + LOGGER.info("X API request %s %s", request.method, request.url) + + async def log_response(response: httpx.Response) -> None: + if not debug_enabled: + return + LOGGER.info( + "X API response %s %s -> %s", + response.request.method, + response.request.url, + response.status_code, + ) + if response.status_code >= 400: + body = await response.aread() + text = body.decode("utf-8", errors="replace") + if len(text) > 1000: + text = text[:1000] + "..." + LOGGER.warning("X API error body: %s", text) + + client = httpx.AsyncClient( + base_url=base_url, + headers=get_auth_headers(), + timeout=timeout, + event_hooks={ + "request": [normalize_query_params, log_request], + "response": [log_response], + }, + ) + return FastMCP.from_openapi( + openapi_spec=filtered_spec, + client=client, + name="X API MCP", + ) + + +def main() -> None: + host = os.getenv("MCP_HOST", "0.0.0.0") + port_value = os.getenv("PORT") or os.getenv("MCP_PORT", "8000") + port = int(port_value) + mcp = create_mcp() + mcp.run(transport="http", host=host, port=port) + + +if __name__ == "__main__": + main() diff --git a/timeline_server.py b/timeline_server.py new file mode 100644 index 0000000..6fe2645 --- /dev/null +++ b/timeline_server.py @@ -0,0 +1,150 @@ +import os +from typing import Any, Dict, List, Optional + +from fastapi import FastAPI, HTTPException +from pydantic import BaseModel, Field + +from a2a_store import add_message, get_agent, list_agents, list_messages, register_agent +from timeline_store import add_item, delete_item, get_item, list_items, update_item + +app = FastAPI(title="xMCP Timeline Service") + + +class TimelineItemCreate(BaseModel): + user_id: str = "default" + title: str + body: str = "" + status: str = "unread" + posted_by: str = "agent" + actions: List[str] = Field(default_factory=list) + metadata: Dict[str, Any] = Field(default_factory=dict) + + +class TimelineItemUpdate(BaseModel): + status: Optional[str] = None + action: Optional[str] = None + posted_by: Optional[str] = None + title: Optional[str] = None + body: Optional[str] = None + actions: Optional[List[str]] = None + metadata: Optional[Dict[str, Any]] = None + + +class AgentCreate(BaseModel): + id: Optional[str] = None + name: str + description: Optional[str] = "" + status: Optional[str] = "offline" + endpoint: Optional[str] = "" + tags: List[str] = Field(default_factory=list) + + +class A2AMessageCreate(BaseModel): + from_agent: str = Field(alias="from") + to: str + type: str = "info" + content: str = "" + metadata: Dict[str, Any] = Field(default_factory=dict) + + +@app.get("/v1/timeline/users/{user_id}/items") +def get_items(user_id: str, status: Optional[str] = None) -> Dict[str, Any]: + items = list_items(user_id, status) + return {"items": items, "count": len(items)} + + +@app.get("/v1/timeline/items/{item_id}") +def get_item_by_id(item_id: str) -> Dict[str, Any]: + item = get_item(item_id) + if not item: + raise HTTPException(status_code=404, detail="Item not found") + return item + + +@app.post("/v1/timeline/items") +def create_item(payload: TimelineItemCreate) -> Dict[str, Any]: + item = add_item(payload.dict()) + return item + + +@app.patch("/v1/timeline/items/{item_id}") +def patch_item(item_id: str, updates: TimelineItemUpdate) -> Dict[str, Any]: + data = updates.dict(exclude_unset=True) + if updates.action and not updates.status: + data["status"] = updates.action.lower() + item = update_item(item_id, data) + if not item: + raise HTTPException(status_code=404, detail="Item not found") + if updates.action: + _dispatch_action(item, updates.action) + return item + + +@app.delete("/v1/timeline/items/{item_id}") +def remove_item(item_id: str) -> Dict[str, Any]: + deleted = delete_item(item_id) + if not deleted: + raise HTTPException(status_code=404, detail="Item not found") + return {"deleted": True, "id": item_id} + + +@app.get("/v1/a2a/agents") +def get_agents() -> Dict[str, Any]: + agents = list_agents() + return {"agents": agents, "count": len(agents)} + + +@app.get("/v1/a2a/agents/{agent_id}") +def get_agent_by_id(agent_id: str) -> Dict[str, Any]: + agent = get_agent(agent_id) + if not agent: + raise HTTPException(status_code=404, detail="Agent not found") + return agent + + +@app.post("/v1/a2a/agents") +def create_agent(payload: AgentCreate) -> Dict[str, Any]: + agent = register_agent(payload.dict(exclude_unset=True)) + return agent + + +@app.get("/v1/a2a/agents/{agent_id}/messages") +def get_agent_messages(agent_id: str) -> Dict[str, Any]: + messages = list_messages(agent_id) + return {"messages": messages, "count": len(messages)} + + +@app.post("/v1/a2a/messages") +def create_message(payload: A2AMessageCreate) -> Dict[str, Any]: + message = add_message(payload.dict(by_alias=True)) + return message + + +def _dispatch_action(item: Dict[str, Any], action: str) -> None: + target_agent = os.getenv("TIMELINE_ACTION_AGENT", "mcp-orchestrator") + add_message( + { + "from": "timeline-ui", + "to": target_agent, + "type": "timeline_action", + "content": f"{action} on {item.get('title')}", + "metadata": { + "timeline_item_id": item.get("id"), + "action": action, + "status": item.get("status"), + }, + } + ) + + +def main() -> None: + host = os.getenv("TIMELINE_HOST", "0.0.0.0") + port_value = os.getenv("PORT") or os.getenv("TIMELINE_PORT", "8080") + port = int(port_value) + import uvicorn + + uvicorn.run(app, host=host, port=port) + + +if __name__ == "__main__": + main() diff --git a/timeline_store.py b/timeline_store.py new file mode 100644 index 0000000..97c42b0 --- /dev/null +++ b/timeline_store.py @@ -0,0 +1,107 @@ +import json +import os +import threading +import uuid +from datetime import datetime, timezone +from pathlib import Path +from typing import Any, Dict, List, Optional + +STORE_PATH = Path(os.getenv("TIMELINE_STORE_PATH", "~/.xmcp/timeline_store.json")).expanduser() +STORE_LOCK = threading.Lock() + + +def _utc_now() -> str: + return datetime.now(timezone.utc).isoformat() + + +def _ensure_store() -> None: + if STORE_PATH.exists(): + return + STORE_PATH.parent.mkdir(parents=True, exist_ok=True) + STORE_PATH.write_text(json.dumps({"items": []}, indent=2), encoding="utf-8") + + +def _read_store() -> Dict[str, Any]: + _ensure_store() + raw = STORE_PATH.read_text(encoding="utf-8") + try: + data = json.loads(raw) + except json.JSONDecodeError: + data = {"items": []} + if "items" not in data or not isinstance(data["items"], list): + data["items"] = [] + return data + + +def _write_store(data: Dict[str, Any]) -> None: + STORE_PATH.parent.mkdir(parents=True, exist_ok=True) + STORE_PATH.write_text(json.dumps(data, indent=2), encoding="utf-8") + + +def list_items(user_id: str, status: Optional[str] = None) -> List[Dict[str, Any]]: + with STORE_LOCK: + data = _read_store() + items = [item for item in data["items"] if item.get("user_id") == user_id] + if status: + items = [item for item in items if item.get("status") == status] + return items + + +def get_item(item_id: str) -> Optional[Dict[str, Any]]: + with STORE_LOCK: + data = _read_store() + for item in data["items"]: + if item.get("id") == item_id: + return item + return None + + +def add_item(payload: Dict[str, Any]) -> Dict[str, Any]: + item = { + "id": payload.get("id") or str(uuid.uuid4()), + "user_id": payload.get("user_id", "default"), + "title": payload.get("title", "Untitled"), + "body": payload.get("body", ""), + "status": payload.get("status", "unread"), + "posted_by": payload.get("posted_by", "agent"), + "actions": payload.get("actions", []), + "metadata": payload.get("metadata", {}), + "created_at": _utc_now(), + "updated_at": None, + } + + with STORE_LOCK: + data = _read_store() + data["items"].insert(0, item) + _write_store(data) + return item + + +def update_item(item_id: str, updates: Dict[str, Any]) -> Optional[Dict[str, Any]]: + with STORE_LOCK: + data = _read_store() + for item in data["items"]: + if item.get("id") != item_id: + continue + for key in ["status", "posted_by", "title", "body"]: + if key in updates and updates[key] is not None: + item[key] = updates[key] + if "metadata" in updates and isinstance(updates["metadata"], dict): + item["metadata"] = {**item.get("metadata", {}), **updates["metadata"]} + if "actions" in updates and isinstance(updates["actions"], list): + item["actions"] = updates["actions"] + item["updated_at"] = _utc_now() + _write_store(data) + return item + return None + + +def delete_item(item_id: str) -> bool: + with STORE_LOCK: + data = _read_store() + original = len(data["items"]) + data["items"] = [item for item in data["items"] if item.get("id") != item_id] + if len(data["items"]) == original: + return False + _write_store(data) + return True