To integrate Replit with Tableau, store your Tableau Server URL, site ID, and Personal Access Token credentials in Replit Secrets (lock icon π), then call the Tableau REST API from your Node.js or Python backend to authenticate, query workbooks, embed views, and publish data sources. Use a Reserved VM deployment if you need persistent Tableau session management, or Autoscale for stateless data queries.
Automate Tableau Workflows from Replit
Tableau is one of the most widely used business intelligence tools in enterprise organizations, but its web interface was designed for analysts β not for automating workflows or embedding analytics into custom applications. The Tableau REST API fills that gap, providing programmatic access to workbooks, views, data sources, users, and permissions on Tableau Server or Tableau Cloud.
From a Replit backend, you can automate a wide range of Tableau operations without anyone opening the Tableau interface. Trigger scheduled data source refreshes at precise times aligned to your data pipeline. Download rendered view images or PDFs for inclusion in automated reports. Query workbook metadata to audit what dashboards exist across projects and sites. Manage user permissions programmatically as team members join or leave. Publish new data sources or update existing ones as your data changes.
The Tableau REST API uses a session-based authentication model where you first sign in to receive a token, then include that token in subsequent requests. Personal Access Tokens (available in Tableau Server 2019.4+ and Tableau Cloud) are the recommended credential type for server-to-server integration β they do not expire unless revoked, and they work independently of any user's active browser session. Your Replit backend manages the PAT sign-in flow transparently, obtaining session tokens as needed and refreshing them when they expire.
Integration method
Tableau exposes a REST API that uses token-based authentication. Your Replit backend first signs in to obtain a session token, then uses that token to call endpoints for querying workbooks, downloading views as images or PDFs, refreshing data sources, and managing users. Tableau Personal Access Tokens (PATs) provide long-lived credentials for server-to-server authentication without requiring a user to interactively log in. All API calls must be made from your Replit server β never expose session tokens in client-side code.
Prerequisites
- A Replit account with a Node.js or Python Repl ready
- Access to Tableau Server (version 2019.4+) or Tableau Cloud with a user account
- A Tableau Personal Access Token (PAT) created in your Tableau account settings
- Your Tableau Server URL and site ID (found in the URL when logged into Tableau)
- The workbook or view ID you want to query (findable via the REST API or Tableau URL)
Step-by-step guide
Create a Tableau Personal Access Token and Configure Replit Secrets
Create a Tableau Personal Access Token and Configure Replit Secrets
Personal Access Tokens are the recommended authentication method for server-to-server Tableau REST API integrations. Unlike username/password authentication, PATs do not expire with user sessions and survive password changes. To create a PAT: log into your Tableau Server or Tableau Cloud account, click your profile avatar in the top-right corner, and select 'Account Settings'. Scroll to the 'Personal Access Tokens' section and click 'Create new token'. Enter a descriptive name like 'replit-backend' and click 'Create'. Tableau shows you the token secret once β copy it immediately, as it cannot be retrieved again. Note the following values you will need: - Your Tableau Server URL (e.g., https://tableau.yourcompany.com or https://10ax.online.tableau.com for Tableau Cloud) - Your site ID from the URL (visible in the browser address bar after /site/ β for the default site it is an empty string or 'default') - Your PAT name (the label you gave the token) - Your PAT secret (the token value itself) In Replit, click the lock icon (π) in the left sidebar and add these secrets: TABLEAU_SERVER_URL: the full base URL of your Tableau Server (no trailing slash) TABLEAU_SITE_ID: your site content URL (empty string for default site) TABLEAU_PAT_NAME: the name you gave the Personal Access Token TABLEAU_PAT_SECRET: the token secret value
1// verify-tableau-secrets.js2const required = ['TABLEAU_SERVER_URL', 'TABLEAU_SITE_ID', 'TABLEAU_PAT_NAME', 'TABLEAU_PAT_SECRET'];3const missing = required.filter(k => !process.env[k]);4if (missing.length) {5 console.error('Missing secrets:', missing.join(', '));6 console.error('Add them in Replit Secrets (lock icon π).');7 process.exit(1);8}9console.log('All Tableau secrets configured.');10console.log('Server:', process.env.TABLEAU_SERVER_URL);11console.log('Site ID:', process.env.TABLEAU_SITE_ID || '(default site)');12console.log('PAT name:', process.env.TABLEAU_PAT_NAME);Pro tip: For Tableau Cloud, your server URL includes a pod identifier like 10ax.online.tableau.com. Find your exact URL in the browser address bar when logged into Tableau Cloud β it is in the format https://[pod].online.tableau.com/#/site/[siteid].
Expected result: The verification script prints 'All Tableau secrets configured' with your server URL and PAT name. No missing secret errors appear.
Authenticate with the Tableau REST API Using PAT
Authenticate with the Tableau REST API Using PAT
The Tableau REST API requires a two-step process: first sign in using your PAT to get a session token, then include that token in all subsequent requests as an X-Tableau-Auth header. Sessions expire after a period of inactivity (typically 240 minutes on Tableau Server, 120 minutes on Tableau Cloud), so your backend should handle re-authentication automatically. The sign-in endpoint is POST {server}/api/{api_version}/auth/signin. Tableau REST API versions map to Tableau Server versions β for Tableau Server 2023.x use api version 3.18; for Tableau Cloud use 3.21 or check the Tableau documentation for the current version. The request body is XML or JSON (Tableau's API accepts both β use JSON for simplicity). A successful sign-in response returns a credentials object containing the token (your session token) and the site's luid (local unique identifier). Store both β you need the token for the X-Tableau-Auth header on every subsequent request, and the site luid as part of the URL path (e.g., /api/3.18/sites/{site_luid}/workbooks). Build a reusable Tableau client class or module that handles sign-in automatically, stores the token and expiry time, and refreshes it transparently when making requests. This keeps the rest of your code clean β just call tableau.get('/workbooks') without worrying about authentication state.
1# tableau_client.py β Tableau REST API client with PAT auth (Python)2import os3import time4import requests56TABLEAU_SERVER = os.environ['TABLEAU_SERVER_URL']7TABLEAU_SITE_ID = os.environ['TABLEAU_SITE_ID'] # empty string for default site8PAT_NAME = os.environ['TABLEAU_PAT_NAME']9PAT_SECRET = os.environ['TABLEAU_PAT_SECRET']10API_VERSION = '3.18' # Update to match your Tableau Server version1112class TableauClient:13 def __init__(self):14 self.token = None15 self.site_luid = None16 self.token_expiry = 017 self.base_url = f"{TABLEAU_SERVER}/api/{API_VERSION}"1819 def _sign_in(self):20 resp = requests.post(21 f"{self.base_url}/auth/signin",22 json={23 'credentials': {24 'personalAccessTokenName': PAT_NAME,25 'personalAccessTokenSecret': PAT_SECRET,26 'site': {'contentUrl': TABLEAU_SITE_ID}27 }28 }29 )30 resp.raise_for_status()31 creds = resp.json()['credentials']32 self.token = creds['token']33 self.site_luid = creds['site']['id']34 self.token_expiry = time.time() + 7000 # ~2 hours35 print(f'Signed in to Tableau. Site LUID: {self.site_luid}')3637 def _ensure_auth(self):38 if not self.token or time.time() > self.token_expiry:39 self._sign_in()4041 def get(self, path, params=None):42 self._ensure_auth()43 url = f"{self.base_url}/sites/{self.site_luid}{path}"44 resp = requests.get(url, headers={'x-tableau-auth': self.token}, params=params)45 resp.raise_for_status()46 return resp.json()4748 def post(self, path, body=None):49 self._ensure_auth()50 url = f"{self.base_url}/sites/{self.site_luid}{path}"51 resp = requests.post(url, headers={'x-tableau-auth': self.token}, json=body)52 resp.raise_for_status()53 return resp.json()5455 def sign_out(self):56 if self.token:57 requests.post(58 f"{self.base_url}/auth/signout",59 headers={'x-tableau-auth': self.token}60 )61 self.token = None6263# Usage64if __name__ == '__main__':65 client = TableauClient()66 workbooks = client.get('/workbooks')67 for wb in workbooks.get('workbooks', {}).get('workbook', []):68 print(f" [{wb['id']}] {wb['name']} β {wb['project']['name']}")Pro tip: Always sign out at the end of a long-lived process using POST /auth/signout to release the session on the Tableau Server. For short-lived scripts that run and exit, sign-out is less critical, but it is good practice in production environments where session limits may apply.
Expected result: The TableauClient successfully signs in, prints the site LUID, and lists your Tableau workbooks with their IDs and project names.
Query Workbooks, Views, and Download Rendered Images
Query Workbooks, Views, and Download Rendered Images
Once authenticated, the most common Tableau REST API operations are querying workbook and view metadata, and downloading rendered views as images or PDFs for use in reports and emails. To list all workbooks on a site: GET /sites/{site_luid}/workbooks. Each workbook has an id, name, project, and a list of views. To get a specific workbook's views: GET /sites/{site_luid}/workbooks/{workbook_luid}/views. Each view has an id (LUID) and a name corresponding to a sheet in the Tableau workbook. To download a view as a PNG image: GET /sites/{site_luid}/views/{view_luid}/image. This endpoint returns binary image data rather than JSON β use response.content (Python) or handle the response as a Buffer (Node.js). You can pass query parameters to control image resolution: maxAge=0 forces a fresh render, and you can set resolution for higher-quality images. To download as PDF: GET /sites/{site_luid}/views/{view_luid}/pdf. PDF export supports orientation and page size parameters. This endpoint is particularly useful for executive report automation where you need print-ready output. For Node.js, use axios with responseType: 'arraybuffer' or 'stream' to receive binary content. For Python, access resp.content for the raw bytes. Save to a file or pass directly to an email attachment or S3 upload.
1// tableau-views.js β Query workbooks and download view images (Node.js)2const axios = require('axios');3const fs = require('fs');45const SERVER = process.env.TABLEAU_SERVER_URL;6const SITE_ID = process.env.TABLEAU_SITE_ID;7const PAT_NAME = process.env.TABLEAU_PAT_NAME;8const PAT_SECRET = process.env.TABLEAU_PAT_SECRET;9const API_VERSION = '3.18';1011let sessionToken = null;12let siteLuid = null;1314async function signIn() {15 const resp = await axios.post(`${SERVER}/api/${API_VERSION}/auth/signin`, {16 credentials: {17 personalAccessTokenName: PAT_NAME,18 personalAccessTokenSecret: PAT_SECRET,19 site: { contentUrl: SITE_ID }20 }21 });22 sessionToken = resp.data.credentials.token;23 siteLuid = resp.data.credentials.site.id;24 console.log('Signed in. Site LUID:', siteLuid);25}2627function authHeaders() {28 return { 'x-tableau-auth': sessionToken };29}3031async function listWorkbooks() {32 const resp = await axios.get(33 `${SERVER}/api/${API_VERSION}/sites/${siteLuid}/workbooks`,34 { headers: authHeaders() }35 );36 return resp.data.workbooks.workbook || [];37}3839async function getWorkbookViews(workbookLuid) {40 const resp = await axios.get(41 `${SERVER}/api/${API_VERSION}/sites/${siteLuid}/workbooks/${workbookLuid}/views`,42 { headers: authHeaders() }43 );44 return resp.data.views.view || [];45}4647async function downloadViewImage(viewLuid, outputPath) {48 const resp = await axios.get(49 `${SERVER}/api/${API_VERSION}/sites/${siteLuid}/views/${viewLuid}/image`,50 {51 headers: authHeaders(),52 responseType: 'arraybuffer',53 params: { maxAge: 0 } // Force fresh render54 }55 );56 fs.writeFileSync(outputPath, resp.data);57 console.log(`View image saved to ${outputPath} (${resp.data.byteLength} bytes)`);58}5960async function downloadViewPdf(viewLuid, outputPath) {61 const resp = await axios.get(62 `${SERVER}/api/${API_VERSION}/sites/${siteLuid}/views/${viewLuid}/pdf`,63 {64 headers: authHeaders(),65 responseType: 'arraybuffer',66 params: { orientation: 'Landscape', type: 'A4' }67 }68 );69 fs.writeFileSync(outputPath, resp.data);70 console.log(`PDF saved to ${outputPath}`);71}7273async function main() {74 await signIn();75 const workbooks = await listWorkbooks();76 console.log(`\nFound ${workbooks.length} workbook(s)`);7778 if (workbooks.length > 0) {79 const wb = workbooks[0];80 console.log(`\nViews in "${wb.name}":`);81 const views = await getWorkbookViews(wb.id);82 views.forEach(v => console.log(` [${v.id}] ${v.name}`));8384 if (views.length > 0) {85 await downloadViewImage(views[0].id, 'dashboard.png');86 await downloadViewPdf(views[0].id, 'dashboard.pdf');87 }88 }89}9091main().catch(console.error);Pro tip: Rendered images and PDFs can take several seconds to generate on Tableau Server for complex dashboards. For production report automation, schedule these downloads during off-peak hours to avoid competing with interactive user queries on the Tableau Server.
Expected result: The script lists your Tableau workbooks and views, then saves dashboard.png and dashboard.pdf in your Replit project directory containing rendered versions of the first view in the first workbook.
Trigger Data Source Refreshes and Build an Express API
Trigger Data Source Refreshes and Build an Express API
One of the most valuable Tableau automation patterns is triggering data source refreshes programmatically when your upstream data pipeline completes, so Tableau dashboards always show fresh data without manual intervention. To refresh a data source: POST /sites/{site_luid}/datasources/{datasource_luid}/refresh. First query your data sources with GET /sites/{site_luid}/datasources to find the LUID of the data source you want to refresh. The refresh endpoint returns a job object β you can poll GET /sites/{site_luid}/jobs/{job_luid} to check when the refresh completes. Wrap the Tableau client in an Express API so other services can trigger Tableau operations via HTTP. This is particularly useful for webhook-driven architectures: your data pipeline POSTs to your Replit server when a load job completes, and your server immediately triggers the Tableau refresh. Set up a Reserved VM deployment if you need this endpoint available 24/7 for incoming webhooks, or Autoscale if traffic is infrequent. For Replit deployments, ensure your .replit file sets the run command to start the Express server. The server binds to 0.0.0.0:3000, which Replit's networking layer exposes externally. Use environment variable TABLEAU_DATASOURCE_LUID to configure which data source to refresh without changing code.
1# tableau_api.py β Express-style Flask API for Tableau operations2import os3import time4import requests5from flask import Flask, jsonify, request67TABLEAU_SERVER = os.environ['TABLEAU_SERVER_URL']8TABLEAU_SITE_ID = os.environ['TABLEAU_SITE_ID']9PAT_NAME = os.environ['TABLEAU_PAT_NAME']10PAT_SECRET = os.environ['TABLEAU_PAT_SECRET']11API_VERSION = '3.18'1213app = Flask(__name__)1415# Global session state16_token = None17_site_luid = None18_expiry = 01920def ensure_auth():21 global _token, _site_luid, _expiry22 if _token and time.time() < _expiry:23 return24 resp = requests.post(25 f'{TABLEAU_SERVER}/api/{API_VERSION}/auth/signin',26 json={'credentials': {27 'personalAccessTokenName': PAT_NAME,28 'personalAccessTokenSecret': PAT_SECRET,29 'site': {'contentUrl': TABLEAU_SITE_ID}30 }}31 )32 resp.raise_for_status()33 creds = resp.json()['credentials']34 _token = creds['token']35 _site_luid = creds['site']['id']36 _expiry = time.time() + 70003738def tableau_get(path, **kwargs):39 ensure_auth()40 url = f'{TABLEAU_SERVER}/api/{API_VERSION}/sites/{_site_luid}{path}'41 resp = requests.get(url, headers={'x-tableau-auth': _token}, **kwargs)42 resp.raise_for_status()43 return resp4445def tableau_post(path, body=None):46 ensure_auth()47 url = f'{TABLEAU_SERVER}/api/{API_VERSION}/sites/{_site_luid}{path}'48 resp = requests.post(url, headers={'x-tableau-auth': _token}, json=body)49 resp.raise_for_status()50 return resp.json()5152@app.route('/api/tableau/workbooks')53def list_workbooks():54 data = tableau_get('/workbooks').json()55 workbooks = data.get('workbooks', {}).get('workbook', [])56 return jsonify({'count': len(workbooks), 'workbooks': [57 {'id': w['id'], 'name': w['name'], 'project': w.get('project', {}).get('name', '')}58 for w in workbooks59 ]})6061@app.route('/api/tableau/datasources')62def list_datasources():63 data = tableau_get('/datasources').json()64 datasources = data.get('datasources', {}).get('datasource', [])65 return jsonify({'datasources': [66 {'id': ds['id'], 'name': ds['name']}67 for ds in datasources68 ]})6970@app.route('/api/tableau/datasources/<ds_luid>/refresh', methods=['POST'])71def refresh_datasource(ds_luid):72 result = tableau_post(f'/datasources/{ds_luid}/refresh')73 job_id = result.get('job', {}).get('id', 'unknown')74 return jsonify({'status': 'refresh_triggered', 'job_id': job_id})7576if __name__ == '__main__':77 app.run(host='0.0.0.0', port=3000)Pro tip: Store your data source LUIDs as environment variables (e.g., TABLEAU_SALES_DS_LUID, TABLEAU_INVENTORY_DS_LUID) in Replit Secrets so you can trigger specific refreshes without looking up IDs each time. LUIDs are stable identifiers that do not change even if the data source is renamed.
Expected result: GET /api/tableau/workbooks lists all workbooks in JSON. GET /api/tableau/datasources lists data sources. POST /api/tableau/datasources/{id}/refresh returns a job ID confirming the refresh was triggered on Tableau Server.
Common use cases
Automated Tableau Report Distribution
Build a Replit backend that connects to Tableau, downloads specific dashboard views as high-resolution PNG images or PDFs, and attaches them to automated email reports. Run it on a Replit Scheduled deployment to send weekly executive summaries without anyone manually exporting from Tableau.
Build a Python script that authenticates to Tableau, downloads a specific view as a PDF, and attaches it to an email sent via SendGrid every Monday morning.
Copy this prompt to try it in Replit
Data Pipeline Trigger and Refresh
When your ETL pipeline finishes loading new data, trigger a Tableau data source refresh via the REST API so dashboards show up-to-date figures immediately. Your Replit backend acts as the orchestrator, calling the Tableau API to refresh specific datasources after each pipeline run completes.
Create a Node.js Express endpoint that receives a POST from your data pipeline on completion, authenticates to Tableau, and triggers a refresh of a specified datasource by ID.
Copy this prompt to try it in Replit
Embedded Analytics with Secure Tokens
Use Tableau's Connected Apps or trusted authentication to generate secure embed tokens from your Replit backend. Your backend issues time-limited tokens that the frontend uses to embed Tableau views in an iframe without exposing your PAT credentials. This enables personalized, secure Tableau embeds for each authenticated user.
Build an Express endpoint that generates a Tableau embed token for the current authenticated user and returns the embed URL for a specific workbook view.
Copy this prompt to try it in Replit
Troubleshooting
401 Unauthorized or 'Invalid credentials' when signing in with Personal Access Token
Cause: The PAT name or secret in Replit Secrets contains a typo or whitespace, the token has been revoked on Tableau Server, or your Tableau Server requires a different API version than the one in your code.
Solution: Open Replit Secrets (lock icon π) and re-enter TABLEAU_PAT_NAME and TABLEAU_PAT_SECRET carefully. Verify the token exists and is active in your Tableau account settings. Check the Tableau REST API version number β it must match a version supported by your Tableau Server installation.
1// Log the first few chars of PAT values to verify they are set2console.log('PAT Name:', process.env.TABLEAU_PAT_NAME);3console.log('PAT Secret set:', !!process.env.TABLEAU_PAT_SECRET, 'length:', (process.env.TABLEAU_PAT_SECRET || '').length);404 Not Found when querying workbooks or views even after successful sign-in
Cause: The site LUID used in the URL does not match the site you are connected to, or you are using the site content URL (text ID) as the site LUID (UUID) in the URL path. The URL path requires the UUID, not the content URL string.
Solution: The sign-in response returns both the site content URL and the site LUID (UUID like 'a1b2c3d4-...'). Use the 'id' field from the response as the site LUID in all subsequent URL paths β not the TABLEAU_SITE_ID environment variable, which is the content URL used only for sign-in.
1// After sign-in, use the returned site LUID (not the site content URL)2const resp = await axios.post(`${SERVER}/api/${API_VERSION}/auth/signin`, body);3const credentials = resp.data.credentials;4console.log('Content URL:', credentials.site.contentUrl);5console.log('Site LUID for API paths:', credentials.site.id); // Use THIS in URLs403 Forbidden when trying to access a workbook or datasource
Cause: The Tableau user account associated with the PAT does not have permission to access that specific workbook, project, or data source. Tableau's permission system is granular β permissions are set at the project and content level.
Solution: Log into Tableau as an administrator and check the permissions on the workbook or data source. Ensure the user account that owns the PAT has at least 'View' permission on the relevant project and content. For data source refreshes, the user needs 'Download' permission on the data source.
View image download returns a 202 Accepted or empty response instead of image binary
Cause: Tableau is still rendering the view asynchronously. The 202 status means the render job was queued but not yet complete. This occurs for complex dashboards that take longer than the API timeout to render.
Solution: Add a retry loop with a short delay. If the view image endpoint returns 202, wait 2-3 seconds and retry. After the view is cached server-side, subsequent requests return the image immediately. Pass maxAge=1 (minutes) instead of maxAge=0 to allow Tableau to serve a recently cached version.
1// Retry view image download with backoff2async function downloadWithRetry(viewLuid, maxAttempts = 5) {3 for (let i = 0; i < maxAttempts; i++) {4 const resp = await axios.get(5 `${SERVER}/api/${API_VERSION}/sites/${siteLuid}/views/${viewLuid}/image`,6 { headers: authHeaders(), responseType: 'arraybuffer', validateStatus: null }7 );8 if (resp.status === 200) return resp.data;9 if (resp.status === 202) {10 console.log(`View still rendering, attempt ${i+1}/${maxAttempts}...`);11 await new Promise(r => setTimeout(r, 3000));12 } else throw new Error(`Unexpected status: ${resp.status}`);13 }14 throw new Error('View render timed out after max attempts');15}Best practices
- Store TABLEAU_PAT_NAME, TABLEAU_PAT_SECRET, TABLEAU_SERVER_URL, and TABLEAU_SITE_ID in Replit Secrets (lock icon π) β Personal Access Tokens provide full user-level access and must be kept secret
- Use Personal Access Tokens instead of username/password authentication for server-to-server integration β PATs do not expire with browser sessions and are easier to rotate without changing code
- Cache the session token from the sign-in response and reuse it for 1-2 hours before re-authenticating β signing in on every API call wastes Tableau Server resources and slows your application
- Use the site LUID returned from the sign-in response in all URL paths, not the site content URL string β they look similar but serve different purposes in the API
- Deploy as Reserved VM if your Replit server needs to maintain a persistent Tableau session for webhook-driven operations; use Autoscale for infrequent on-demand queries
- Match the API version in your request URLs to your Tableau Server version β using a newer API version than your server supports returns 404 errors on valid endpoints
- Poll the job status endpoint after triggering a data source refresh rather than assuming immediate completion β large data sources can take minutes to refresh
- Restrict the Tableau user account associated with the PAT to only the projects and content it needs to access β do not use a site administrator account for routine automation tasks
Alternatives
Looker is Google Cloud's native BI platform with a robust REST API and tighter BigQuery integration β choose it if your organization is already on Google Cloud infrastructure.
Power BI is deeply integrated with the Microsoft ecosystem (Azure AD, Teams, Office 365) and is the natural choice for organizations already invested in Microsoft tooling.
Google Cloud AI Platform provides managed ML prediction and analytics services natively integrated with BigQuery for organizations building custom ML-powered analytics.
Frequently asked questions
How do I connect Replit to Tableau?
Store your Tableau Server URL, site ID, and Personal Access Token credentials in Replit Secrets (lock icon π), then call the Tableau REST API from your Node.js or Python backend. The flow is: POST to /auth/signin to get a session token, then include that token in an x-tableau-auth header on all subsequent requests for workbooks, views, and data sources.
Does Replit work with Tableau?
Yes. Tableau Server and Tableau Cloud both expose a REST API that any HTTP client can call. Your Replit backend authenticates using a Personal Access Token and can query workbooks, download view images and PDFs, trigger data source refreshes, and manage users programmatically.
How do I store my Tableau API credentials in Replit?
Click the lock icon (π) in the Replit sidebar and add TABLEAU_SERVER_URL, TABLEAU_SITE_ID, TABLEAU_PAT_NAME, and TABLEAU_PAT_SECRET as separate secrets. In Node.js, access them as process.env.TABLEAU_PAT_SECRET; in Python, use os.environ['TABLEAU_PAT_SECRET']. Never hardcode these values in source files.
Can I use Tableau REST API with Replit for free?
Access to Tableau Server or Tableau Cloud requires a paid Tableau license β there is no free tier for Tableau Server access. However, Tableau offers a 14-day free trial. On the Replit side, the Autoscale deployment is sufficient for periodic API calls, and billing starts only when your app receives traffic.
What Tableau REST API version should I use?
The API version must match a version supported by your Tableau Server installation. Tableau 2023.x supports API versions through 3.18-3.21. Check your Tableau Server version in the About dialog, then consult the Tableau REST API version history in the official documentation to find the corresponding maximum API version.
How do I download a Tableau dashboard as an image from Replit?
After signing in and getting the site LUID, call GET /api/{version}/sites/{site_luid}/views/{view_luid}/image with your session token in the x-tableau-auth header and responseType: 'arraybuffer' (Node.js) or stream the response (Python). The endpoint returns the rendered dashboard as PNG binary data that you can save to a file or email as an attachment.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation