OpenX API Docs

OpenAI Compatible

X / Twitter Data API

Real-time Twitter data scraping via standard OpenAI SDK. Search tweets, users, followers, following lists — all through familiar chat completions format.

Table of Contents

  1. Quick Start
  2. Authentication
  3. Available Models
  4. Request Format
  5. Response Format
  6. Code Examples
  7. Streaming
  8. Error Codes
  9. Rate Limits

1. Quick Start

OpenX API is 100% compatible with the OpenAI Chat Completions format. You can use any OpenAI SDK to access Twitter data.

Three things you need

ItemValue
base_urlhttps://api.gugou.ai/v1
api_keyYour API key (starts with sk-)
modelOne of the 5 supported models below

Minimal example (Python)

from openai import OpenAI
import json

client = OpenAI(
    api_key="sk-your-api-key",
    base_url="https://api.gugou.ai/v1",
)

resp = client.chat.completions.create(
    model="x-search-tweets",
    messages=[{
        "role": "user",
        "content": json.dumps({
            "query": "bitcoin",
            "limit": 5,
            "product": "Latest"
        })
    }]
)

tweets = json.loads(resp.choices[0].message.content)
for t in tweets:
    print(f"@{t['user']['username']}: {t['rawContent'][:80]}")

Minimal example (cURL)

curl -X POST https://api.gugou.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "x-search-tweets",
    "messages": [{"role": "user", "content": "{\"query\":\"bitcoin\",\"limit\":5,\"product\":\"Latest\"}"}]
  }'

2. Authentication

All requests require an API key in the Authorization header:

Authorization: Bearer sk-your-api-key
To obtain an API key, please contact us or register on the management portal.

3. Available Models

x-search-tweets

Search tweets by keyword or query string.

Params: query, limit, product

For stock-related posts, use $ + ticker, such as $TSLA, $AAPL, $NVDA.

x-search-users

Search Twitter users by keyword.

Params: query, limit

x-user-tweets

Get tweets from a specific user.

Params: user_id, limit

x-user-followers

Get a user's followers list.

Params: user_id, limit

x-user-following

Get accounts a user follows.

Params: user_id, limit

Parameter Reference

ParameterTypeRequiredDescription
querystringFor search modelsSearch keyword or query string
user_idintegerFor user modelsTwitter numeric user ID
limitintegerNo (default: 20)Max results to return (1–500)
productstringNo (default: "Top")Search type: Top, Latest, People, Photos, Videos

4. Request Format

Parameters are passed as a JSON string inside the user message content:

{
  "model": "x-search-tweets",
  "messages": [
    {
      "role": "user",
      "content": "{\"query\": \"bitcoin\", \"limit\": 10, \"product\": \"Latest\"}"
    }
  ],
  "stream": false
}
Important: The content field must be a JSON string, not a nested object. Use json.dumps() in Python or JSON.stringify() in JavaScript.

For stock ticker searches

When searching for stock-related tweets, it is recommended to use $ + stock symbol for better precision.

{
  "model": "x-search-tweets",
  "messages": [
    {
      "role": "user",
      "content": "{\"query\": \"$TSLA\", \"limit\": 10, \"product\": \"Latest\"}"
    }
  ]
}
Examples: $TSLA, $AAPL, $NVDA, $MSFT. In many cases, using the ticker symbol is more accurate than using the company name directly.

Advanced stock search examples

You can combine ticker symbols with company names or other query operators for broader or more precise matching.

{
  "model": "x-search-tweets",
  "messages": [
    {
      "role": "user",
      "content": "{\"query\": \"$TSLA OR Tesla\", \"limit\": 20, \"product\": \"Latest\"}"
    }
  ]
}
{
  "model": "x-search-tweets",
  "messages": [
    {
      "role": "user",
      "content": "{\"query\": \"$AAPL lang:en\", \"limit\": 20, \"product\": \"Latest\"}"
    }
  ]
}
Recommended patterns: $TSLA OR Tesla, $NVDA OR Nvidia, $AAPL lang:en, $MSFT -filter:replies. These query strings are passed directly to X search.

For user-based models

{
  "model": "x-user-tweets",
  "messages": [
    {
      "role": "user",
      "content": "{\"user_id\": 44196397, \"limit\": 10}"
    }
  ]
}
Tip: You can find a user's numeric ID by searching for them with x-search-users first — the id field in the response is the numeric user ID.

5. Response Format

Responses follow the standard OpenAI Chat Completions format. The actual Twitter data is in choices[0].message.content as a JSON string that needs to be parsed.

{
  "id": "chatcmpl-openx-7663002f5683",
  "object": "chat.completion",
  "created": 1774489310,
  "model": "x-search-tweets",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "[{\"id\": 123, \"rawContent\": \"...\", \"user\": {...}}, ...]"
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 100,
    "completion_tokens": 900,
    "total_tokens": 1000
  }
}

Tweet Object Fields

FieldTypeDescription
idintegerTweet numeric ID
urlstringDirect link to the tweet
datestringTimestamp
rawContentstringFull tweet text
userobjectAuthor info (username, displayname, followersCount, etc.)
replyCountintegerNumber of replies
retweetCountintegerNumber of retweets
likeCountintegerNumber of likes
viewCountintegerNumber of views
hashtagsarrayHashtags in the tweet
mediaobjectAttached photos, videos, GIFs

User Object Fields

FieldTypeDescription
idintegerUser numeric ID
usernamestringHandle (without @)
displaynamestringDisplay name
rawDescriptionstringBio text
followersCountintegerNumber of followers
friendsCountintegerNumber of following
statusesCountintegerTotal tweets
profileImageUrlstringAvatar URL
verifiedbooleanLegacy verification badge
bluebooleanTwitter Blue subscriber

6. Code Examples

Python — Search tweets

from openai import OpenAI
import json

client = OpenAI(api_key="sk-your-key", base_url="https://api.gugou.ai/v1")

resp = client.chat.completions.create(
    model="x-search-tweets",
    messages=[{"role": "user", "content": json.dumps({
        "query": "$TSLA OR $BTC",
        "limit": 20,
        "product": "Latest"
    })}]
)

tweets = json.loads(resp.choices[0].message.content)
for t in tweets:
    print(f"@{t['user']['username']} [{t['likeCount']} likes]: {t['rawContent'][:100]}")
For stock-related searches, prefer $ + ticker format, such as $TSLA or $AAPL, instead of only using the company name.

Python — Advanced stock query

resp = client.chat.completions.create(
    model="x-search-tweets",
    messages=[{
        "role": "user",
        "content": json.dumps({
            "query": "$TSLA OR Tesla lang:en",
            "limit": 20,
            "product": "Latest"
        })
    }]
)

tweets = json.loads(resp.choices[0].message.content)
for t in tweets:
    print(f"@{t['user']['username']}: {t['rawContent'][:120]}")

Python — Get user info

# Step 1: Find user ID
resp = client.chat.completions.create(
    model="x-search-users",
    messages=[{"role": "user", "content": json.dumps({"query": "elonmusk", "limit": 1})}]
)
users = json.loads(resp.choices[0].message.content)
user_id = users[0]["id"]
print(f"Found: @{users[0]['username']} (ID: {user_id}, Followers: {users[0]['followersCount']})")

# Step 2: Get their tweets
resp = client.chat.completions.create(
    model="x-user-tweets",
    messages=[{"role": "user", "content": json.dumps({"user_id": user_id, "limit": 5})}]
)
tweets = json.loads(resp.choices[0].message.content)
for t in tweets:
    print(f"  {t['rawContent'][:100]}")

Node.js — Search users

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "sk-your-key",
  baseURL: "https://api.gugou.ai/v1",
});

const resp = await client.chat.completions.create({
  model: "x-search-users",
  messages: [{ role: "user", content: JSON.stringify({ query: "AI", limit: 5 }) }],
});

const users = JSON.parse(resp.choices[0].message.content);
users.forEach(u => console.log(`@${u.username} - ${u.followersCount} followers`));

cURL — Get followers

curl -X POST https://api.gugou.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "x-user-followers",
    "messages": [{"role": "user", "content": "{\"user_id\": 44196397, \"limit\": 10}"}]
  }'

7. Streaming (SSE)

Set "stream": true to receive results as Server-Sent Events. Each chunk contains one page of results.

resp = client.chat.completions.create(
    model="x-search-tweets",
    messages=[{"role": "user", "content": json.dumps({
        "query": "breaking news",
        "limit": 50,
        "product": "Latest"
    })}],
    stream=True
)

for chunk in resp:
    if chunk.choices[0].delta.content:
        page = json.loads(chunk.choices[0].delta.content)
        print(f"Received {len(page)} tweets in this chunk")
Streaming is especially useful for x-search-tweets with large limit values. Results are delivered page-by-page as they are scraped.

8. Error Codes

ErrorHTTP StatusDescription
model_not_found400Invalid model name. Check the 5 supported models above.
invalid_request_error400Missing or invalid parameters (e.g., query not provided for search models).
scraping_error500Internal scraping failure. Usually temporary — retry after a few seconds.
invalid token401API key is invalid or expired.
insufficient quota403Account balance exhausted. Please top up.

Error response format

{
  "error": {
    "message": "Model 'x-bad-model' not found. Available: ['x-search-tweets', ...]",
    "type": "model_not_found",
    "code": "model_not_found"
  }
}

9. Rate Limits & Best Practices