Core concepts

Targets and keywords are different things

A target is an account you watch; you get everything it does, or only the event types you choose. A keyword is a query you watch across all of X; you get posts from anyone that match it, as search.match events. Targets are identified by handle, keywords by the query text, and a key holds any number of each up to its plan's caps.

An account is its id, not its handle

You monitor an account, identified by its numeric X id (id on a Target). An account can change its handle (screen_name) or display name at any time: you keep receiving its events, later events carry the new handle in target.screen_name, and a profile.screen_name or profile.name event tells you what changed. Key your records on id. Wherever the API takes an account you can name it by its user_id, its current handle or a handle it had before.

Two-phase delivery: create, then update

Some post events are delivered in two frames. The first, op: "create", carries the essentials — the post id, the author and the text — so you can act on it immediately. A moment later the same event id arrives again with op: "update", now carrying media, the quoted or replied-to original, counts and the rest. Events that are complete when first seen have no second frame; GET /v1/meta/event-types says which types can have one.

What to do about it. If you need speed, act on create. If you need the whole post, wait for update on the same id. Either way, key your storage on id and let a later update overwrite what you kept. The type changes between the two frames in one way only: a first tweet.create with kind_final: false can become tweet.quote. If you treat original posts and quotes differently, sort such a frame once its update arrives.

At-least-once, never exactly-once

Every monitored account is watched by several independent paths at once, so that one failing path costs you nothing. The first to report a given change wins and becomes the event; the others are recorded as corroboration rather than delivered again. Across a reconnect, however, you may see an event you already have. Deduplicate on id.

Position and replay

Each event carries a sid — its position in our log. Persist the last one you processed; on reconnect, pass it as ?last_id= and we send everything after it before resuming live. The log holds 24 hours, and a single reconnect replays at most 5,000 events. Targets or keywords you add while a socket is open start flowing on it within 30 seconds; you do not need to reconnect.