Eventos
Envelope
Todo evento tem o mesmo envelope; d carrega o payload específico do tipo, descrito abaixo.
| Campo | Tipo | Significado |
|---|---|---|
v | int | Versão do envelope. 1 hoje |
t | string | Tipo do evento, conforme a tabela abaixo |
op | create | update | delete | create, update (enriquecimento do mesmo id) ou delete |
id | string | Identidade estável. Deduplique por ele |
ts | int (ms) | Quando aconteceu no X, em ms desde a época Unix. O X não informa quando um perfil mudou, quando alguém foi seguido ou deixou de ser seguido, quando chegou um seguidor verificado nem quando uma publicação foi apagada: nesses eventos é quando detectamos |
sid | string | Posição no stream para replay; presente no stream e no histórico |
target.id | string | Id numérico no X da conta monitorada (para search.match, do autor da publicação) |
target.screen_name | string | Nome de usuário da conta monitorada |
target.name | string | O nome de exibição da conta |
d | object | Payload específico do tipo |
Tipos de evento
| Tipo | Categoria | Significado |
|---|---|---|
tweet.create | Publicações | A conta publicou algo novo |
tweet.reply | Publicações | Ela respondeu a alguém; reply_to traz a publicação respondida, com texto e mídia |
tweet.retweet | Publicações | Ela republicou alguém; retweet_of traz a publicação original completa |
tweet.quote | Publicações | Ela citou alguém; quoted traz a publicação citada completa |
tweet.edit | Publicações | Editou uma publicação; o evento traz a nova versão e edit_of a versão que ela substitui |
tweet.delete | Publicações | Uma publicação que a conta havia feito desapareceu |
profile.name | Perfil | Nome de exibição alterado |
profile.screen_name | Perfil | Nome de usuário alterado |
profile.bio | Perfil | Bio alterada |
profile.location | Perfil | Localização alterada |
profile.url | Perfil | Link do perfil alterado |
profile.avatar | Perfil | Avatar alterado; old e new são URLs de imagem |
profile.banner | Perfil | Banner alterado; old e new são URLs de imagem |
profile.pinned | Perfil | Publicação fixada alterada; tweet e old_tweet trazem as próprias publicações |
profile.verified | Perfil | Selo de verificação apareceu ou desapareceu |
follow.add | Seguidos e seguidores | A conta começou a seguir alguém; user é o perfil completo dessa conta |
follow.remove | Seguidos e seguidores | A conta parou de seguir alguém |
followers.verified.add | Seguidos e seguidores | Uma conta verificada começou a segui-la; user traz bio, contagens, localização e data de entrada |
account.status | Conta | A conta ficou protegida, suspensa ou indisponível, ou voltou a ficar ativa |
search.match | Busca | Alguém publicou algo que corresponde a uma das suas palavras-chave; keyword diz qual, author é o perfil completo do autor |
O X não fornece timestamp para "começou a seguir" ou "ganhou um seguidor", então, para esses eventos, ts é o momento em que detectamos a alteração.
Payloads
Cinco formatos de payload cobrem todos os dezoito tipos.
Payload de tweet
O d de tweet.create, tweet.reply, tweet.retweet e tweet.quote, e a base de search.match.
| Campo | Tipo | Significado |
|---|---|---|
tweet_id | string | O id da publicação, como string |
kind | tweet | reply | retweet | quote | Que tipo de publicação é |
text | string | Texto completo (incluindo publicações longas) |
lang | string | null | Idioma detectado pelo X |
author | User | A conta que publicou, como User completo — o mesmo objeto do autor de um search.match: nome de usuário, nome, bio, avatar, banner, contadores, verificação, localização, link e data de entrada. Num primeiro frame enxuto é a conta como lida pela última vez; o update a traz como lida junto com a publicação |
reply_to | Brief+ | null | Para respostas: a publicação respondida — um Brief mais screen_name, tweet_id e user_id do seu autor |
retweet_of | Brief | null | Para republicações: a publicação original |
quoted | Brief | null | Para citações: a publicação citada |
media | string[] | URLs de imagem simples, uma por item de mídia |
media_items | Media[] | Cada item de mídia com tipo, variantes de vídeo e dimensões |
urls | string[] | Links expandidos na publicação |
article | Article | null | Em posts que apontam para um artigo do X: o artigo |
counts | {reply, rt, like, quote, bookmark} | Contagens de respostas, republicações, curtidas, citações e itens salvos no momento em que lemos |
views | int | null | Contagem de visualizações, quando o X a expõe |
url | string | Link canônico da publicação |
full | bool | false em um primeiro frame create enxuto; true quando o evento traz a publicação inteira |
kind_final | bool | true quando kind está definido. false apenas em um primeiro frame enxuto cujo kind é tweet: a publicação ainda pode se revelar uma citação, e o update do mesmo id resolve |
kind_was | tweet | null (update only) | Só no update que define o tipo de uma publicação, e só quando o primeiro frame dizia outra coisa: o tipo que esse frame tinha (tweet para uma publicação que se revelou uma citação) |
edit_of | Brief | null | Em tweet.edit: a versão que esta substitui (o id, e o texto e o autor quando os tínhamos) |
{
"v": 1,
"t": "tweet.create",
"op": "create",
"id": "tweet:2097879002992070835",
"ts": 1789012345678,
"sid": "1789012346012-0",
"target": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters"
},
"d": {
"tweet_id": "2097879002992070835",
"kind": "tweet",
"text": "Ash-covered shoes and a president in crisis…",
"lang": "en",
"author": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters",
"bio": "Top and breaking news, pictures and videos from Reuters.",
"avatar": "https://pbs.twimg.com/profile_images/1874154135869616128/nJDmubGJ_normal.jpg",
"banner": "https://pbs.twimg.com/profile_banners/1652541/1573687397",
"followers": 25900000,
"following": 1150,
"tweets": 1080000,
"location": "Around the world",
"url": "https://www.reuters.com",
"verified": true,
"verified_type": "Business",
"protected": false,
"created_at": "2007-03-20T17:46:05Z",
"category": null
},
"reply_to": null,
"retweet_of": null,
"quoted": null,
"media": [
"https://pbs.twimg.com/media/….jpg"
],
"media_items": [
{
"type": "photo",
"url": "https://pbs.twimg.com/media/….jpg",
"expanded_url": "https://x.com/Reuters/status/2097879002992070835/photo/1",
"width": 1200,
"height": 675
}
],
"urls": [
"https://reut.rs/…"
],
"counts": {
"reply": 12,
"rt": 40,
"like": 131,
"quote": 3,
"bookmark": 9
},
"views": 20411,
"url": "https://x.com/Reuters/status/2097879002992070835",
"full": true,
"kind_final": true
}
}Um primeiro frame create é deliberadamente enxuto: traz o id, o autor (author, a conta como lida pela última vez) e o texto, que pode vir encurtado, para que possa sair no instante em que o post é visto; url já aponta para o post. Nesse momento nem sempre dá para distinguir uma citação de uma publicação original, então esse frame diz tweet.create com kind_final: false. O update que vem em seguida com o mesmo id traz a carga completa acima e o tipo definido: tweet.quote com kind_was: "tweet" se era uma citação.
{
"v": 1,
"t": "tweet.create",
"op": "create",
"id": "tweet:2097879002992070835",
"ts": 1789012345678,
"sid": "1789012346012-0",
"target": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters"
},
"d": {
"tweet_id": "2097879002992070835",
"kind": "tweet",
"text": "Ash-covered shoes and a president in crisis…",
"author": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters",
"bio": "Top and breaking news, pictures and videos from Reuters.",
"avatar": "https://pbs.twimg.com/profile_images/1874154135869616128/nJDmubGJ_normal.jpg",
"banner": "https://pbs.twimg.com/profile_banners/1652541/1573687397",
"followers": 25900000,
"following": 1150,
"tweets": 1080000,
"location": "Around the world",
"url": "https://www.reuters.com",
"verified": true,
"verified_type": "Business",
"protected": false,
"created_at": "2007-03-20T17:46:05Z",
"category": null
},
"url": "https://x.com/Reuters/status/2097879002992070835",
"full": false,
"kind_final": false
}
}Payload de exclusão
O d de tweet.delete. Só é enviado para uma publicação que havíamos visto e que agora sumiu. Seu ts é quando a remoção foi detectada; o horário da própria publicação está no frame create anterior.
| Campo | Tipo | Significado |
|---|---|---|
tweet_id | string | O id da publicação excluída |
url | string | Onde ela costumava estar |
{
"v": 1,
"t": "tweet.delete",
"op": "delete",
"id": "tweet:2097879002992070835:delete",
"ts": 1789012345678,
"sid": "…",
"target": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters"
},
"d": {
"tweet_id": "2097879002992070835",
"url": "https://x.com/Reuters/status/2097879002992070835"
}
}Payload de alteração de perfil
O d de todo evento profile.*. Para estes, op é update.
| Campo | Tipo | Significado |
|---|---|---|
field | string | Qual campo do perfil mudou; a mesma palavra que vem depois de profile. no tipo |
old | any | O valor anterior |
new | any | O novo valor |
tweet | Brief (pinned only) | Para profile.pinned: a publicação recém-fixada |
old_tweet | Brief (pinned only) | Para profile.pinned: a publicação fixada anteriormente, se a tínhamos |
{
"v": 1,
"t": "profile.bio",
"op": "update",
"id": "profile:1652541:bio:9c1d2e3f4a5b",
"ts": 1789012400000,
"sid": "…",
"target": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters"
},
"d": {
"field": "bio",
"old": "Top news and analysis from around the world.",
"new": "Top news, analysis and video from around the world."
}
}Payload de seguir
O d de follow.add, follow.remove e followers.verified.add.
| Campo | Tipo | Significado |
|---|---|---|
user | User | A outra conta, como um User completo |
{
"v": 1,
"t": "follow.add",
"op": "create",
"id": "follow:44196397:12:add:496948",
"ts": 1789012400000,
"sid": "…",
"target": {
"id": "44196397",
"screen_name": "elonmusk",
"name": "Elon Musk"
},
"d": {
"user": {
"id": "12",
"screen_name": "jack",
"name": "jack",
"bio": "…",
"avatar": "https://pbs.twimg.com/profile_images/…",
"banner": null,
"followers": 6400000,
"following": 4200,
"tweets": 29000,
"location": "",
"url": null,
"verified": true,
"verified_type": "blue",
"protected": false,
"created_at": "2006-03-21T20:50:14Z",
"category": null
}
}
}Carga de status da conta
O d de account.status. Um status é active, protected (publicações visíveis só para seguidores aprovados), suspended (pelo X) ou unavailable (desativada, excluída ou não visível por outro motivo). ts é quando detectamos a mudança.
| Campo | Tipo | Significado |
|---|---|---|
old | active | protected | suspended | unavailable | O status anterior |
new | active | protected | suspended | unavailable | O status atual |
reason | string | null | O texto do X, quando houver (por exemplo Suspended) |
{
"v": 1,
"t": "account.status",
"op": "update",
"id": "account:9000002:status:active>suspended:497010",
"ts": 1789236000000,
"sid": "…",
"target": {
"id": "9000002",
"screen_name": "some_account",
"name": "Some Account"
},
"d": {
"old": "active",
"new": "suspended",
"reason": "Suspended"
}
}Payload de correspondência de busca
O d de search.match: um payload de tweet mais três campos sobre a correspondência. O target do envelope é o autor da publicação, que não precisa ser uma das suas contas monitoradas.
| Campo | Tipo | Significado |
|---|---|---|
keyword.id | int | Id da palavra-chave que correspondeu |
keyword.query | string | A busca dela |
keyword.label | string | null | O rótulo dela, se você definiu um |
author | User | O perfil completo do autor |
author_is_target | bool | true se o autor também é uma conta monitorada neste sistema |
… | TweetPayload | Todos os campos do payload de tweet |
{
"v": 1,
"t": "search.match",
"op": "create",
"id": "search:12:2097900000000000000",
"ts": 1789012500000,
"sid": "…",
"target": {
"id": "9000001",
"screen_name": "some_trader",
"name": "Some Trader"
},
"d": {
"tweet_id": "2097900000000000000",
"kind": "tweet",
"text": "$SOL breaking out…",
"lang": "en",
"author": {
"id": "9000001",
"screen_name": "some_trader",
"name": "Some Trader",
"bio": "…",
"followers": 1200,
"verified": false,
"…": "…"
},
"keyword": {
"id": 12,
"query": "($SOL OR \"Solana\") -filter:retweets",
"label": "solana"
},
"author_is_target": false,
"media": [],
"media_items": [],
"urls": [],
"url": "https://x.com/some_trader/status/2097900000000000000",
"full": true
}
}