Skip to docs content

Accounts and settings

Manage monitored accounts and optional event sources through authenticated REST endpoints and account settings.

Run the 5-minute quickstart
Open in chat
Reviewed against product code on September 2, 2026

Add and remove accounts

Use the REST endpoints from your backend to change the watchlist.

Send handles

Send one handle or an array in accounts. A leading @ is optional, and matching is case-insensitive.

Add accounts

typescript
const apiKey = process.env.TWEETSTREAM_API_KEY;
if (!apiKey) throw new Error("Missing TWEETSTREAM_API_KEY");
 
const response = await fetch("https://api.tweetstream.io/api/add-account", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    accounts: ["marketdesk", "realDonaldTrump"],
  }),
});
 
if (!response.ok && response.status !== 207) {
  throw new Error(`Add failed (${response.status}): ${await response.text()}`);
}
 
console.log(await response.json());

Remove an account

typescript
const apiKey = process.env.TWEETSTREAM_API_KEY;
if (!apiKey) throw new Error("Missing TWEETSTREAM_API_KEY");
 
const response = await fetch("https://api.tweetstream.io/api/remove-account", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    accounts: "marketdesk",
  }),
});
 
if (!response.ok && response.status !== 207) {
  throw new Error(`Remove failed (${response.status}): ${await response.text()}`);
}
 
console.log(await response.json());

Choose the credential scope

A standard API key updates the standard tracked-account list. An active Ultra key updates the Ultra selection and enforces its paid account limit.

Read every result

The response contains one result per handle. Use the row state, not only the HTTP status, before retrying.

Command result

json
{
  "action": "follow",
  "requestId": "8b4f9c9c-9e7b-4a0c-9c7d-2d4d6f0a9a25",
  "error": null,
  "results": [
    {
      "input": "marketdesk",
      "state": "added"
    },
    {
      "input": "realDonaldTrump",
      "state": "added"
    }
  ],
  "summary": {
    "failed": 0,
    "succeeded": 2,
    "total": 2
  }
}

Check current usage

Call /api/me with either the standard or Ultra API key. The private response is not cached.

Read plan and usage fields

The response contains base-plan usage and any additive Ultra Speed details.

FieldTypeNotes
credentialScopestandard or ultra_speedScope of the bearer key used
planBASIC, ELITE, or ENTERPRISERuntime plan enum
trackedAccountsobjectCount, limit, and normalized handles
websocketobjectCurrent active connection count and plan limit
stripeobjectSubscription status and billing period fields; treat identifiers as private
ultraSpeedobject or nullUltra status, billing cycle, limits, scoped WebSocket usage, and cancellation timing

Inspect the response

Account usage request

typescript
const apiKey = process.env.TWEETSTREAM_API_KEY;
if (!apiKey) throw new Error("Missing TWEETSTREAM_API_KEY");
 
const response = await fetch("https://api.tweetstream.io/api/me", {
  headers: {
    Authorization: `Bearer ${apiKey}`,
  },
});
 
if (!response.ok) {
  throw new Error(`Account status failed (${response.status}): ${await response.text()}`);
}
 
console.log(await response.json());

Account usage response

json
{
  "credentialScope": "standard",
  "plan": "ELITE",
  "trackedAccounts": {
    "count": 2,
    "limit": 250,
    "handles": ["marketdesk", "realDonaldTrump"]
  },
  "websocket": {
    "count": 1,
    "limit": 10
  },
  "stripe": {
    "subscriptionStatus": "ACTIVE",
    "customerId": "[redacted]",
    "hasCustomer": true,
    "subscriptionId": "[redacted]",
    "currentPeriodStart": "2026-06-30T00:00:00.000Z",
    "currentPeriodEnd": "2026-07-30T00:00:00.000Z",
    "canceledAt": null
  },
  "ultraSpeed": {
    "active": true,
    "status": "ACTIVE",
    "billingCycle": "MONTHLY",
    "paymentRail": "STRIPE_CARD",
    "accountLimit": 25,
    "websocket": {
      "count": 1,
      "limit": 5
    },
    "currentPeriodEnd": "2026-07-30T00:00:00.000Z",
    "cancelAtPeriodEnd": false,
    "canceledAt": null
  }
}

Track affiliate list changes

Affiliate list changes are off by default for tracked business accounts on active or trialing Pro, Scale, and Ultra plans.

Enable or disable alerts

Use POST /api/affiliate-alerts, DELETE /api/affiliate-alerts, or the dashboard. Send the tracked handle as account; a leading @ is optional. Repeating a request is safe. Success returns { account, affiliateAlertsEnabled }.

Change the alert setting

typescript
async function setAffiliateAlerts(account: string, enabled: boolean) {
  const response = await fetch("https://api.tweetstream.io/api/affiliate-alerts", {
    method: enabled ? "POST" : "DELETE",
    headers: {
      Authorization: `Bearer ${process.env.TWEETSTREAM_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ account }),
  });
 
  if (!response.ok) {
    throw new Error(await response.text());
  }
  return await response.json();
}
 
console.log(await setAffiliateAlerts("marketdesk", true));
console.log(await setAffiliateAlerts("marketdesk", false));

Handle setting errors

When enabling alerts, TweetStream checks that the account still qualifies as a business account. A failed check returns 400 with { error: "This account is not a business account." }.

StatusWhen it appearsAction
200The saved setting matches the requestRead affiliateAlertsEnabled
400The body is invalid or the account is not a business accountFix the request
401The bearer key is missing or invalidSend a valid API key
403The subscription or feature access is inactiveCheck plan access
404The handle is not tracked by this API keyCheck the tracked handle
500TweetStream could not confirm eligibilityRetry later

Store and replay changes

Changes go to WebSocket, the dashboard feed, and your Discord route. Keyword filters do not apply. Store relationships by (organization.id, member.id) and use eventId only for exact replay deduplication. Replay recorded changes with GET /api/history?type=affiliate. There is no current-list snapshot or pre-feature backfill.

Stream Binance Square posts

Binance Square accounts are off by default. Enable them in the dashboard or through this API. They remain separate from tracked X accounts and do not use an X account slot.

List and change settings

GET /api/binance-square returns saved settings and the catalog fields displayName, squareHandle, profileUrl, avatarUrl, and enabled. POST /api/binance-square enables an account; DELETE /api/binance-square disables it. Send the Square handle in account; a leading @ is optional. Repeating a request is safe.

  • profileUrl is canonical. avatarUrl is null when unavailable.
  • Settings belong to your TweetStream user, so active Standard and Ultra credentials share them.
  • A saved response returns { account, binanceSquareEnabled } with the canonical handle.

List Binance Square accounts

typescript
const response = await fetch(
  "https://api.tweetstream.io/api/binance-square",
  {
    headers: {
      Authorization: `Bearer ${process.env.TWEETSTREAM_API_KEY}`,
    },
  },
);
 
if (!response.ok) {
  throw new Error(await response.text());
}
 
const catalog = await response.json();
console.log(catalog);
// {
//   accounts: [{
//     avatarUrl: "https://bin.bnbstatic.com/static/content/live-admin-api/images/chVikg58jFQ6ScXcVmWNmj.png",
//     displayName: "币安Binance华语",
//     enabled: true,
//     profileUrl: "https://www.binance.com/en/square/profile/Vpo7Qwqy63rk7_Km3zYYaQ",
//     squareHandle: "binancezh"
//   }],
//   canManage: true
// }

Enable or disable posts

typescript
async function setBinanceSquarePosts(account: string, enabled: boolean) {
  const response = await fetch("https://api.tweetstream.io/api/binance-square", {
    method: enabled ? "POST" : "DELETE",
    headers: {
      Authorization: `Bearer ${process.env.TWEETSTREAM_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ account }),
  });
 
  if (!response.ok) {
    throw new Error(await response.text());
  }
  return await response.json();
}
 
console.log(await setBinanceSquarePosts("binancezh", true));
// { account: "binancezh", binanceSquareEnabled: true }

Handle live content

Enabled accounts send live posts, replies, and quotes over WebSocket and applicable Discord routes. History does not store Square content, so reconnects do not backfill missed posts. Keyword filters still apply. Discord uses the global webhook unless an account-specific route applies.

  • Content uses tweet/content, with author.platform set to binance_square and kind set to post, reply, or quote.
  • Later tweet operations set d.platform to binance_square; use (platform, tweetId) as the post key.
  • Replies and quotes include ref when reference context is available. Post and profile links use canonical Binance URLs.

Binance Square content event

json
{
  "v": 1,
  "t": "tweet",
  "op": "content",
  "id": "358051617962575",
  "ts": 1772000001100,
  "d": {
    "tweetId": "358051617962575",
    "kind": "quote",
    "text": "Example Binance Square quote",
    "createdAt": 1772000001000,
    "receivedAt": 1772000001100,
    "link": "https://www.binance.com/en/square/post/358051617962575",
    "author": {
      "id": "Vpo7Qwqy63rk7_Km3zYYaQ",
      "handle": "@binancezh",
      "platform": "binance_square",
      "url": "https://www.binance.com/en/square/profile/Vpo7Qwqy63rk7_Km3zYYaQ"
    },
    "ref": {
      "type": "quote",
      "tweetId": "358012920288073"
    }
  }
}

Handle setting errors

StatusWhen it appearsAction
200The catalog was listed or the setting was savedRead the response body
400The body is invalid or the account is not in the catalogFix the request
401The bearer key is missing or invalidSend a valid API key
403The API credential is not activeCheck subscription status
500TweetStream could not save the settingRetry later

Read handle result states

StateWhen it appearsRecommended handling
addedHandle was added to the watchlistTreat as success
already_followingHandle is already trackedTreat as idempotent at the row level
removedHandle was removedTreat as success
not_followingHandle was not trackedTreat as idempotent at the row level
invalid_input, duplicate, not_found, failedInvalid input, duplicate input, missing account, or operation failureShow the row-level message and retry only when appropriate

Read REST status codes

Add and remove endpoints return one result per handle. The HTTP status describes the batch; each result row describes its handle.

StatusWhen it appearsNotes
200No row failed, including idempotent success rowssummary.failed is 0; already_following and not_following are successful outcomes
207Some rows succeeded and some rows failedRead each results row before retrying
400The request body is invalid or every row failed for a non-temporary reasonFix the request or row-level errors before retrying
503Every row failed for a temporary reasonRetry the batch with backoff

Check plan limits

  • Minimum: 50 monitored accounts and 3 WebSocket connections after trial.
  • Trial: 5 monitored accounts and 1 WebSocket connection for 3 days.
  • Pro: 250 monitored accounts and 10 WebSocket connections.
  • Scale: self-serve higher monitored-account and WebSocket limits from the pricing page.
  • History replay is available on Pro and Scale; Ultra includes affiliate replay.