Connect Retool to Twitter (X) Ads using a REST API Resource targeting the Twitter Ads API v12 (ads-api.twitter.com). Authenticate with OAuth 1.0a — the Twitter Ads API requires all four credentials: consumer key, consumer secret, access token, and access token secret. Query campaigns, line items, and analytics to build ad spend optimization dashboards combining Twitter data with other platform metrics.
| Fact | Value |
|---|---|
| Tool | Twitter (X) Ads |
| Category | Marketing |
| Method | REST API Resource |
| Difficulty | Intermediate |
| Time required | 40 minutes |
| Last updated | April 2026 |
Why connect Retool to Twitter (X) Ads?
Twitter Ads Manager provides campaign reporting, but paid media teams managing multi-platform budgets need Twitter ad performance data alongside Meta, TikTok, and Google in a single custom view. Twitter's native reporting interface does not support combining Twitter data with actual revenue attribution from a database, cannot be customized to internal ROAS definitions, and requires manual exports for cross-platform comparison. Retool enables building unified paid media dashboards that pull Twitter campaign metrics through the Ads API alongside other advertising platforms.
The primary challenge with Twitter Ads integration is authentication. The Twitter Ads API (and Twitter's broader API ecosystem) uses OAuth 1.0a with HMAC-SHA1 request signing — a more complex authentication method than the Bearer tokens or API keys used by most modern APIs. Each request requires a dynamically generated signature computed from the request method, URL, parameters, and all four credential values. This means Retool's standard REST API Resource cannot directly handle Twitter Ads API authentication without a signing mechanism. The solution is a lightweight signing middleware (deployed as a Retool Workflow webhook, a serverless function, or a simple proxy) that handles the OAuth 1.0a signature generation before forwarding requests to Twitter.
Once authenticated, Twitter's Ads API exposes accounts, campaigns, line items (ad groups), and the Analytics API for performance metrics. The Analytics endpoint is the most complex to use: it requires specifying an entity type (CAMPAIGN, LINE_ITEM, PROMOTED_TWEET), entity IDs, a list of metric groups, and a date range. Understanding this structure is key to building efficient performance queries.
Integration method
Twitter Ads connects via Retool's REST API Resource targeting the Twitter Ads API at https://ads-api.twitter.com. Unlike most modern APIs that use OAuth 2.0 or simple API keys, the Twitter Ads API requires OAuth 1.0a with HMAC-SHA1 signatures using all four credentials: consumer key, consumer secret, access token, and access token secret. Since Retool's native REST API Resource does not generate OAuth 1.0a signatures automatically, the integration uses a pre-signed request approach or a custom middleware. All queries proxy server-side through Retool, keeping credentials off the browser.
Prerequisites
- A Twitter (X) Developer account with an approved app at developer.twitter.com
- A Twitter Ads account linked to your developer app (apply for Ads API access at developer.twitter.com/en/products/twitter-api/enterprise)
- All four OAuth 1.0a credentials: consumer key (API key), consumer secret (API secret), access token, and access token secret from the developer portal
- The Twitter Ads account ID (visible in Twitter Ads Manager URL as /accounts/ACCOUNT_ID)
- A Retool account with Resource creation permissions and ideally Workflow access for the OAuth middleware
Step-by-step guide
Obtain Twitter Ads API credentials
Twitter Ads API access requires two separate approvals: a Twitter Developer account with an approved app, and specific Ads API product access. In the Twitter Developer Portal (developer.twitter.com), sign in and navigate to your project and app settings. If you do not have a developer app, create one by clicking Create Project and then Create App. In the app settings, navigate to the Keys and Tokens tab. Under Consumer Keys, you will find the API Key (consumer key) and API Secret Key (consumer secret). Under Authentication Tokens, generate an Access Token and Secret — click Generate under Access Token and Secret, and copy both values immediately. These four credentials (consumer key, consumer secret, access token, access token secret) are all required for OAuth 1.0a request signing. Next, apply for Ads API access: in the developer portal, navigate to Products → Twitter Ads API and submit an application. Twitter reviews Ads API applications and approves them manually — approval typically takes 1-5 business days. Once approved, your app can access the Ads API endpoints. Note your Twitter Ads account ID: in Twitter Ads Manager, the account ID appears in the URL as a hexadecimal string (https://ads.twitter.com/accounts/XXXXXXXXXX). This account ID is required as a path parameter in most Ads API endpoints (e.g., /11/accounts/{account_id}/campaigns).
Pro tip: Twitter requires the access token to be generated by the same account that manages the Ads account. If you are building this for a company's Twitter Ads account, ensure the access token is generated by a Twitter account with Admin access to the Ads account, not just your personal developer account.
Expected result: You have all four OAuth 1.0a credentials (consumer key, consumer secret, access token, access token secret) and your Twitter Ads account ID. Ads API access has been approved for your developer app.
Set up OAuth 1.0a signing with a Retool Workflow
Retool's native REST API Resource does not generate OAuth 1.0a HMAC-SHA1 signatures automatically. OAuth 1.0a requires computing a signature for each individual request using the request method, URL, all parameters, and all four credentials — this must happen at request time, not at Resource configuration time. The recommended approach is to use a Retool Workflow as a lightweight proxy that generates the OAuth signature and forwards the request to Twitter. Navigate to Retool Workflows and create a new Workflow named Twitter Ads Proxy. Add a Webhook trigger — copy the generated webhook URL and API key. In the Workflow, add a JavaScript Code block. In the code block, write the OAuth 1.0a signature generation logic: build the signature base string from the HTTP method, encoded URL, and sorted encoded parameters (including oauth_consumer_key, oauth_nonce, oauth_signature_method, oauth_timestamp, oauth_token, oauth_version), compute the HMAC-SHA1 signature using the consumer secret and access token secret as the signing key, and build the Authorization header with all OAuth parameters. Then use Retool's built-in HTTP fetch in the JavaScript block to call Twitter's Ads API with the generated Authorization header and return the response to the Workflow caller. In your Retool app, instead of calling the Twitter API directly, create a REST API Resource pointing to the Retool Workflow webhook URL, passing the target Twitter endpoint and parameters as the request body. The Workflow handles signing and proxying. Store all four Twitter credentials as Retool configuration variables marked as secret.
1// JavaScript Code block in Retool Workflow2// Generates OAuth 1.0a signature and proxies request to Twitter Ads API3// Input from webhook: { method, path, params }45const crypto = require('crypto');67// Credentials from Retool config vars (access via retoolContext in Workflow)8const CONSUMER_KEY = retoolContext.configVars.TWITTER_CONSUMER_KEY;9const CONSUMER_SECRET = retoolContext.configVars.TWITTER_CONSUMER_SECRET;10const ACCESS_TOKEN = retoolContext.configVars.TWITTER_ACCESS_TOKEN;11const ACCESS_SECRET = retoolContext.configVars.TWITTER_ACCESS_SECRET;1213const method = trigger.data.method || 'GET';14const twitterPath = trigger.data.path;15const queryParams = trigger.data.params || {};1617const BASE_URL = `https://ads-api.twitter.com/12${twitterPath}`;1819// Generate OAuth 1.0a signature20const timestamp = Math.floor(Date.now() / 1000).toString();21const nonce = crypto.randomBytes(16).toString('hex');2223const oauthParams = {24 oauth_consumer_key: CONSUMER_KEY,25 oauth_nonce: nonce,26 oauth_signature_method: 'HMAC-SHA1',27 oauth_timestamp: timestamp,28 oauth_token: ACCESS_TOKEN,29 oauth_version: '1.0'30};3132// Combine all params for signature base string33const allParams = { ...queryParams, ...oauthParams };34const sortedParams = Object.keys(allParams).sort().map(k =>35 `${encodeURIComponent(k)}=${encodeURIComponent(allParams[k])}`36).join('&');3738const signatureBase = [39 method.toUpperCase(),40 encodeURIComponent(BASE_URL),41 encodeURIComponent(sortedParams)42].join('&');4344const signingKey = `${encodeURIComponent(CONSUMER_SECRET)}&${encodeURIComponent(ACCESS_SECRET)}`;45const signature = crypto.createHmac('sha1', signingKey).update(signatureBase).digest('base64');4647// Build Authorization header48oauthParams.oauth_signature = signature;49const authHeader = 'OAuth ' + Object.keys(oauthParams)50 .map(k => `${encodeURIComponent(k)}="${encodeURIComponent(oauthParams[k])}"`)51 .join(', ');5253// Build query string54const queryString = Object.keys(queryParams).length55 ? '?' + Object.keys(queryParams).map(k =>56 `${encodeURIComponent(k)}=${encodeURIComponent(queryParams[k])}`57 ).join('&')58 : '';5960// Proxy request to Twitter61const response = await fetch(`${BASE_URL}${queryString}`, {62 method: method,63 headers: {64 'Authorization': authHeader,65 'Content-Type': 'application/json'66 }67});6869const responseData = await response.json();70return responseData;Pro tip: OAuth 1.0a signature generation is sensitive to parameter ordering and encoding. The nonce must be unique per request (a random value), and the timestamp must be current Unix time in seconds. If the timestamp is more than 5 minutes off from Twitter's server time, the request will be rejected with a 401 error.
Expected result: The Retool Workflow is configured with the OAuth 1.0a signing JavaScript code. A test call to the Workflow with a simple Twitter Ads API path returns data, confirming the signing mechanism is working.
Configure the Retool Resource and query campaigns
With the OAuth proxy Workflow in place, configure a Retool REST API Resource to call the Workflow. Navigate to Resources → Add Resource → REST API. Name it Twitter Ads (via proxy). Set the Base URL to your Retool Workflow webhook URL (e.g., https://retool.com/api/workflow/WORKFLOW_ID/startTrigger). In the Headers, add the Workflow API key authentication: header name X-Workflow-Api-Key with value {{ config.RETOOL_WORKFLOW_KEY }}. Create a RETOOL_WORKFLOW_KEY configuration variable with the Workflow's API key. Store all four Twitter credentials as configuration variables: TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_SECRET — all marked as secret. Now create queries in the Retool app. Create a query targeting the Twitter Ads proxy Resource with Method POST (sending instructions to the Workflow). Set Path to / (the Workflow webhook base). Set Body type to JSON with the following structure: { "method": "GET", "path": "/accounts/{{ retoolContext.configVars.TWITTER_ADS_ACCOUNT_ID }}/campaigns", "params": { "count": "200" } }. The Workflow receives this, signs the request, calls Twitter, and returns the response. Create a second similar query for analytics. The Twitter Ads API returns campaigns as a data array with id, name, status, budget_optimization, created_at, and associated daily_budget_amount_local_micro (budget in micro-dollars — divide by 1,000,000 for display).
1// Query body for fetching campaigns via OAuth proxy Workflow2// Method: POST, targeting the Retool Workflow webhook3{4 "method": "GET",5 "path": "/accounts/{{ retoolContext.configVars.TWITTER_ADS_ACCOUNT_ID }}/campaigns",6 "params": {7 "count": "200",8 "with_deleted": "false"9 }10}1112// Query body for fetching line items (ad groups) for a campaign13{14 "method": "GET",15 "path": "/accounts/{{ retoolContext.configVars.TWITTER_ADS_ACCOUNT_ID }}/line_items",16 "params": {17 "campaign_ids": "{{ campaignsTable.selectedRow.id || '' }}",18 "count": "200"19 }20}Pro tip: Twitter Ads API returns budget amounts as micro-dollars (1/1,000,000 of a dollar). Always divide micro-dollar values by 1,000,000 before displaying them. For example, a daily_budget_amount_local_micro of 50000000 represents a $50 daily budget.
Expected result: The campaigns query returns Twitter Ads campaign data via the OAuth proxy Workflow. Campaign names, statuses, and budgets are visible in the Retool query inspector, confirming the end-to-end authentication and proxy flow is working.
Query Twitter Ads analytics for performance metrics
Twitter Ads analytics requires a separate endpoint with different parameters than campaign listing queries. Create a query through the proxy Workflow with Body: { "method": "GET", "path": "/stats/accounts/{{ retoolContext.configVars.TWITTER_ADS_ACCOUNT_ID }}", "params": { "entity": "CAMPAIGN", "entity_ids": "{{ campaignIds.join(',') }}", "metric_groups": "ENGAGEMENT,BILLING", "granularity": "DAY", "start_time": "{{ formatDate(dateRangePicker.value[0], 'YYYY-MM-DD') }}", "end_time": "{{ formatDate(dateRangePicker.value[1], 'YYYY-MM-DD') }}", "placement": "ALL_ON_TWITTER" } }. The entity_ids parameter accepts a comma-separated list of campaign IDs — build this from the campaigns query response. The metric_groups parameter selects which metric categories to return: ENGAGEMENT (impressions, clicks, engagements, follows), BILLING (billed_charge_local_micro for spend), VIDEO (video views, completions). The granularity parameter controls aggregation: DAY for daily breakdown, TOTAL for period totals. The response is a data array where each element contains id_data with nested metrics per day. Add a JavaScript transformer to flatten this nested structure into a flat array of campaign-day records suitable for Table and Chart display. This transformer must handle Twitter's nested response where metrics are arrays of values corresponding to the time series.
1// JavaScript transformer for Twitter Ads Analytics API response2// Twitter returns metrics as arrays aligned to the time series3const analyticsData = data.data || [];45const results = [];67analyticsData.forEach(campaignMetrics => {8 const campaignId = campaignMetrics.id;9 const idData = campaignMetrics.id_data || [];1011 idData.forEach(dayData => {12 const metrics = dayData.metrics || {};13 const billedCharges = metrics.billed_charge_local_micro || [];14 const impressions = metrics.impressions || [];15 const clicks = metrics.clicks || [];16 const engagements = metrics.engagements || [];1718 // Each metrics field is an array; values at same index correspond to same day19 const days = billedCharges.length;20 for (let i = 0; i < days; i++) {21 const spend = (billedCharges[i] || 0) / 1000000; // Convert micro-dollars22 const imp = impressions[i] || 0;23 const clk = clicks[i] || 0;24 const eng = engagements[i] || 0;2526 results.push({27 campaign_id: campaignId,28 day_index: i,29 spend: spend.toFixed(2),30 spend_display: `$${spend.toFixed(2)}`,31 impressions: imp,32 clicks: clk,33 engagements: eng,34 ctr: imp > 0 ? ((clk / imp) * 100).toFixed(2) + '%' : '0%',35 cpm: imp > 0 ? `$${(spend / imp * 1000).toFixed(2)}` : '$0',36 engagement_rate: imp > 0 ? ((eng / imp) * 100).toFixed(2) + '%' : '0%'37 });38 }39 });40});4142return results;Pro tip: Twitter Ads Analytics API returns metrics as arrays of values aligned to a time series. The first element in each metrics array corresponds to the first day of the requested date range, the second element to the second day, and so on. You must use index-based alignment (not date-based) when processing these arrays in your transformer.
Expected result: The analytics transformer returns a flat array of campaign-day records with spend in dollars, impressions, clicks, and engagement rate. The data is ready to bind to a Table and Line Chart for the performance dashboard.
Build the Twitter Ads performance dashboard
Assemble the performance dashboard in Retool. Add a DateRangePicker component at the top defaulting to the last 7 days. Add a Stat row showing period totals — compute these in a JavaScript query that sums the analytics array: total spend, total impressions, total engagements, and blended engagement rate. Drag a Table and bind it to the campaigns list from the campaigns query, joining campaign names with analytics totals using campaign_id as the join key. Configure Table columns: Campaign Name, Status, Daily Budget, Period Spend, Impressions, Engagements, Engagement Rate. Add conditional formatting: highlight campaigns where spend is 0 (paused or not spending). Add a Line Chart below the Table bound to the analytics data with date on X axis and spend on Y axis — this shows the daily spend trend across all campaigns. For creative-level analysis, add a second query at entity type PROMOTED_TWEET to get individual tweet performance. Join tweet IDs with tweet text by querying the Twitter v2 API (separate Resource with Bearer token auth, which is simpler) for tweet objects. Display tweet text, impressions, engagements, and engagement rate in a secondary Table. For complex multi-platform advertising operations platforms integrating Twitter, Meta, Google, TikTok, and custom attribution in Retool, RapidDev's team can architect comprehensive paid media operations solutions.
1// JavaScript query: join campaign metadata with analytics totals2const campaigns = getCampaigns.data?.data || [];3const analytics = getAnalytics.data || [];45// Aggregate analytics by campaign_id6const byCampaign = {};7analytics.forEach(row => {8 const id = row.campaign_id;9 if (!bycampaign[id]) {10 byCampaign[id] = { spend: 0, impressions: 0, clicks: 0, engagements: 0 };11 }12 byampaign[id].spend += parseFloat(row.spend || 0);13 byC[id].impressions += parseInt(row.impressions || 0);14 byC[id].clicks += parseInt(row.clicks || 0);15 byCampaign[id].engagements += parseInt(row.engagements || 0);16});1718return campaigns.map(c => {19 const stats = byCampaign[c.id] || {};20 const budget = c.daily_budget_amount_local_micro21 ? `$${(c.daily_budget_amount_local_micro / 1000000).toFixed(2)}`22 : 'Campaign Budget';23 return {24 id: c.id,25 name: c.name,26 status: c.status || c.entity_status || '',27 daily_budget: budget,28 spend: (stats.spend || 0).toFixed(2),29 spend_display: `$${(stats.spend || 0).toFixed(2)}`,30 impressions: stats.impressions || 0,31 engagements: stats.engagements || 0,32 engagement_rate: stats.impressions > 033 ? ((stats.engagements / stats.impressions) * 100).toFixed(2) + '%'34 : '0%'35 };36});Pro tip: Twitter Ads API rate limits are per-endpoint and per-app. The Analytics endpoint is rate-limited to 60 requests per 15-minute window per app. Cache analytics queries for at least 15 minutes to avoid hitting this limit when multiple team members use the dashboard simultaneously.
Expected result: A complete Twitter Ads performance dashboard shows period total Stats, a campaigns Table with spend and engagement metrics, and a daily spend trend Line Chart. All data updates when the date range picker changes.
Common use cases
Twitter Ads campaign performance dashboard
Build a Retool dashboard showing all active Twitter Ads campaigns with spend, impressions, clicks, engagements, and engagement rate for a selected date range. A Table displays campaigns sorted by spend with filtering by campaign type (promoted tweets, follower campaigns, app installs). A Bar Chart shows daily spend trend. Summary Stats show period totals for spend, total impressions, and total engagements across all campaigns.
Build a Retool Twitter Ads performance dashboard that queries campaigns and analytics via the Twitter Ads API. Show a Table with campaign name, objective, status, spend (in micro-dollars converted to dollars), impressions, clicks, engagements, and engagement rate. Add a date range picker for the analytics window. Include a Bar Chart of daily spend and Stat components showing period totals.
Copy this prompt to try it in Retool
Cross-platform ad spend comparison dashboard
Combine Twitter Ads spend and engagement data with Facebook Ads and TikTok Ads metrics in a single Retool dashboard. Three parallel queries fetch data from each platform, and a JavaScript transformer joins results by date to produce a unified daily view. A stacked Bar Chart shows spend by platform per day. A Table compares CPM, CPC, and engagement rate across platforms to inform budget reallocation decisions.
Build a Retool cross-platform ad comparison dashboard combining Twitter, Facebook, and TikTok Ads data. Show a stacked Bar Chart of daily spend by platform. Display a Table with columns for each platform's CPM, CPC, and engagement rate for the selected date range. Calculate total ROAS by joining ad spend data with revenue from a PostgreSQL database query.
Copy this prompt to try it in Retool
Promoted tweet creative performance tracker
Create a Retool panel showing individual promoted tweet performance metrics including engagement rate, video completion rate (for video ads), link clicks, and retweet counts. Query the Twitter Ads Analytics API at the PROMOTED_TWEET entity level to get per-creative metrics. Display a Table of promoted tweets ranked by engagement rate with tweet text previews. Identify top-performing creative for reuse and underperforming creative for optimization.
Build a Retool promoted tweet creative tracker that queries Twitter Ads Analytics at the PROMOTED_TWEET level for a selected campaign. Show a Table with tweet ID, tweet text preview, spend, impressions, engagement rate, link clicks, and video views (if applicable). Rank by engagement rate. Add a campaign selector to switch between campaigns.
Copy this prompt to try it in Retool
Troubleshooting
OAuth 1.0a requests return 401 Unauthorized with 'Could not authenticate you' message
Cause: The OAuth 1.0a signature is being computed incorrectly — most commonly due to incorrect parameter encoding, wrong parameter sorting, timestamp being out of sync, or using the wrong signing key format.
Solution: Verify the signing key format is consumer_secret&access_token_secret (both URL-encoded and joined with an ampersand). Ensure all OAuth parameters and request parameters are sorted alphabetically before building the signature base string. Check that the timestamp is current Unix time in seconds (not milliseconds). Validate your server clock is synchronized — Twitter rejects requests with timestamps more than 5 minutes off. Use Twitter's OAuth signature validator tool for debugging.
Analytics query returns empty data array for campaigns that have active spend
Cause: The entity_ids parameter contains campaign IDs in an incorrect format, the date range is outside the available data retention window, or the metric_groups parameter includes unsupported combinations.
Solution: Verify entity_ids is a comma-separated string of campaign IDs with no extra spaces. Check that start_time and end_time are in YYYY-MM-DD format. Twitter Ads Analytics data is available for campaigns that were active in the specified date range — if a campaign was created after the end_time or ended before the start_time, it returns no data. Start with a single known campaign ID and a recent date range (last 7 days) to isolate the issue.
Campaign query returns campaigns but budget is null or zero
Cause: Twitter stores campaign budgets at the funding instrument level, not always at the campaign level. Some campaigns use total budgets rather than daily budgets, and the daily_budget_amount_local_micro field may be null.
Solution: Check for both daily_budget_amount_local_micro and total_budget_amount_local_micro in the campaign object. Some campaigns use total budgets rather than daily budgets. For line item-level budgets, query /accounts/{id}/line_items with the campaign_id filter — line items can have their own bid and budget settings independent of the campaign.
Retool Workflow OAuth proxy returns 'Timestamp out of bounds' error
Cause: The Workflow JavaScript code is generating timestamps in milliseconds instead of seconds, or there is a clock skew between the Workflow execution environment and Twitter's servers.
Solution: Ensure the timestamp is generated with Math.floor(Date.now() / 1000) — dividing by 1000 converts milliseconds to seconds. Do not use Date.now() directly (milliseconds). Twitter requires the timestamp to be within 5 minutes of their server time. If clock skew is suspected, add a small buffer: generate the timestamp slightly before the request to ensure it is within the acceptable window.
1// Correct timestamp generation for OAuth 1.0a2const timestamp = Math.floor(Date.now() / 1000).toString(); // SECONDS, not milliseconds3// NOT: const timestamp = Date.now().toString(); // This is milliseconds and will failBest practices
- Store all four OAuth 1.0a credentials in Retool configuration variables marked as secret — the consumer secret and access token secret are the most sensitive values, as they are used to sign requests and must never be exposed.
- Use a Retool Workflow as the OAuth 1.0a signing proxy rather than attempting to hardcode signatures — signatures must be generated dynamically per request, making a signing service the only viable approach with Retool's REST API Resource.
- Generate a unique nonce for each request in the OAuth signing code — reusing nonces causes Twitter to reject requests with a 401 error, even if all other OAuth parameters are correct.
- Cache analytics queries for 15+ minutes — Twitter Ads Analytics data does not update in real time and the Analytics endpoint has strict rate limits (60 requests per 15 minutes per app).
- Convert micro-dollar values to dollars in transformers before display — all monetary values in the Twitter Ads API are in micro-dollars (1/1,000,000 of a dollar). Always divide by 1,000,000 before showing dollar amounts to users.
- Process Twitter Analytics metrics arrays using index alignment rather than date comparison — Twitter returns metric values as arrays where array position corresponds to the day in the date range, not as objects with explicit date keys.
- Limit analytics requests to at most 20 campaign IDs per query — the entity_ids parameter supports multiple IDs but very large batches can cause timeout errors; paginate campaign IDs in groups of 20 for large accounts.
Alternatives
Facebook Ads uses a simpler System User token that never expires rather than OAuth 1.0a with four credentials, making it easier to set up in Retool and better suited for B2C advertising with Meta's broader audience network.
LinkedIn Ads uses modern OAuth 2.0 rather than OAuth 1.0a, making it simpler to authenticate in Retool, and is the preferred platform for B2B campaigns targeting by job title, seniority, and company.
Reddit Ads uses OAuth 2.0 with client credentials for simpler server-to-server authentication than Twitter's OAuth 1.0a, and is better for reaching niche communities with specific interests.
Frequently asked questions
Why does Twitter Ads still use OAuth 1.0a when most APIs have moved to OAuth 2.0?
Twitter's OAuth 1.0a requirement is a legacy of Twitter's early API architecture. While Twitter's v2 API supports OAuth 2.0 Bearer tokens for read operations, the Ads API requires OAuth 1.0a with request signing for write operations and some analytics endpoints. This is a deliberate security choice for advertising data — the HMAC-SHA1 signature ensures request integrity and prevents token replay attacks. Twitter has not announced a timeline for migrating Ads API authentication to OAuth 2.0.
Can I use Twitter's v2 API Bearer token for some requests and OAuth 1.0a for others?
Yes. Twitter's v2 API (api.twitter.com/2) supports OAuth 2.0 Bearer tokens for read-only endpoints like fetching tweet text, user profiles, and public metrics. Create a separate Retool Resource for the Twitter v2 API with a Bearer token header — this is much simpler to configure. Use the OAuth 1.0a proxy Resource only for Ads API endpoints (ads-api.twitter.com) that require full authentication. This hybrid approach lets you fetch tweet content (v2 API) while querying ad performance (Ads API) in the same Retool dashboard.
What is the Twitter Ads API rate limit, and how does it affect my Retool dashboard?
Twitter Ads API rate limits vary by endpoint. The Analytics endpoint is typically limited to 60 requests per 15-minute window per app credential set. Campaign listing endpoints have higher limits (200-300 requests per 15 minutes). For shared Retool dashboards with multiple users, these limits apply per app, not per user — aggressive caching (15+ minutes) is essential to stay within limits when multiple users trigger queries simultaneously.
How do I handle the micro-dollar currency units in Twitter Ads API responses?
Twitter Ads stores all monetary values in micro-dollars — 1/1,000,000 of a dollar. A value of 5000000 represents $5.00. In your JavaScript transformer, divide all monetary fields by 1,000,000 before displaying: const dollars = microDollars / 1000000. The fields affected include daily_budget_amount_local_micro, total_budget_amount_local_micro, and billed_charge_local_micro from the analytics endpoint.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation