API do Twitter em PHP: obtenha dados do X com cURL, Guzzle e Laravel
Para obter dados do Twitter (X) em PHP, envie requisições HTTPS com cURL ou Guzzle, coloque a chave de API em um header, decodifique o JSON e siga o cursor página por página; a API oficial do X cobra US$ 0,005 por post.
Resposta curta: O X publica SDKs oficiais só para Python e TypeScript, então o PHP chega à API oficial do X por clientes da comunidade, como o TwitterOAuth, com uma conta de desenvolvedor e créditos pré-pagos: US$ 0,005 por post e US$ 0,015 com o autor, a partir de 22 de novembro de 2026. Para dados públicos, use a Sorsa API: uma chave, 20 tweets por requisição a partir de US$ 0,07 por 1.000; 100 requisições grátis cobrem 2.000.
- Endpoint
POST /user-tweets- Tamanho da página
- 20 tweets por requisição
- Preço
- a partir de US$ 0,07 por 1.000 tweets
#Existe um SDK oficial da API do X para PHP?
Não. O X publica SDKs oficiais só para Python e TypeScript, e a página de ferramentas dele lista três clientes PHP da comunidade que o X não mantém: twitter-api-v2-php, bird-elephant e TwitterOAuth (ferramentas e bibliotecas do X (abre em uma nova aba)). O TwitterOAuth é o mais instalado dos três, com cerca de 240 mil instalações por mês no Composer. A versão 9.0.0 dele, lançada em 1º de novembro de 2026, fala apenas com a API v2 e exige PHP 8.3 ou posterior.
Os três são clientes da API oficial do X, então cada chamada que fazem exige uma conta de desenvolvedor, as chaves de um app e créditos pré-pagos. Novos desenvolvedores não têm plano gratuito, e o X cobra cada objeto que uma resposta devolve: US$ 0,005 por post e US$ 0,010 por usuário, até 3 milhões de posts lidos por mês (tabela de preços do X (abre em uma nova aba)). A partir de 22 de novembro de 2026, os autores e as mídias trazidos por expansões são cobrados pelas mesmas tarifas (aviso do X de 23 de outubro (abre em uma nova aba)), então a busca usual do TwitterOAuth paga por cada autor que anexa:
use Abraham\TwitterOAuth\TwitterOAuth;
$x = new TwitterOAuth($apiKey, $apiSecret, null, $bearerToken);
$posts = $x->get('tweets/search/recent', [
'query' => 'laravel lang:en',
'max_results' => 100,
'expansions' => 'author_id',
]);
// 100 posts: $0.50. From Nov 22, 2026, with authors: up to $1.50
Respostas mais antigas apontam para mais longe no passado. O primeiro resultado do Google para esta busca é o J7mbo/twitter-api-php, um wrapper para chamadas da v1.1 cujo repositório no GitHub está arquivado e foi alterado pela última vez em abril de 2020. Todas as tarifas, limites e datas atuais da rota oficial estão em preços da API do X.
O que a rota oficial exige antes da primeira chamada
- Uma conta de desenvolvedor em console.x.com, aberta com uma conta do X e com o Contrato de Desenvolvedor do X aceito.
- Um app com a sua API key, API secret e bearer token, que o X mostra uma única vez (guia de acesso do X (abre em uma nova aba)).
- Créditos comprados antecipadamente e gastos por post e por usuário devolvido.
- Tokens de usuário OAuth 1.0a, um access token e o respectivo secret, para qualquer coisa que poste; o construtor de quatro argumentos do TwitterOAuth os recebe.
Nada disso é necessário para ler posts e perfis públicos. A próxima seção faz isso com uma chave e a extensão cURL que a maioria das builds do PHP já inclui.
#Obtenha tweets em PHP com uma só chave de API
Para ler dados do X a partir do PHP, use a Sorsa API, uma API e scraper do Twitter (X): um header ApiKey no lugar do OAuth, 20 requisições por segundo em todos os planos, inclusive nas contas grátis, e timelines e busca a partir de US$ 0,07 por 1.000 tweets. Toda resposta é JSON simples que o json_decode transforma em arrays, com o perfil completo do autor dentro de cada tweet. Ela nunca pede o seu login do X, então a sua conta do X não corre risco.
-
Obtenha uma chave. Cadastre-se e copie a sua chave de API no painel. As primeiras 100 requisições são grátis, não pedem cartão e nunca expiram.
-
Mantenha a chave fora do código. Defina-a como variável de ambiente, ou no
.envdo Laravel, e chame a API apenas a partir de PHP no servidor: uma chave em JavaScript no navegador fica visível para todo visitante.Terminal export SORSA_API_KEY="your_key" # PowerShell: $env:SORSA_API_KEY="your_key" -
Busque os tweets mais recentes de uma conta. Envie o nome de usuário para
POST /user-tweets(abre em uma nova aba) com a chave no headerApiKey. Experimente primeiro pelo terminal:Terminal curl -X POST "https://api.sorsa.io/v3/user-tweets" \ -H "ApiKey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"username": "php_release_notes"}' -
Chame-a a partir do PHP. O cURL simples não precisa de nenhum pacote do Composer. Com o Guzzle, termine o
base_uricom uma barra e comece o caminho sem ela, ou a parte/v3se perde.<?php $key = getenv('SORSA_API_KEY') ?: 'YOUR_API_KEY'; $ch = curl_init('https://api.sorsa.io/v3/user-tweets'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'ApiKey: ' . $key, 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode(['username' => 'php_release_notes']), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, ]); $body = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); $data = json_decode($body, true, flags: JSON_THROW_ON_ERROR); if ($status !== 200) { exit("HTTP $status: {$data['message']}\n"); } foreach ($data['tweets'] as $tweet) { echo $tweet['created_at'], ' ', mb_substr($tweet['full_text'], 0, 60), "\n"; } -
Leia a página. Cada resposta traz até 20 tweets e um
next_cursorenquanto ainda restam resultados. Os valores abaixo são dados de demonstração no formato documentado.Response200 OK { "tweets": [ { "id": "1985432176540981234", "full_text": "PHP 8.5.12 is out with two security fixes. Upgrade today.", "created_at": "2026-11-01T18:42:07Z", "lang": "en", "likes_count": 42, "retweet_count": 7, "reply_count": 3, "quote_count": 1, "view_count": 3810, "bookmark_count": 5, "is_reply": false, "user": { "id": "1592041833471827968", "username": "php_release_notes", "display_name": "PHP Release Notes", "followers_count": 1840, "verified": false } } ], "next_cursor": "DAABCgABF7Y8kQ3wAAA" }
Cada tweet chega com as suas contagens e o seu autor, então um script PHP não define expansões nem listas de campos. Estes são os campos que a maioria dos scripts lê:
| Campo | O que contém |
|---|---|
id | O ID do tweet: 19 dígitos, enviado como string |
full_text | O texto completo do post |
created_at | O horário em ISO 8601, UTC, pronto para new DateTimeImmutable() |
likes_count, retweet_count, reply_count, quote_count | Contagens de engajamento |
view_count, bookmark_count | Visualizações e itens salvos |
user | O perfil do autor: 19 campos, como username e followers_count |
quoted_status, retweeted_status | O tweet citado ou repostado, no mesmo formato |
id- O que contém
- O ID do tweet: 19 dígitos, enviado como string
full_text- O que contém
- O texto completo do post
created_at- O que contém
- O horário em ISO 8601, UTC, pronto para
new DateTimeImmutable()
likes_count,retweet_count,reply_count,quote_count- O que contém
- Contagens de engajamento
view_count,bookmark_count- O que contém
- Visualizações e itens salvos
user- O que contém
- O perfil do autor: 19 campos, como
usernameefollowers_count
quoted_status,retweeted_status- O que contém
- O tweet citado ou repostado, no mesmo formato
#Uma função de requisição com retentativas
Envie toda chamada por uma única função que repete apenas o que uma nova tentativa pode resolver. Um 429 significa que mais de 20 requisições começaram dentro de um segundo na sua chave, e um 5xx ou uma conexão interrompida é uma falha temporária; as duas se resolvem sozinhas. A sorsa() repete até quatro vezes, esperando 1, 2, 4 e 8 segundos, e envia os parâmetros GET como chaves repetidas, a forma que os endpoints de lote abaixo leem. O resto deste guia se apoia nela.
<?php
const SORSA_API = 'https://api.sorsa.io/v3';
const RETRY = [429, 500, 502, 503, 504];
/** Build a query string; a list becomes a repeated key: a=1&a=2. */
function query(array $params): string
{
$parts = [];
foreach ($params as $name => $value) {
foreach ((array) $value as $one) {
$parts[] = rawurlencode($name) . '=' . rawurlencode($one);
}
}
return implode('&', $parts);
}
/** Send one request; retry 429, 5xx and network errors up to 4 times. */
function sorsa(string $method, string $path, array $params = []): array
{
$url = SORSA_API . $path;
$headers = ['ApiKey: ' . (getenv('SORSA_API_KEY') ?: 'YOUR_API_KEY')];
$options = [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30];
if ($method === 'GET') {
$url .= $params ? '?' . query($params) : '';
} else {
$headers[] = 'Content-Type: application/json';
$options[CURLOPT_POSTFIELDS] = json_encode($params);
}
$options[CURLOPT_HTTPHEADER] = $headers;
for ($attempt = 0; ; $attempt++) {
$ch = curl_init($url);
curl_setopt_array($ch, $options);
$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); // 0: no answer
$again = in_array($status, [0, ...RETRY], true);
if (!$again || $attempt === 4) {
break;
}
sleep(2 ** $attempt); // 1, 2, 4, 8 seconds
}
if ($raw === false) {
throw new RuntimeException('Network error: ' . curl_error($ch));
}
$data = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);
if ($status !== 200) {
throw new RuntimeException("HTTP $status: " . ($data['message'] ?? ''));
}
return $data;
}
Um 401 ou um 403 nunca merece nova tentativa: a chave está errada ou ausente, ou suas requisições acabaram, e o campo message diz qual é o caso. Requisições que falham nunca são cobradas, então repetir não custa nada, e todo endpoint da Sorsa API só lê, então repetir um POST não cria nada em duplicidade. A função roda no PHP 8.0 e posteriores. Ela dispensa o curl_close(), que não faz nada desde o PHP 8.0, porque os handles do cURL agora se fecham sozinhos.
#Percorra os resultados com next_cursor
Um cursor é uma chave opaca para a próxima página de resultados: devolva o next_cursor sem alterações e pare quando uma resposta vier sem ele. As timelines e o POST /search-tweets (abre em uma nova aba) devolvem até 20 tweets por página, e uma página pode trazer menos enquanto ainda restam resultados, então a contagem de itens nunca indica que o fim chegou. Um gerador entrega uma página por vez e mantém a memória estável por mais longo que seja o job.
require 'sorsa.php';
/** Yield pages of a POST endpoint until the cursor runs out. */
function pages(string $path, array $body, int $maxPages = 100): Generator
{
for ($i = 0; $i < $maxPages; $i++) {
$page = sorsa('POST', $path, $body);
yield $page;
if (empty($page['next_cursor'])) {
return;
}
$body['next_cursor'] = $page['next_cursor'];
}
}
foreach (pages('/search-tweets', ['query' => 'laravel lang:en']) as $page) {
foreach ($page['tweets'] as $tweet) {
echo $tweet['id'], ' @', $tweet['user']['username'], "\n";
}
}
Mantenha a consulta e o order inalterados enquanto um cursor estiver em uso e trate $maxPages como um orçamento: 100 páginas são 100 requisições e no máximo 2.000 tweets. Os endpoints GET recebem o cursor na query string. O GET /followers (abre em uma nova aba) devolve até 200 perfis por página:
$params = ['username' => 'php_release_notes'];
$followers = [];
do {
$page = sorsa('GET', '/followers', $params);
array_push($followers, ...$page['users']);
$params['next_cursor'] = $page['next_cursor'] ?? null;
} while ($params['next_cursor']);
Duas tarefas têm scripts completos próprios: baixar todos os tweets de um usuário retoma uma timeline inteira a partir de um cursor salvo, e o guia para exportar seguidores do Twitter grava listas de seguidores em CSV.
#Busque 100 tweets ou perfis por requisição
Quando você já tem IDs de tweets ou nomes de usuário, envie-os em lotes. O POST /tweet-info-bulk (abre em uma nova aba) recebe até 100 IDs ou links de tweets, e o GET /info-batch (abre em uma nova aba) recebe até 100 nomes de usuário. As respostas em lote não têm cursor: uma resposta traz o lote inteiro.
$tweets = [];
foreach (array_chunk($tweetIds, 100) as $batch) {
$res = sorsa('POST', '/tweet-info-bulk', ['tweet_links' => $batch]);
array_push($tweets, ...$res['tweets']);
}
$profiles = [];
foreach (array_chunk($usernames, 100) as $batch) {
$res = sorsa('GET', '/info-batch', ['usernames' => $batch]);
array_push($profiles, ...$res['users']);
}
Uma requisição custa o mesmo seja qual for o retorno, então um lote de 100 tweets custa o mesmo que um tweet: a partir de US$ 0,014 por 1.000 tweets, mais de 250 vezes menos que os US$ 5,00 da API oficial do X. As 100 requisições grátis cobrem 10 mil tweets dessa forma.
Bom saber
O
GET /info-batchlê uma lista como uma chave repetida,usernames=a&usernames=b, a forma que a referência OpenAPI dele define. Ohttp_build_query()do PHP escreveusernames%5B0%5D=a&usernames%5B1%5D=bem vez disso, e o mesmo fazem a opçãoquerycom array do Guzzle e oHttp::get($url, $array)do Laravel, que montam a consulta da mesma maneira. Use o helperquery()acima, ou oGuzzleHttp\Psr7\Query::build(), que escreve chaves repetidas.
#Rode lotes em paralelo a 19 requisições por segundo
O PHP executa requisições lado a lado com o curl_multi, e um único processo alcança as 20 requisições por segundo por chave da Sorsa API assim que o trabalho se divide em requisições independentes. Os lotes se dividem bem, porque cada um é autônomo. Uma cadeia de cursor não pode ser dividida, já que cada página precisa do cursor da anterior, então rode contas ou janelas de datas separadas lado a lado. A parallel() inicia no máximo 19 requisições por segundo, uma abaixo do limite, e recoloca na fila qualquer 429 ou 5xx.
/** POST many bodies side by side, starting at most $rate a second. */
function parallel(string $path, array $bodies, float $rate = 19): array
{
$multi = curl_multi_init();
$queue = array_keys($bodies);
$tries = $results = [];
$next = microtime(true);
$running = 0;
while ($queue || $running) {
if ($queue && microtime(true) >= $next) {
$key = array_shift($queue);
$ch = curl_init(SORSA_API . $path);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'ApiKey: ' . (getenv('SORSA_API_KEY') ?: 'YOUR_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($bodies[$key]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_PRIVATE => (string) $key,
]);
curl_multi_add_handle($multi, $ch);
$next = max($next, microtime(true) - 1 / $rate) + 1 / $rate;
}
curl_multi_exec($multi, $running);
while ($done = curl_multi_info_read($multi)) {
$ch = $done['handle'];
$key = curl_getinfo($ch, CURLINFO_PRIVATE);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$tries[$key] = ($tries[$key] ?? 0) + 1;
if (in_array($status, [0, ...RETRY], true) && $tries[$key] < 5) {
$queue[] = $key; // back in line, it waits its turn
} else {
$results[$key] = json_decode(curl_multi_getcontent($ch), true);
}
curl_multi_remove_handle($multi, $ch);
}
curl_multi_select($multi, 0.01);
}
return $results;
}
$bodies = array_map(fn ($batch) => ['tweet_links' => $batch],
array_chunk($tweetIds, 100));
$tweets = array_merge(...array_column(parallel('/tweet-info-bulk', $bodies),
'tweets'));
Com 19 inícios por segundo, 100 lotes movem 10 mil tweets em cerca de 5 segundos, 1.900 tweets por segundo. Mantenha um único loop parallel() por chave: dois processos rodando lado a lado iniciam o dobro do limite entre eles. O Pool do Guzzle parece a ferramenta certa para isto, mas a opção concurrency dele limita as requisições em andamento, não os inícios por segundo, então um pool de respostas rápidas ainda pode ultrapassar 20 por segundo e depender de retentativas.
#Laravel: as mesmas chamadas com o cliente Http
O cliente Http do Laravel envolve o Guzzle, então um app Laravel não precisa de nenhum pacote extra. Uma macro define a URL base, a chave e uma regra de retentativa que repete apenas 429, respostas 5xx e conexões interrompidas; todo controller, job ou comando Artisan chama então Http::sorsa().
// config/services.php: 'sorsa' => ['key' => env('SORSA_API_KEY')],
// .env: SORSA_API_KEY=YOUR_API_KEY
// app/Providers/AppServiceProvider.php
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;
// inside the class
public function boot(): void
{
Http::macro('sorsa', fn () => Http::baseUrl('https://api.sorsa.io/v3')
->withHeaders(['ApiKey' => config('services.sorsa.key')])
->timeout(30)
->retry(5, fn (int $attempt) => 1000 * 2 ** ($attempt - 1),
fn (Throwable $e) => $e instanceof ConnectionException
|| ($e instanceof RequestException
&& ($e->response->status() === 429
|| $e->response->serverError()))));
}
O retry() espera 1, 2, 4 e 8 segundos entre as tentativas e lança uma RequestException quando as tentativas acabam ou o status não vale uma nova tentativa, como um 401 ou um 403, então uma chamada que falhou nunca vai parar no cache. Rode jobs longos, como milhares de requisições em lote, a partir de um job em fila ou de um comando Artisan, e não dentro de uma requisição de página.
Um feed em cache gasta requisições pelo relógio, não por visitante. O planejador transforma o número de feeds e o tempo de cache em requisições por dia e por mês, e no plano da Sorsa API que as comporta.
- Requisições por dia
- 288
- Requisições por mês
- 8,640
- Plano da Sorsa API que comporta
- Starter
- As 100 requisições grátis duram
- cerca de 8 h
seja qual for o tráfego
30 dias
10K requisições por mês, 86% usadas
sem cartão, nunca expiram
Todo visitante no mesmo período de 5 minutos lê a cópia em cache, então 100 visualizações de página e 1M de visualizações custam as mesmas 288 requisições por dia.
As requisições dependem de com que frequência o cache é atualizado, nunca das visualizações de página.
#Quanto custa um job em PHP
A Sorsa API cobra por requisição, seja qual for o retorno do endpoint: timelines e busca custam a partir de US$ 0,07 por 1.000 tweets, lotes a partir de US$ 0,014, e requisições com falha nunca são cobradas. A API oficial do X cobra por objeto: US$ 5,00 por 1.000 posts e, a partir de 22 de novembro de 2026, até US$ 15,00 por 1.000 quando o código expande o autor de cada post, como faz a maioria das buscas do TwitterOAuth.
API oficial do X
US$ 5.000
para 1 milhão tweets
US$ 0,005 por post
Sorsa API
a partir deUS$ 70
para 1 milhão tweets
a partir de US$ 0,07 por 1.000
O perfil do autor vem dentro de cada tweet
A tarifa por 1.000 requisições vai de US$ 4,90 no Starter a US$ 1,40 no Hyperscale, e cada plano a aplica igualmente a todos os endpoints. Consultar o que resta não custa nada: GET /key-usage-info (abre em uma nova aba) nunca desconta das suas requisições.
$usage = sorsa('GET', '/key-usage-info');
echo $usage['remaining_requests'], ' left until ', $usage['valid_until'], "\n";
#Como migrar o código do TwitterOAuth para a Sorsa API
A maioria das leituras do TwitterOAuth corresponde a um endpoint da Sorsa API, e o código abandona as expansões e as listas de campos, porque cada tweet já traz o autor e as contagens. A tabela une caminhos comuns da v2 aos seus endpoints; para migrar uma base de código inteira, o guia para migrar da API do Twitter (X) mapeia todos os endpoints da v2 e campos de resposta.
| Chamada do TwitterOAuth | Endpoint da Sorsa API | O que muda |
|---|---|---|
get('tweets/search/recent') | POST /search-tweets | Um só endpoint para busca recente e de arquivo, desde 2006 |
get("users/$id/tweets") | POST /user-tweets | Basta o nome de usuário, e não há limite de 3.200 posts |
get('tweets') com ids | POST /tweet-info-bulk | 100 IDs ou links por requisição |
get('users/by') com usernames | GET /info-batch | 100 nomes de usuário por requisição |
get("users/$id/followers") | GET /followers | 200 seguidores por página |
post('tweets') | nenhum | Somente leitura: poste pela API oficial do X |
get('tweets/search/recent')- Endpoint da Sorsa API
POST /search-tweets- O que muda
- Um só endpoint para busca recente e de arquivo, desde 2006
get("users/$id/tweets")- Endpoint da Sorsa API
POST /user-tweets- O que muda
- Basta o nome de usuário, e não há limite de 3.200 posts
get('tweets')comids- Endpoint da Sorsa API
POST /tweet-info-bulk- O que muda
- 100 IDs ou links por requisição
get('users/by')comusernames- Endpoint da Sorsa API
GET /info-batch- O que muda
- 100 nomes de usuário por requisição
get("users/$id/followers")- Endpoint da Sorsa API
GET /followers- O que muda
- 200 seguidores por página
post('tweets')- Endpoint da Sorsa API
- nenhum
- O que muda
- Somente leitura: poste pela API oficial do X
Os nomes dos campos mudam também: text vira full_text, public_metrics->like_count vira likes_count, author_id com includes->users vira o array user, e meta->next_token vira next_cursor. O TwitterOAuth devolve objetos, enquanto json_decode($body, true) dá os arrays que este guia usa. A timeline de usuário também passa dos 3.200 posts mais recentes, onde a timeline oficial para (abre em uma nova aba).
#Faça hoje a sua primeira requisição em PHP
Ler dados do X em PHP exige a extensão cURL, uma chave e quatro funções curtas: sorsa() para as retentativas, pages() para os cursores, array_chunk() com os endpoints de lote para 100 itens por requisição e parallel() para 19 requisições por segundo. Comece pela Sorsa API, a API do Twitter feita para ler dados públicos do X em escala: 20 tweets por requisição de timeline ou busca a partir de US$ 0,07 por 1.000, 100 por lote a partir de US$ 0,014 e 100 requisições grátis que não pedem cartão e nunca expiram. As mesmas chamadas em outras linguagens estão nos guias da API do Twitter em Python e da API do Twitter em Node.js.
#Perguntas frequentes
Qual API do Twitter devo usar com PHP?
Para ler dados do X em PHP, use a Sorsa API: uma chave em um header ApiKey no lugar do OAuth, JSON simples para o json_decode, timelines e busca a partir de US$ 0,07 por 1.000 tweets e lotes a partir de US$ 0,014, 20 requisições por segundo em todos os planos, busca desde 2006 e nenhum login do X, então a sua conta nunca corre risco. Para postar também, combine-a com a API oficial do X.
Existe uma API do Twitter grátis para PHP?
A API oficial do X não tem plano gratuito para novos desenvolvedores: o TwitterOAuth é grátis, mas cada leitura gasta créditos pré-pagos a US$ 0,005 por post. A Sorsa API dá a toda conta 100 requisições grátis que nunca expiram e não pedem cartão. No PHP, elas buscam 2.000 tweets por timelines ou busca, ou até 10 mil tweets em lotes de 100. O panorama completo está em a API do Twitter é grátis?.
O Twitter (X) usa PHP?
Não. O Twitter nasceu em Ruby on Rails e, a partir de 2010, passou o back end para a JVM, com serviços em Scala e Java, como descreve o blog de engenharia do Twitter (abre em uma nova aba). O código de recomendação que o X publicou em 2023 e de novo em janeiro de 2026 é em sua maior parte Scala, Java, Rust e Python, sem nenhum PHP. Mesmo assim, o PHP funciona bem como cliente: os dados do X chegam a um script PHP como JSON por HTTPS.
Posso postar tweets em PHP com a Sorsa API?
Não. A Sorsa API é somente leitura por princípio: ela lê posts, perfis e seguidores públicos e nunca posta, curte, segue nem envia mensagens, então uma chave não pode agir em nenhuma conta do X. Para postar em PHP, use a API oficial do X com tokens de usuário OAuth 1.0a, como o post('tweets', ...) do TwitterOAuth, a US$ 0,015 por post, e deixe a Sorsa API para as leituras.
Posso usar a Sorsa API no WordPress?
Sim. As funções HTTP do próprio WordPress enviam a mesma requisição: wp_remote_post() com o header ApiKey e um corpo JSON, depois wp_remote_retrieve_body() e json_decode(). Guarde o resultado com set_transient() por alguns minutos, para que visualizações de página nunca virem requisições, e armazene a chave no wp-config.php ou em uma variável de ambiente, nunca em um script que o navegador carregue.
Existe um pacote do Composer para a Sorsa API?
Nenhum pacote é necessário: a Sorsa API é REST simples com JSON, então a extensão cURL, o Guzzle ou o cliente Http do Laravel cobrem os 45 endpoints, e as funções deste guia cabem em cerca de 100 linhas. A referência OpenAPI em api.sorsa.io/v3/swagger.json lista todos os endpoints, então um gerador como o openapi-generator pode criar um cliente PHP tipado, se você quiser um.
#Como verificamos
Escrevemos cada requisição deste guia a partir da referência OpenAPI ao vivo da Sorsa API (45 endpoints) e da documentação dela sobre rate limits e paginação, lidas em 2 de novembro de 2026. Não tivemos uma chave da Sorsa API nesta rodada, então a resposta exibida usa valores de demonstração, e rodamos cada bloco PHP no PHP 8.4.27 com Guzzle 8.3.1 e illuminate/http 13 do Laravel contra um mock local que responde nos formatos documentados e devolve 429 acima de 20 requisições por segundo: as primeiras requisições, as retentativas, os dois loops de cursor, os lotes de 100, as query strings, a macro do Laravel e a parallel(), que enviou 100 requisições de lote a 19 por segundo com no máximo um 429 por execução, sempre recuperado pela retentativa. No mesmo dia lemos a tabela de preços do X, a página de ferramentas, a documentação de timelines e o aviso sobre expansões, e as versões do TwitterOAuth, do Guzzle e do Laravel no Packagist.
Fontes
- X API pay-per-usage pricing (docs.x.com) (abre em uma nova aba)
- Tools and libraries: official SDKs and community PHP clients (docs.x.com) (abre em uma nova aba)
- X API PPU: expansions update (X Developers, October 23, 2026) (abre em uma nova aba)
- Getting Access (docs.x.com) (abre em uma nova aba)
- Timelines: up to 3,200 most recent posts (docs.x.com) (abre em uma nova aba)
- TwitterOAuth documentation (abre em uma nova aba)
- abraham/twitteroauth on Packagist (abre em uma nova aba)
- Laravel HTTP client documentation (abre em uma nova aba)
- New Tweets per second record, and how (Twitter Engineering, 2013) (abre em uma nova aba)
- Sorsa API reference, OpenAPI
- Sorsa API rate limits (abre em uma nova aba)
- Sorsa API pagination (abre em uma nova aba)