Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
IT NachrichtenWie ein Drogenrausch: Control Resonant im Test(29.09.2026 um 10:20 Uhr)
•
IT NachrichtenDigitalkompetenz ist in vielen Berufen gefragt(29.09.2026 um 09:58 Uhr)
••••
IT NachrichtenDieses Elektroauto von VW kostet nur rund 11.000 Euro(29.09.2026 um 10:27 Uhr)
••
IT NachrichtenDie Amazon Prime Deal Days kommen im Oktober(29.09.2026 um 10:31 Uhr)
•••
IT NachrichtenWie ein Drogenrausch: Control Resonant im Test(29.09.2026 um 10:20 Uhr)
•
IT NachrichtenDigitalkompetenz ist in vielen Berufen gefragt(29.09.2026 um 09:58 Uhr)
••••
IT NachrichtenDieses Elektroauto von VW kostet nur rund 11.000 Euro(29.09.2026 um 10:27 Uhr)
••
IT NachrichtenDie Amazon Prime Deal Days kommen im Oktober(29.09.2026 um 10:31 Uhr)
•••
Intelligence View
⚡ tsecurity.de Intelligence

Fetching X Timelines with API v2 Pay-Per-Use: Cost Breakdown, Caching, and the Gotchas

X's Pay-Per-Use pricing changed how I think about API integrations. Before it existed, "display a Twitter/X timeline on a website" meant either a bloated embed widget or a $200/month API plan — neither made sense for small p…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

X's Pay-Per-Use pricing changed how I think about API integrations. Before it existed, "display a Twitter/X timeline on a website" meant either a bloated embed widget or a $200/month API plan — neither made sense for small projects.



Pay-Per-Use flips that. You pay per request. For fetching 10 posts three times a day, the real-world cost lands around $2–3/month. That's a different conversation.



This article covers how I implemented X API v2 timeline fetching in PHP/WordPress — including the cost math, the API structure, retweet handling, caching strategy, and two WP-Cron gotchas that will bite you if you're not ready.









Cost Breakdown First



Before writing a line of code, it's worth understanding what you're paying for.



Timeline fetching is a two-step process:




























Action Cost
User lookup (Step 1) $0.010 / cycle
Per post fetched (Step 2) $0.005 / post
5 posts per cycle $0.035
10 posts per cycle $0.060


X API Pay-Per-Use credit consumption details — developer.x.com



At 10 posts × 3 updates/day, the ceiling is $0.060 × 90 = $5.40/month. In practice it's lower.



The no-duplicate-billing rule



X API does not charge twice for the same post within a 24-hour UTC window. On the second and third daily updates, you only pay for newly published posts. For accounts that don't post constantly, the second and third updates often cost almost nothing. Real-world cost for most use cases: $2–3/month.



One important caveat: X has stated that Pay-Per-Use is a pilot program with provisional pricing that may change. Always verify current rates at developer.x.com before building anything that depends on these numbers.









Authentication



Bearer Token only. App-only OAuth 2.0. No user context needed for public timelines.




$response = wp_remote_get( $url, [
'headers' => [
'Authorization' => 'Bearer ' . $bearer_token,
],
'timeout' => 15,
] );






If you're in WordPress, use wp_remote_get() instead of curl or file_get_contents. It respects WordPress SSL settings and timeout configuration out of the box.









Step 1: User Lookup






GET https://api.twitter.com/2/users/by/username/{username}






You need the numeric user ID to call the timeline endpoint. This call costs $0.010.




$url      = 'https://api.twitter.com/2/users/by/username/' . rawurlencode( $username );
$response = wp_remote_get( $url, [ 'headers' => $headers ] );
$data = json_decode( wp_remote_retrieve_body( $response ), true );
$user_id = $data['data']['id'];






Note: use rawurlencode() on the username, not urlencode(). The latter encodes spaces as +, which breaks the endpoint.









Step 2: Timeline Fetch






GET https://api.twitter.com/2/users/{id}/tweets






The expansions and field parameters are where most of the complexity lives.




$params = http_build_query( [
'max_results' => 10,
'tweet.fields' => 'created_at,entities,attachments,referenced_tweets',
'expansions' => 'attachments.media_keys,referenced_tweets.id,referenced_tweets.id.author_id',
'media.fields' => 'url,preview_image_url,type,variants,width,height',
'user.fields' => 'name,profile_image_url,username',
'exclude' => 'replies', // optional: hide replies
] );

$url = 'https://api.twitter.com/2/users/' . $user_id . '/tweets?' . $params;






Important: max_results has a minimum of 5. Requesting fewer than 5 returns an API error. Plan your display logic accordingly.



Available expansions for GET /2/users/:id/tweets — X Developer Platform









Retweet Handling (The Tricky Part)



When a retweet appears in the timeline, the API returns a reference to the original post — not the content itself. This trips a lot of people up.



The fix: include referenced_tweets.id in your expansions. The original post data will appear in includes.tweets in the response.



Response structure with includes — X API v2 Fields documentation




$tweets   = $data['data'];             // timeline posts
$includes = $data['includes'] ?? []; // expanded data

foreach ( $tweets as $tweet ) {
$ref_tweets = $tweet['referenced_tweets'] ?? [];

foreach ( $ref_tweets as $ref ) {
if ( $ref['type'] === 'retweeted' ) {
// find the original in includes.tweets
$original = array_filter(
$includes['tweets'] ?? [],
fn( $t ) => $t['id'] === $ref['id']
);
$original = array_values( $original )[0] ?? null;
}

if ( $ref['type'] === 'quoted' ) {
// same lookup, different type
}
}
}






Type values to know:





  • retweeted — standard retweet


  • quoted — quote tweet


  • replied_to — reply (usually excluded via the exclude param)



Media attached to referenced tweets is also in includes.media, keyed by media_key. You'll need to cross-reference tweet.attachments.media_keys against includes.media to render images and video.









Caching Strategy: Stale-While-Revalidate



Never call the API on every page load. It defeats the purpose of caching and burns through your credits.



The pattern I use: WordPress Transients + Stale-While-Revalidate (SWR).




function get_timeline_data() {
$cached = get_transient( 'xtl_timeline_data' );

if ( $cached !== false ) {
$age = time() - $cached['last_updated'];

if ( $age > 12 * HOUR_IN_SECONDS ) {
// Stale but present: serve it, refresh in background
wp_schedule_single_event( time(), 'xtl_swr_update_event' );
}

return $cached;
}

// No cache: schedule a fetch, return nothing for now
wp_schedule_single_event( time(), 'xtl_swr_update_event' );
return false;
}






WordPress Transients API — set_transient() documentation



The tradeoff: first-time visitors see nothing until the background fetch completes (usually a few seconds). Every subsequent visitor gets instant cached content. For most use cases this is acceptable.



Store your fetched data with a TTL long enough that it won't expire between scheduled updates:




set_transient( 'xtl_timeline_data', $data, DAY_IN_SECONDS );












Two WP-Cron Gotchas






1. DST drift with wp_schedule_event('daily')



WordPress's daily interval is a fixed 86400 seconds. During daylight saving time transitions, this causes scheduled events to drift by an hour. If you need updates at specific times, use wp_schedule_single_event() and re-schedule after each run:




// After executing, schedule the next occurrence
$next = strtotime( 'tomorrow ' . $time_str, current_time( 'timestamp' ) );
wp_schedule_single_event(
$next,
'xtl_cron_update_event',
[ [ 'time_str' => $time_str ] ]
);






This keeps the scheduled time accurate regardless of DST changes.






2. wp_clear_scheduled_hook() doesn't remove argument-keyed events



If you're scheduling cron events with arguments (as above), wp_clear_scheduled_hook() will silently fail to remove them. Old events accumulate every time you save settings.



The fix: iterate _get_cron_array() and unschedule explicitly.




function clear_cron_events() {
$crons = _get_cron_array();

foreach ( (array) $crons as $timestamp => $cron ) {
if ( ! isset( $cron['xtl_cron_update_event'] ) ) {
continue;
}
foreach ( $cron['xtl_cron_update_event'] as $data ) {
wp_unschedule_event(
$timestamp,
'xtl_cron_update_event',
$data['args'] ?? []
);
}
}
}






Call this before registering new cron events whenever settings change.



wp_unschedule_event() parameters — WordPress Developer Resources









Rate Limit Handling



When you hit a 429, back off for at least an hour. A simple Transient-based cooldown works well:




if ( 429 === wp_remote_retrieve_response_code( $response ) ) {
set_transient( 'xtl_api_cooldown', true, HOUR_IN_SECONDS );
return new WP_Error( 'rate_limited', 'X API rate limit exceeded.' );
}






Check for the cooldown before every API call:




if ( get_transient( 'xtl_api_cooldown' ) ) {
return; // skip until cooldown clears
}












Key Takeaways



On cost: The no-duplicate-billing rule makes Pay-Per-Use more affordable than the raw numbers suggest. Second and third daily updates often cost almost nothing for low-volume accounts.



On retweets: The most common implementation mistake. Always use expansions=referenced_tweets.id and look up the original in includes.tweets. Don't assume the content is in data.



On caching: SWR is the right pattern for external API data in WordPress. Serve stale content immediately and refresh in the background — don't make visitors wait.



On WP-Cron: Two silent failure modes that are easy to miss: DST drift with daily interval, and argument-keyed events not being removed by wp_clear_scheduled_hook().






I packaged this implementation into two WordPress plugins if you'd rather skip the plumbing:





  • X Timeline — displays a configurable timeline feed with retweet support, filters, and auto-update scheduling


  • X Pinned Post — fetches only the pinned post from an account, at a lower API cost per cycle






ikka.inc — design and web production studio based in Japan.

2. Cyber Threat Intelligence & Forensik

CTI Threat Relationship Graph3 Knoten / 2 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Fetching X Timelines with API v2 Pay-Per-Use: Cost Breakdown, Caching, and the Gotchas

Thematisch verwandte Begriffe: Fetching, Timelines, with, PayPerUse · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

💬 Kommentare werden geladen…
Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-102240 | A vulnerability was found in Netcore NAP930 0.1.241010.141410. This aff…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag