Skip to docs content

Profile, follow, and affiliate events

Account events carry observed profile, follow, and affiliate relationship changes.

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

Account event types

Route by op. Ignore unknown account operations without closing the socket.

Account event contracts

typescript
type VerifiedType = 'blue' | 'business' | 'government' | 'verified' | 'none';
type TweetVerifiedLabel = {
  badge: string | null;
  description: string;
  url: string | null;
};
 
type TweetAuthor = {
  banner?: string;
  bio?: string;
  followersCount?: number;
  followingCount?: number;
  id?: string;
  joinedAt?: number;
  location?: string;
  metrics?: {
    likes?: number;
    tweets?: number;
  };
  // Includes a leading @ when present, for example "@elonmusk".
  handle?: string;
  name?: string;
  platform?: 'twitter' | 'truth_social' | 'binance_square';
  profileImage?: string;
  url?: string;
  verifiedLabel?: TweetVerifiedLabel;
  verifiedType?: VerifiedType;
};
 
type AccountEventActor = TweetAuthor & {
  websiteUrl?: string;
};
 
type ProfileUpdateEvent = {
  kind: 'PROFILE';
  eventId: string;
  observedAt: number;
  receivedAt?: number;
  actor: AccountEventActor;
  changes: {
    avatar?: string;
    banner?: string;
    bio?: string;
    handle?: string;
    location?: string;
    name?: string;
    verifiedLabel?: TweetVerifiedLabel | null;
    websiteUrl?: string | null;
  };
  previous?: {
    avatar?: string;
    banner?: string;
    bio?: string;
    handle?: string;
    location?: string;
    name?: string;
    verifiedLabel?: TweetVerifiedLabel | null;
    websiteUrl?: string | null;
  };
};
 
type FollowEvent = {
  kind: 'FOLLOW';
  eventId: string;
  observedAt: number;
  receivedAt?: number;
  actor: AccountEventActor;
  target: AccountEventActor & {
    handle: string;
  };
};
 
type UnfollowEvent = {
  kind: 'UNFOLLOW';
  eventId: string;
  observedAt: number;
  receivedAt?: number;
  actor: AccountEventActor;
  target: AccountEventActor & {
    handle: string;
  };
};
 
type AffiliateAccountIdentity = AccountEventActor & {
  id: string;
};
 
type AffiliateUpdateEvent = {
  action: 'added' | 'removed';
  eventId: string;
  observedAt: number;
  receivedAt?: number;
  organization: AffiliateAccountIdentity;
  member: AffiliateAccountIdentity;
};

account/profile_update

Apply only fields present in changes; absence means unchanged.

Profile update event

json
{
  "v": 1,
  "t": "account",
  "op": "profile_update",
  "id": "profile-1",
  "ts": 1772000001060,
  "d": {
    "actor": {
      "id": "10228272",
      "handle": "@TeamYouTube",
      "name": "TeamYouTube",
      "profileImage": "https://pbs.twimg.com/media/avatar.jpg",
      "websiteUrl": "https://youtube.com"
    },
    "changes": {
      "handle": "@TeamYouTube",
      "name": "Team YouTube",
      "websiteUrl": "https://youtube.com/new"
    },
    "eventId": "profile-1",
    "kind": "PROFILE",
    "observedAt": 1772000001060,
    "previous": {
      "handle": "@OldTeam"
    },
    "receivedAt": 1772000001050
  }
}

account/follow

Store the observed relationship using stable actor and target identifiers.

Follow event

json
{
  "v": 1,
  "t": "account",
  "op": "follow",
  "id": "follow-1",
  "ts": 1772000001060,
  "d": {
    "actor": {
      "id": "10228272",
      "handle": "@TeamYouTube"
    },
    "eventId": "follow-1",
    "kind": "FOLLOW",
    "observedAt": 1772000001060,
    "target": {
      "id": "4398626122",
      "handle": "@OpenAI"
    },
    "receivedAt": 1772000001050
  }
}

account/unfollow

Remove the observed relationship using the same identifiers.

Unfollow event

json
{
  "v": 1,
  "t": "account",
  "op": "unfollow",
  "id": "unfollow-1",
  "ts": 1772000001060,
  "d": {
    "actor": {
      "id": "10228272",
      "handle": "@TeamYouTube"
    },
    "eventId": "unfollow-1",
    "kind": "UNFOLLOW",
    "observedAt": 1772000001060,
    "target": {
      "id": "4398626122",
      "handle": "@OpenAI"
    },
    "receivedAt": 1772000001050
  }
}

account/affiliate_update

Apply the added or removed action idempotently to (organization.id, member.id). Use eventId only to suppress an exact replay.

Keyword filters do not apply. Replay stored changes with GET /api/history?type=affiliate. History is not a current-list snapshot and does not backfill changes from before the feature was enabled.

Affiliate update event

json
{
  "v": 1,
  "t": "account",
  "op": "affiliate_update",
  "id": "affiliate-update-1",
  "ts": 1772000001060,
  "d": {
    "action": "added",
    "organization": {
      "id": "10228272",
      "handle": "@TeamYouTube",
      "name": "TeamYouTube",
      "profileImage": "https://pbs.twimg.com/media/avatar.jpg",
      "websiteUrl": "https://youtube.com"
    },
    "member": {
      "id": "4398626122",
      "handle": "@OpenAI",
      "name": "OpenAI",
      "profileImage": "https://pbs.twimg.com/media/member-avatar.jpg"
    },
    "eventId": "affiliate-update-1",
    "observedAt": 1772000001060,
    "receivedAt": 1772000001050
  }
}