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

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,profilee o envelopepageem 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 maisrepostedBy, uma citação que aninha um nível, uma conta protegida que devolve suas contagens mas nenhum post, eviews, 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.
createdAtejoinedAtse parecem com2026-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.
| Campo | Tipo | Significado |
|---|---|---|
id | string | ID do post |
text | string | Texto completo. Posts longos (notes) são devolvidos por inteiro; o link curto de mídia no final é removido quando há mídia anexada |
createdAt | string (ISO 8601) | Hora de publicação |
language | string, opcional | Código BCP-47 detectado pelo X (en, ja, …) |
conversationId | string, opcional | Id do post raiz da thread à qual este post pertence |
inReplyToPostId | string, opcional | O post que este responde, quando é uma resposta |
possiblySensitive | boolean | A flag do próprio X |
url | string | URL canônica do x.com |
author | profile ou null | O autor; null só quando o X o omitiu |
metrics | object | Veja abaixo |
media | array de media | Vazio quando não há |
repostedBy | object ou null | Definido quando esta entrada é um repost: { id, handle, name } da conta que repostou. O resto do registro é o post original |
quoted | post ou null | O 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
| Campo | Tipo | Significado |
|---|---|---|
likes | integer | |
reposts | integer | Reposts (retweets), sem contar citações |
replies | integer | A contagem de respostas do X; pode ser maior que o número de respostas públicas legíveis |
quotes | integer | Posts com citação |
bookmarks | integer | |
views | integer, opcional | Impressões. O X as informa na maioria dos posts; ausente quando não informa |
media
| Campo | Tipo | Significado |
|---|---|---|
kind | photo | video | animated_gif | |
url | string, opcional | Imagem em tamanho completo, ou o frame de capa para vídeo e GIF |
previewUrl | string, opcional | Igual a url hoje; reservado para uma versão menor |
width, height | integer, opcional | Dimensões originais |
durationMs | integer, opcional | Duração do vídeo |
videoUrl | string, opcional | O 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.
| Campo | Tipo | Significado |
|---|---|---|
id | string | ID do usuário |
handle | string | Sem o @, com a capitalização do X (NASA) |
name | string | Nome de exibição |
verified | boolean | Qualquer verificação (azul, governo, empresa) |
verifiedType | string, opcional | Government, Business, … quando o X nomeia uma |
protected | boolean | Os posts não são públicos. Os endpoints devolvem contagens, mas nenhum post |
bio | string | Pode estar vazia |
location | string | Texto livre, pode estar vazio |
website | string, opcional | URL expandida, não o link curto t.co |
joinedAt | string (ISO 8601) | |
avatarUrl | string, opcional | Versão 400×400 |
bannerUrl | string, opcional | |
followers | integer | |
following | integer | |
posts | integer | Contagem de posts de toda a vida da conta |
listed | integer, opcional | Listas em que a conta aparece, quando informado |
pinnedPostId | string, opcional | |
url | string | https://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…" }
| Campo | Tipo | Significado |
|---|---|---|
items | array | registros post, ou registros profile em followers, ou registros community |
hasMore | boolean | True exatamente quando nextCursor está definido |
nextCursor | string ou null | Opaco. 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" } }
type | HTTP | Quando |
|---|---|---|
validation_error | 400 | Entrada ausente ou malformada (Missing handle: pass ?handle=…) |
not_found | 404 | Conta ou post inexistente; contas suspensas dizem isso na mensagem |
rate_limited | 429 | Limite gratuito atingido; o corpo acrescenta retryAfterSeconds e upgrade |
upstream_error | 502 | A camada de dados do X respondeu com erro |
upstream_unavailable | 503 | Timeout ou inacessível |
not_configured | 503 | O 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.