JSON de post e perfil do X, campo a campo: uma referência para agentes

JSON de post e perfil do X, campo a campo: uma referência para agentes
Unif Engineering team
Unif Engineering team

Atualizado

Cada campo que os endpoints grátis de X da UnifAPI retornam para posts, perfis, páginas, limites de taxa e erros, com tipos e casos de borda.

Em resumo: os endpoints do X na UnifAPI, grátis, sem fazer login e com limite por visitante, devolvem três registros (post, profile e o envelope page em volta das listas) mais um formato de erro e três headers de rate limit. Os nomes de campo são camelCase, os ids são strings (eles ultrapassam 2^53), as datas são ISO 8601 em UTC, as contagens são inteiros, e tudo o que o X não informa fica ausente em vez de zero. Esta página lista todos os campos com seu tipo e os casos que um programa precisa tratar: um repost que carrega o post original mais repostedBy, uma citação que aninha um nível, uma conta protegida que devolve suas contagens mas nenhum post, e views, que o X informa na maioria dos posts, mas não em todos.

Modelos são bons em ler JSON que já viram. A diferença entre um agente que usa uma fonte de dados corretamente e um que chuta nomes de campo é se a referência estava no contexto dele ou nos dados de treinamento. Esta é a referência. É o mesmo modelo que as páginas de visualizador para humanos renderizam, então o que você vê em /tools/x-profile-viewer é exatamente o que /tools/x/profile?handle=… devolve.

Convenções

  • Ids são strings. Os ids do X são de 64 bits; números em JSON perdem precisão acima de 2^53. Todo id é uma string, inclusive em URLs e cursores.
  • Datas são ISO 8601, UTC. createdAt e joinedAt se parecem com 2026-10-05T22:33:56.000Z.
  • Contagens são inteiros. Nunca strings formatadas, nunca nulls. Uma contagem que o X não informou fica de fora, não vira 0.
  • Opcional significa ausente. Um campo marcado como opcional não aparece no objeto quando não há valor. Teste com "views" in post.metrics, não com === 0.
  • URLs são URLs canônicas do x.com. post.url é https://x.com/<handle>/status/<id>; as URLs de mídia apontam para a CDN do X e nunca são re-hospedadas.

post

Devolvido por /tools/x/post (como post), e como cada item de posts.items em profile, media e search, e de replies.items em replies.

CampoTipoSignificado
idstringID do post
textstringTexto completo. Posts longos (notes) são devolvidos por inteiro; o link curto de mídia no final é removido quando há mídia anexada
createdAtstring (ISO 8601)Hora de publicação
languagestring, opcionalCódigo BCP-47 detectado pelo X (en, ja, …)
conversationIdstring, opcionalId do post raiz da thread à qual este post pertence
inReplyToPostIdstring, opcionalO post que este responde, quando é uma resposta
possiblySensitivebooleanA flag do próprio X
urlstringURL canônica do x.com
authorprofile ou nullO autor; null só quando o X o omitiu
metricsobjectVeja abaixo
mediaarray de mediaVazio quando não há
repostedByobject ou nullDefinido quando esta entrada é um repost: { id, handle, name } da conta que repostou. O resto do registro é o post original
quotedpost ou nullO post citado quando este é um post com citação, aninhado um nível (uma citação dentro de uma citação não é expandida)

metrics

CampoTipoSignificado
likesinteger
repostsintegerReposts (retweets), sem contar citações
repliesintegerA contagem de respostas do X; pode ser maior que o número de respostas públicas legíveis
quotesintegerPosts com citação
bookmarksinteger
viewsinteger, opcionalImpressões. O X as informa na maioria dos posts; ausente quando não informa

media

CampoTipoSignificado
kindphoto | video | animated_gif
urlstring, opcionalImagem em tamanho completo, ou o frame de capa para vídeo e GIF
previewUrlstring, opcionalIgual a url hoje; reservado para uma versão menor
width, heightinteger, opcionalDimensões originais
durationMsinteger, opcionalDuração do vídeo
videoUrlstring, opcionalO MP4 de maior bitrate que o X expõe, na CDN do X

profile

Devolvido por /tools/x/profile, /tools/x/media e /tools/x/followers (como profile), como post.author, e como cada item de users.items em followers.

CampoTipoSignificado
idstringID do usuário
handlestringSem o @, com a capitalização do X (NASA)
namestringNome de exibição
verifiedbooleanQualquer verificação (azul, governo, empresa)
verifiedTypestring, opcionalGovernment, Business, … quando o X nomeia uma
protectedbooleanOs posts não são públicos. Os endpoints devolvem contagens, mas nenhum post
biostringPode estar vazia
locationstringTexto livre, pode estar vazio
websitestring, opcionalURL expandida, não o link curto t.co
joinedAtstring (ISO 8601)
avatarUrlstring, opcionalVersão 400×400
bannerUrlstring, opcional
followersinteger
followinginteger
postsintegerContagem de posts de toda a vida da conta
listedinteger, opcionalListas em que a conta aparece, quando informado
pinnedPostIdstring, opcional
urlstringhttps://x.com/<handle>

/tools/x/profile acrescenta engagementRate: a média de curtidas, respostas, reposts e citações por post original na página, dividida pelos seguidores, como porcentagem com quatro algarismos significativos. Reposts ficam fora da média. Para uma conta com 90 milhões de seguidores é um número pequeno (0.0058), o que é correto, não um bug.

page

Toda lista vem embrulhada:

{ "items": [ … ], "hasMore": true, "nextCursor": "DAAHCgABHUAq3YL__-wLAAIAAAATMj…" }
CampoTipoSignificado
itemsarrayregistros post, ou registros profile em followers, ou registros community
hasMorebooleanTrue exatamente quando nextCursor está definido
nextCursorstring ou nullOpaco. Devolva como cursor= para receber a próxima página

Tamanhos de página: 10 posts em profile, 12 em media, 20 em replies, search e communities, 50 em followers, 30 tendências. Os cursores são opacos; alguns se parecem com 20@, outros com as strings DAAH… do próprio X. Nunca os interprete.

Tendências e comunidades

/tools/x/trends devolve { woeid, locationSlug, generatedAt, trends: [ { rank, name, postCount?, url } ] }. postCount só está presente nas tendências para as quais o X informa um volume; para a maioria das localidades hoje isso é nenhuma, então trate-o como opcional. url é a busca ao vivo no x.com.

/tools/x/communities devolve { query, communities: page }, em que cada item é { id, name, description, memberCount?, access?, joinPolicy?, createdAt?, url }.

Headers de rate limit

Em toda resposta, de sucesso ou de erro:

X-RateLimit-Limit: 20
X-RateLimit-Remaining: 17
X-RateLimit-Reset: 1791357984

Reset é o instante, em segundos Unix, em que a janela atual de 10 minutos termina. Uma busca custa 2 unidades, todo o resto custa 1. Um 429 acrescenta Retry-After em segundos.

Erros

Toda resposta não 2xx é:

{ "error": { "type": "not_found", "message": "X user not found: @nobody_here_123" } }
typeHTTPQuando
validation_error400Entrada ausente ou malformada (Missing handle: pass ?handle=…)
not_found404Conta ou post inexistente; contas suspensas dizem isso na mensagem
rate_limited429Limite gratuito atingido; o corpo acrescenta retryAfterSeconds e upgrade
upstream_error502A camada de dados do X respondeu com erro
upstream_unavailable503Timeout ou inacessível
not_configured503O deployment não tem credenciais de upstream

Ramifique em type; message é para humanos e pode mudar.

Modo Markdown

Adicione format=md ou envie Accept: text/markdown a qualquer endpoint e o mesmo registro é renderizado em Markdown: um título com o autor, o texto, uma linha de métricas, links de mídia, a URL e um rodapé com o próximo cursor. Ele carrega todos os campos acima, exceto os ids brutos dentro do objeto do autor, e é o jeito mais barato de colocar um perfil ou uma thread no contexto de um modelo.

Onde ficam as amostras

A página em Markdown de cada ferramenta traz uma resposta real capturada do seu endpoint, cortada para poucos itens: /tools/x-profile-viewer/index.md, /tools/x-post-viewer/index.md, /tools/x-search/index.md e assim por diante. /llms.txt lista todos os oito com uma URL de exemplo cada. A API do X / Twitter medida usa os mesmos nomes de campo atrás de uma chave de workspace, então o código escrito contra os endpoints gratuitos migra sem edições.