twitterapi.io
Official skill maintained by the twitterapi.io team. Paths, parameters, and body fields in this skill are verified against the live backend.
When to use this skill
Trigger when the user wants any of:
- Fetch tweets, user profiles, followers/following, trends, replies, quote-tweets, retweeters, articles
- Advanced tweet search (X operators, date ranges, engagement filters)
- Monitor users or filter rules in near real time
- Post / delete / like / retweet / bookmark / quote-tweet / reply / follow / DM / schedule tweets
- Update profile / avatar / banner, upload media
- Create/join/leave communities, manage lists, report content
- Anything involving
twitterapi.io, api.twitterapi.io, x-api-key, login_cookies, or the X API without OAuth
Core facts
|
|
| Base URL |
https://api.twitterapi.io |
| Prefix |
/twitter/... most endpoints; /oapi/x_user_stream/... and /oapi/tweet_filter/... for real-time monitoring/webhooks; /oapi/my/info for balance |
| Auth header |
x-api-key: YOUR_KEY |
| Dashboard |
https://twitterapi.io/dashboard |
| Docs |
https://docs.twitterapi.io |
| Rate limit |
~200 req/s per client |
| Pricing |
~$0.15/1k tweets, ~$0.18/1k profiles, $0.00015 minimum |
⚠️ Two rules that catch people
Rule 1 — Parameter naming is per-endpoint
No universal snake_case or camelCase rule. Examples (all correct):
/twitter/user/followers?userName= (camel)
/twitter/user/verifiedFollowers?user_id= (snake)
/twitter/user/articles?username= (all-lowercase)
/twitter/tweets?tweet_ids= (snake) but /twitter/tweet/replies?tweetId= (camel)
/twitter/list/tweets_timeline?listId= (camel) but /twitter/list/members?list_id= (snake)
Copy the exact parameter name from references/endpoints.md. Don't normalize.
Rule 2 — Writes need three things in body, not two
Every write endpoint requires:
login_cookies (plural, not login_cookie) — base64-encoded JSON from /twitter/user_login_v2
proxy (HTTP/SOCKS proxy URL — configure in dashboard)
- Action-specific fields, almost always snake_case (
tweet_id, user_id)
Plus key field-name traps:
create_tweet_v2 text field is tweet_text (not text); reply field is reply_to_tweet_id (not in_reply_to_tweet_id)
update_profile_v2 uses description (not bio)
bookmarks_v2 uses count (not pageSize)
send_dm_to_user: user_id + text; optional media_id (singular)
- Monitoring add uses
x_user_name; remove uses id_for_user (different fields per endpoint!)
See references/write-operations.md for full body shapes.
Rule 3 — Response shape varies per endpoint
data-wrapped: user/info, user_about, last_tweets, tweet_timeline, trends, check_follow_relationship → r["data"]["..."]
- Flat with envelope:
followers, followings, replies, mentions, community/tweets → r["followers"], r["tweets"], etc.
- Flat without envelope:
advanced_search, thread_context, user/search, get_tweets_from_all_community → just {tweets[], has_next_page, next_cursor}
- Named top-level field:
community/info → r["community_info"]; batch_info_by_ids → r["users"]
oapi/my/info → {recharge_credits, total_bonus_credits} (no status wrapper)
Prefer defensive access: r.get("tweets", r.get("data", {}).get("tweets", [])).
Security
Never hardcode the API key. Read from env TWITTERAPI_IO_KEY. If missing, ask the user.
Minimal working example
curl -s "https://api.twitterapi.io/twitter/user/info?userName=elonmusk" \
-H "x-api-key: $TWITTERAPI_IO_KEY"
import os, requests
BASE = "https://api.twitterapi.io"
HEADERS = {"x-api-key": os.environ["TWITTERAPI_IO_KEY"]}
r = requests.get(f"{BASE}/twitter/user/info",
headers=HEADERS,
params={"userName": "elonmusk"},
timeout=30)
r.raise_for_status()
d = r.json()["data"]
print(f"{d['userName']} — {d['followers']:,} followers")
Endpoint quick reference
Reads (API key only). Exact param names — copy as shown.
| Capability |
Method |
Path & key param |
| User by screen name |
GET |
/twitter/user/info?userName= |
| Extended bio |
GET |
/twitter/user_about?userName= |
| Batch users by IDs |
GET |
/twitter/user/batch_info_by_ids?userIds= |
| Search users |
GET |
/twitter/user/search?query= (not keyword) |
| Recent tweets |
GET |
/twitter/user/last_tweets?userName= (or userId=) |
| Timeline by ID |
GET |
/twitter/user/tweet_timeline?userId= |
| User's articles |
GET |
/twitter/user/articles?username= (all-lowercase) |
| Mentions of user |
GET |
/twitter/user/mentions?userName= |
| Followers |
GET |
/twitter/user/followers?userName=&pageSize=200 |
| Verified followers |
GET |
/twitter/user/verifiedFollowers?user_id= (snake) |
| Followings |
GET |
/twitter/user/followings?userName= |
| Check follow |
GET |
/twitter/user/check_follow_relationship?source_user_name=&target_user_name= |
| Tweets by IDs |
GET |
/twitter/tweets?tweet_ids= (snake) |
| Tweet replies |
GET |
/twitter/tweet/replies?tweetId= |
| Replies (sortable) |
GET |
/twitter/tweet/replies/v2?tweetId=&queryType=Latest |
| Quote tweets |
GET |
/twitter/tweet/quotes?tweetId= |
| Retweeters |
GET |
/twitter/tweet/retweeters?tweetId= |
| Thread context |
GET |
/twitter/tweet/thread_context?tweetId= |
| Article content |
GET |
/twitter/article?tweet_id= (snake) |
| Advanced search |
GET |
/twitter/tweet/advanced_search?query= |
| Bulk advanced search |
POST |
/twitter/tweet/bulk_advanced_search body {queries:[{query,queryType?,cursor?}]} |
| Trends |
GET |
/twitter/trends?woeid=1&count=30 |
| Space detail |
GET |
/twitter/spaces/detail?space_id= (snake) |
| List tweets (with filters) |
GET |
/twitter/list/tweets?listId= |
| List tweets_timeline |
GET |
/twitter/list/tweets_timeline?listId= |
| List members / followers |
GET |
/twitter/list/{members,followers}?list_id= (snake) |
| Community info |
GET |
/twitter/community/info?community_id= |
| Community tweets/members/mods |
GET |
/twitter/community/{tweets,members,moderators}?community_id= |
| All-community firehose |
GET |
/twitter/community/get_tweets_from_all_community?query= (required!) |
| Account balance |
GET |
/oapi/my/info |
Real-time monitoring (/oapi/x_user_stream/*). Field names differ per endpoint!
| Capability |
Method |
Path & body |
| Add monitor |
POST |
/oapi/x_user_stream/add_user_to_monitor_tweet body {x_user_name} ← not user_id |
| List monitors |
GET |
/oapi/x_user_stream/get_user_to_monitor_tweet (+ query_type 0/1/2) |
| Remove monitor |
POST |
/oapi/x_user_stream/remove_user_to_monitor_tweet body {id_for_user} ← different field from add |
Webhook filter rules (/oapi/tweet_filter/*):
| Capability |
Method |
Path & body |
| Add rule |
POST |
/oapi/tweet_filter/add_rule body {tag, value, interval_seconds?=60} (range 0.05–86400) |
| List rules |
GET |
/oapi/tweet_filter/get_rules |
| Update rule |
POST |
/oapi/tweet_filter/update_rule body {rule_id, tag, value, interval_seconds?, is_effect?} |
| Delete rule |
DELETE |
/oapi/tweet_filter/delete_rule body {rule_id} (body JSON, not query) |
Writes — require login_cookies + proxy in body. login_cookies is base64(json(cookie_dict)) from /twitter/user_login_v2.
| Capability |
Method |
Path |
Key body fields (beyond login_cookies+proxy) |
| Log in → cookies |
POST |
/twitter/user_login_v2 |
{user_name, email, password, totp_secret?, proxy} |
| Create tweet |
POST |
/twitter/create_tweet_v2 |
tweet_text (req); optional reply_to_tweet_id, quote_tweet_id, community_id, media_ids[], schedule_for |
| Delete |
POST |
/twitter/delete_tweet_v2 |
tweet_id |
| Like / Unlike |
POST |
/twitter/{like,unlike}_tweet_v2 |
tweet_id |
| Retweet |
POST |
/twitter/retweet_tweet_v2 |
tweet_id |
| Bookmark / Unbookmark |
POST |
/twitter/{bookmark,unbookmark}_tweet_v2 |
tweet_id |
| List bookmarks |
POST |
/twitter/bookmarks_v2 |
optional count (def 20, not pageSize), cursor |
| Follow / Unfollow |
POST |
/twitter/{follow,unfollow}_user_v2 |
user_id |
| Send DM |
POST |
/twitter/send_dm_to_user |
user_id, text, optional media_id (singular), reply_to_message_id |
| Report |
POST |
/twitter/report_v2 |
(tweet_id OR user_id), reason (enum, see endpoints.md) |
| Upload media |
POST |
/twitter/upload_media_v2 |
multipart: file, optional media_category, is_long_video |
| Update profile |
PATCH |
/twitter/update_profile_v2 |
JSON: at least one of name, description (not bio!), location, url |
| Update avatar/banner |
PATCH |
/twitter/update_{avatar,banner}_v2 |
multipart: file |
| Create community |
POST |
/twitter/create_community_v2 |
name, description (both required) |
| Join / Leave community |
POST |
/twitter/{join,leave}_community_v2 |
community_id |
| Delete community |
POST |
/twitter/delete_community_v2 |
community_id, community_name (both required) |
| Add list member |
POST |
/twitter/list/add_member_v2 |
list_id, user_id |
For exact param lists, response shapes, and edge cases see references/endpoints.md.
Recurring patterns
Cursor pagination — use has_next_page
def iter_followers(user_name):
cursor = ""
while True:
r = requests.get(f"{BASE}/twitter/user/followers",
headers=HEADERS,
params={"userName": user_name, "cursor": cursor, "pageSize": 200},
timeout=30).json()
yield from r.get("followers", [])
if not r.get("has_next_page"):
break
cursor = r.get("next_cursor") or ""
Error handling
# FastAPI-style 4xx/5xx
{ "detail": "tweet_id is required" }
{ "detail": [{"type":"missing","loc":["body","file"]}] } # 422 on multipart
# Semantic 200 errors
{ "status": "error", "msg": "No active monitoring subscription" }
401 → bad x-api-key or expired login_cookies
402 → top up balance at dashboard
429 → rate-limited; exponential backoff
400/422 → read detail — it names the missing/wrong field
500 → transient; retry with jitter. If repeated, the param name is wrong
Cost awareness
Before a loop that could paginate for a long time (followers of a mega-account, years of advanced search), estimate cost up front and confirm with the user if it could exceed a few dollars. A 100M-follower crawl is $15k+ at $0.15/1k.
Anti-patterns
- Do not assume a universal param-casing rule — check endpoints.md
- Do not use
login_cookie (singular) — it's login_cookies plural
- Do not forget
proxy in write bodies — every write requires it
- Do not send
text for create_tweet_v2 — use tweet_text
- Do not use
bio in update_profile_v2 — use description
- Do not use
in_reply_to_tweet_id for create_tweet_v2 — it's reply_to_tweet_id
- Do not send JSON to
upload_media_v2 / update_avatar_v2 / update_banner_v2 — they're multipart/form-data
- Do not use
pageSize for bookmarks_v2 — it's count
- Do not send
user_id to monitoring add — it's x_user_name; remove uses id_for_user
- Do not log or commit API keys,
login_cookies, proxies, or totp_secret
- Do not use
developer.twitter.com / official X OAuth — this API replaces them
- Do not poll
/user/last_tweets for "real-time" — use /oapi/tweet_filter/add_rule + webhook
Source: kaitoInfra/twitterapi-io — distributed by TomeVault.
1---2name: twitterapi-io3description: Official skill for twitterapi.io — query Twitter/X data (tweets, profiles, followers, advanced search, trends, spaces, communities, lists) and perform authenticated actions (post, reply, like, retweet, follow, DM) via the twitterapi.io REST API using a single `x-api-key` header — no OAuth. Use when the user needs to scrape, analyze, monitor, or automate X/Twitter without going through the official developer portal. Use when this capability is needed.4---56# twitterapi.io78**Official skill** maintained by the [twitterapi.io](https://twitterapi.io) team. Paths, parameters, and body fields in this skill are verified against the live backend.910## When to use this skill1112Trigger when the user wants any of:1314- Fetch tweets, user profiles, followers/following, trends, replies, quote-tweets, retweeters, articles15- Advanced tweet search (X operators, date ranges, engagement filters)16- Monitor users or filter rules in near real time17- Post / delete / like / retweet / bookmark / quote-tweet / reply / follow / DM / schedule tweets18- Update profile / avatar / banner, upload media19- Create/join/leave communities, manage lists, report content20- Anything involving `twitterapi.io`, `api.twitterapi.io`, `x-api-key`, `login_cookies`, or the X API without OAuth2122## Core facts2324| | |25|---|---|26| Base URL | `https://api.twitterapi.io` |27| Prefix | `/twitter/...` most endpoints; `/oapi/x_user_stream/...` and `/oapi/tweet_filter/...` for real-time monitoring/webhooks; `/oapi/my/info` for balance |28| Auth header | `x-api-key: YOUR_KEY` |29| Dashboard | https://twitterapi.io/dashboard |30| Docs | https://docs.twitterapi.io |31| Rate limit | ~200 req/s per client |32| Pricing | ~$0.15/1k tweets, ~$0.18/1k profiles, $0.00015 minimum |3334## ⚠️ Two rules that catch people3536### Rule 1 — Parameter naming is per-endpoint3738No universal snake_case or camelCase rule. Examples (all correct):39- `/twitter/user/followers?userName=` (camel)40- `/twitter/user/verifiedFollowers?user_id=` (snake)41- `/twitter/user/articles?username=` (all-lowercase)42- `/twitter/tweets?tweet_ids=` (snake) but `/twitter/tweet/replies?tweetId=` (camel)43- `/twitter/list/tweets_timeline?listId=` (camel) but `/twitter/list/members?list_id=` (snake)4445**Copy the exact parameter name from [references/endpoints.md](references/endpoints.md). Don't normalize.**4647### Rule 2 — Writes need three things in body, not two4849Every write endpoint requires:501. `login_cookies` (**plural**, not `login_cookie`) — base64-encoded JSON from `/twitter/user_login_v2`512. `proxy` (HTTP/SOCKS proxy URL — configure in dashboard)523. Action-specific fields, almost always **snake_case** (`tweet_id`, `user_id`)5354Plus key field-name traps:55- `create_tweet_v2` text field is `tweet_text` (not `text`); reply field is `reply_to_tweet_id` (not `in_reply_to_tweet_id`)56- `update_profile_v2` uses `description` (not `bio`)57- `bookmarks_v2` uses `count` (not `pageSize`)58- `send_dm_to_user`: `user_id` + `text`; optional `media_id` (singular)59- Monitoring add uses `x_user_name`; remove uses `id_for_user` (different fields per endpoint!)6061See [references/write-operations.md](references/write-operations.md) for full body shapes.6263### Rule 3 — Response shape varies per endpoint6465- `data`-wrapped: `user/info`, `user_about`, `last_tweets`, `tweet_timeline`, `trends`, `check_follow_relationship` → `r["data"]["..."]`66- Flat with envelope: `followers`, `followings`, `replies`, `mentions`, `community/tweets` → `r["followers"]`, `r["tweets"]`, etc.67- Flat without envelope: `advanced_search`, `thread_context`, `user/search`, `get_tweets_from_all_community` → just `{tweets[], has_next_page, next_cursor}`68- Named top-level field: `community/info` → `r["community_info"]`; `batch_info_by_ids` → `r["users"]`69- `oapi/my/info` → `{recharge_credits, total_bonus_credits}` (no status wrapper)7071Prefer defensive access: `r.get("tweets", r.get("data", {}).get("tweets", []))`.7273## Security7475**Never** hardcode the API key. Read from env `TWITTERAPI_IO_KEY`. If missing, ask the user.7677## Minimal working example7879```bash80curl -s "https://api.twitterapi.io/twitter/user/info?userName=elonmusk" \81 -H "x-api-key: $TWITTERAPI_IO_KEY"82```8384```python85import os, requests8687BASE = "https://api.twitterapi.io"88HEADERS = {"x-api-key": os.environ["TWITTERAPI_IO_KEY"]}8990r = requests.get(f"{BASE}/twitter/user/info",91 headers=HEADERS,92 params={"userName": "elonmusk"},93 timeout=30)94r.raise_for_status()95d = r.json()["data"]96print(f"{d['userName']} — {d['followers']:,} followers")97```9899## Endpoint quick reference100101Reads (API key only). **Exact param names — copy as shown.**102103| Capability | Method | Path & key param |104|---|---|---|105| User by screen name | GET | `/twitter/user/info?userName=` |106| Extended bio | GET | `/twitter/user_about?userName=` |107| Batch users by IDs | GET | `/twitter/user/batch_info_by_ids?userIds=` |108| Search users | GET | `/twitter/user/search?query=` (**not** `keyword`) |109| Recent tweets | GET | `/twitter/user/last_tweets?userName=` (or `userId=`) |110| Timeline by ID | GET | `/twitter/user/tweet_timeline?userId=` |111| User's articles | GET | `/twitter/user/articles?username=` (**all-lowercase**) |112| Mentions of user | GET | `/twitter/user/mentions?userName=` |113| Followers | GET | `/twitter/user/followers?userName=&pageSize=200` |114| Verified followers | GET | `/twitter/user/verifiedFollowers?user_id=` (**snake**) |115| Followings | GET | `/twitter/user/followings?userName=` |116| Check follow | GET | `/twitter/user/check_follow_relationship?source_user_name=&target_user_name=` |117| Tweets by IDs | GET | `/twitter/tweets?tweet_ids=` (**snake**) |118| Tweet replies | GET | `/twitter/tweet/replies?tweetId=` |119| Replies (sortable) | GET | `/twitter/tweet/replies/v2?tweetId=&queryType=Latest` |120| Quote tweets | GET | `/twitter/tweet/quotes?tweetId=` |121| Retweeters | GET | `/twitter/tweet/retweeters?tweetId=` |122| Thread context | GET | `/twitter/tweet/thread_context?tweetId=` |123| Article content | GET | `/twitter/article?tweet_id=` (**snake**) |124| Advanced search | GET | `/twitter/tweet/advanced_search?query=` |125| Bulk advanced search | POST | `/twitter/tweet/bulk_advanced_search` body `{queries:[{query,queryType?,cursor?}]}` |126| Trends | GET | `/twitter/trends?woeid=1&count=30` |127| Space detail | GET | `/twitter/spaces/detail?space_id=` (**snake**) |128| List tweets (with filters) | GET | `/twitter/list/tweets?listId=` |129| List tweets_timeline | GET | `/twitter/list/tweets_timeline?listId=` |130| List members / followers | GET | `/twitter/list/{members,followers}?list_id=` (**snake**) |131| Community info | GET | `/twitter/community/info?community_id=` |132| Community tweets/members/mods | GET | `/twitter/community/{tweets,members,moderators}?community_id=` |133| All-community firehose | GET | `/twitter/community/get_tweets_from_all_community?query=` (required!) |134| Account balance | GET | `/oapi/my/info` |135136Real-time monitoring (`/oapi/x_user_stream/*`). **Field names differ per endpoint!**137138| Capability | Method | Path & body |139|---|---|---|140| Add monitor | POST | `/oapi/x_user_stream/add_user_to_monitor_tweet` body `{x_user_name}` ← **not `user_id`** |141| List monitors | GET | `/oapi/x_user_stream/get_user_to_monitor_tweet` (+ `query_type` 0/1/2) |142| Remove monitor | POST | `/oapi/x_user_stream/remove_user_to_monitor_tweet` body `{id_for_user}` ← **different field from add** |143144Webhook filter rules (`/oapi/tweet_filter/*`):145146| Capability | Method | Path & body |147|---|---|---|148| Add rule | POST | `/oapi/tweet_filter/add_rule` body `{tag, value, interval_seconds?=60}` (range 0.05–86400) |149| List rules | GET | `/oapi/tweet_filter/get_rules` |150| Update rule | POST | `/oapi/tweet_filter/update_rule` body `{rule_id, tag, value, interval_seconds?, is_effect?}` |151| Delete rule | DELETE | `/oapi/tweet_filter/delete_rule` body `{rule_id}` (**body JSON, not query**) |152153Writes — require `login_cookies` + `proxy` in body. `login_cookies` is **base64(json(cookie_dict))** from `/twitter/user_login_v2`.154155| Capability | Method | Path | Key body fields (beyond login_cookies+proxy) |156|---|---|---|---|157| Log in → cookies | POST | `/twitter/user_login_v2` | `{user_name, email, password, totp_secret?, proxy}` |158| Create tweet | POST | `/twitter/create_tweet_v2` | `tweet_text` (req); optional `reply_to_tweet_id`, `quote_tweet_id`, `community_id`, `media_ids[]`, `schedule_for` |159| Delete | POST | `/twitter/delete_tweet_v2` | `tweet_id` |160| Like / Unlike | POST | `/twitter/{like,unlike}_tweet_v2` | `tweet_id` |161| Retweet | POST | `/twitter/retweet_tweet_v2` | `tweet_id` |162| Bookmark / Unbookmark | POST | `/twitter/{bookmark,unbookmark}_tweet_v2` | `tweet_id` |163| List bookmarks | POST | `/twitter/bookmarks_v2` | optional `count` (def 20, **not `pageSize`**), `cursor` |164| Follow / Unfollow | POST | `/twitter/{follow,unfollow}_user_v2` | `user_id` |165| Send DM | POST | `/twitter/send_dm_to_user` | `user_id`, `text`, optional `media_id` (singular), `reply_to_message_id` |166| Report | POST | `/twitter/report_v2` | (`tweet_id` OR `user_id`), `reason` (enum, see endpoints.md) |167| Upload media | POST | `/twitter/upload_media_v2` | **multipart**: `file`, optional `media_category`, `is_long_video` |168| Update profile | PATCH | `/twitter/update_profile_v2` | JSON: at least one of `name`, **`description`** (not `bio`!), `location`, `url` |169| Update avatar/banner | PATCH | `/twitter/update_{avatar,banner}_v2` | **multipart**: `file` |170| Create community | POST | `/twitter/create_community_v2` | `name`, `description` (both required) |171| Join / Leave community | POST | `/twitter/{join,leave}_community_v2` | `community_id` |172| Delete community | POST | `/twitter/delete_community_v2` | `community_id`, **`community_name`** (both required) |173| Add list member | POST | `/twitter/list/add_member_v2` | `list_id`, `user_id` |174175For exact param lists, response shapes, and edge cases see [references/endpoints.md](references/endpoints.md).176177## Recurring patterns178179### Cursor pagination — use `has_next_page`180181```python182def iter_followers(user_name):183 cursor = ""184 while True:185 r = requests.get(f"{BASE}/twitter/user/followers",186 headers=HEADERS,187 params={"userName": user_name, "cursor": cursor, "pageSize": 200},188 timeout=30).json()189 yield from r.get("followers", [])190 if not r.get("has_next_page"):191 break192 cursor = r.get("next_cursor") or ""193```194195### Error handling196197```python198# FastAPI-style 4xx/5xx199{ "detail": "tweet_id is required" }200{ "detail": [{"type":"missing","loc":["body","file"]}] } # 422 on multipart201202# Semantic 200 errors203{ "status": "error", "msg": "No active monitoring subscription" }204```205206- `401` → bad `x-api-key` or expired `login_cookies`207- `402` → top up balance at dashboard208- `429` → rate-limited; exponential backoff209- `400/422` → read `detail` — it names the missing/wrong field210- `500` → transient; retry with jitter. If repeated, the param name is wrong211212### Cost awareness213214Before a loop that could paginate for a long time (followers of a mega-account, years of advanced search), **estimate cost up front** and confirm with the user if it could exceed a few dollars. A 100M-follower crawl is $15k+ at $0.15/1k.215216## Anti-patterns217218- Do **not** assume a universal param-casing rule — check endpoints.md219- Do **not** use `login_cookie` (singular) — it's `login_cookies` plural220- Do **not** forget `proxy` in write bodies — every write requires it221- Do **not** send `text` for `create_tweet_v2` — use `tweet_text`222- Do **not** use `bio` in `update_profile_v2` — use `description`223- Do **not** use `in_reply_to_tweet_id` for `create_tweet_v2` — it's `reply_to_tweet_id`224- Do **not** send JSON to `upload_media_v2` / `update_avatar_v2` / `update_banner_v2` — they're **multipart/form-data**225- Do **not** use `pageSize` for `bookmarks_v2` — it's `count`226- Do **not** send `user_id` to monitoring add — it's `x_user_name`; remove uses `id_for_user`227- Do **not** log or commit API keys, `login_cookies`, proxies, or `totp_secret`228- Do **not** use `developer.twitter.com` / official X OAuth — this API replaces them229- Do **not** poll `/user/last_tweets` for "real-time" — use `/oapi/tweet_filter/add_rule` + webhook230231---232> Source: [kaitoInfra/twitterapi-io](https://github.com/kaitoInfra/twitterapi-io) — distributed by [TomeVault](https://tomevault.io).233<!-- tomevault:4.0:skill_md:2026-06-20 -->