TSC Datasource Management: All Methods

Every data source operation on the site — list, inspect, download, publish, refresh, update, rotate credentials, delete — from one script instead of a hundred clicks.

intermediate30 min10 steps

Why it matters

Data sources are where Tableau sites rot: refreshes fail silently, connection credentials expire, nobody knows which extract feeds which dashboard. TSC's datasources endpoint is ten methods that replace the clicking — and once you can enumerate and modify every data source programmatically, stale-content audits, credential rotation, and bulk migrations stop being projects and become scripts.

Prompt Recipe

Write a Python CLI using tableauserverclient and argparse with subcommands for Tableau data source operations: `list` (with optional --name-contains, --project, and --tag filters via RequestOptions), `inspect <id>` (details plus populated connections), `download <id>` (backup, with --no-extract for speed), `publish <path> --project <name> --mode CreateNew|Overwrite`, `refresh <id>` (trigger and poll the job to completion), `update <id> --owner|--certified --note`, `rotate <id>` (update connection credentials from environment variables), and `delete <id>`. Authenticate with a PAT from environment variables. Every destructive subcommand (publish --mode Overwrite, rotate, delete) requires a --confirm flag and supports --dry-run that prints what would change instead of doing it.

Step 1datasources.get — List & Filter Data Sources

datasources.get — List & Filter Data Sources

List every datasource on your site and filter with RequestOptions + Filter (name, project, tags, owner, certification).

💡 Info
Filtering by Name Contains is handy for quick, broad matches (e.g., 'Sales'). Combine multiple filters for precise results.
with server.auth.sign_in(tableau_auth):
    ro = TSC.RequestOptions()
    ro.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Contains, 'Sales'))
    all_datasources, pagination_item = server.datasources.get(ro)
    print([ds.name for ds in all_datasources])

Step 2datasources.get_by_id — Fetch a Specific Datasource

datasources.get_by_id — Fetch a Specific Datasource

Each datasource has a unique ID; fetch it to access full details like project, owner, and certification note.

💡 Info
Grab the ID from list results or the URL in Tableau. Using IDs avoids name collisions.
with server.auth.sign_in(tableau_auth):
    datasource = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
    print(datasource.name, datasource.project_name, datasource.owner_id)

Step 3datasources.populate_connections — See Connection Details

datasources.populate_connections — See Connection Details

Datasource objects do not include connection info by default. Populate to view server address, DB name, and connection type.

💡 Info
Connection details help diagnose refresh failures and Bridge routing before edits.
with server.auth.sign_in(tableau_auth):
    ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
    server.datasources.populate_connections(ds)
    for conn in ds.connections:
        print(conn.connection_type, conn.server_address, conn.dbname)

Step 4datasources.download — Save a Datasource File

datasources.download — Save a Datasource File

Download a local copy to inspect structure or keep a backup. You can exclude extracts for faster downloads.

Success
Versioned backups make rollbacks painless and reduce risk during refactors.
with server.auth.sign_in(tableau_auth):
    path = server.datasources.download('YOUR-DATASOURCE-ID', include_extract=False)
    print(f'Downloaded to {path}')

Step 5datasources.publish — Publish a New Datasource

datasources.publish — Publish a New Datasource

Publish a new datasource or update an existing one. Provide a valid file path and target project.

⚠️ Warning
Overwrite may replace prior versions. Ensure you have a backup or publish as new first.
💡 Info
Publish modes: CreateNew (new item), Overwrite (replace), Append (for compatible extract schemas).
with server.auth.sign_in(tableau_auth):
    project_id = 'YOUR-PROJECT-ID'
    file_path = r'C:\\path\\to\\WorldIndicators.hyper'
    new_ds_item = TSC.DatasourceItem(project_id, name='WorldIndicators')
    new_ds = server.datasources.publish(new_ds_item, file_path, TSC.Server.PublishMode.CreateNew)
    print(new_ds.name, new_ds.id)

Step 6datasources.refresh — Run an On-Demand Extract Refresh

datasources.refresh — Run an On-Demand Extract Refresh

Trigger a refresh now instead of waiting for the schedule. Returns a job you can track.

💡 Info
Consider off-peak execution to minimize contention with live traffic. Log job IDs for status tracking.
with server.auth.sign_in(tableau_auth):
    ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
    job = server.datasources.refresh(ds)
    print('Refresh job started:', job.id)

Step 7datasources.update — Update Metadata

datasources.update — Update Metadata

Modify metadata like owner, description, and certification settings, then push changes.

💡 Info
Use a certification policy: set certified only after validation; include a clear certification_note for auditors.
with server.auth.sign_in(tableau_auth):
    ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
    ds.certified = True
    ds.certification_note = 'Validated by BI team'
    updated = server.datasources.update(ds)
    print(updated.certified, updated.certification_note)

Step 8datasources.update_connection — Rotate or Edit Connection Credentials

datasources.update_connection — Rotate or Edit Connection Credentials

Populate connections, change fields, then apply with update_connection.

⚠️ Warning
Credential or host changes can break refreshes and Bridge routing. Test on a copy and verify scheduled jobs.
💡 Info
Prefer password vaults or Connected Apps when possible; avoid storing plaintext in scripts.
with server.auth.sign_in(tableau_auth):
    ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
    server.datasources.populate_connections(ds)
    conn = ds.connections[0]
    conn.server_address = 'new-db-host'
    conn.username = 'newuser'
    conn.password = 'newpass'
    updated_conn = server.datasources.update_connection(ds, conn)
    print(updated_conn.server_address, updated_conn.username)

Step 9datasources.update_hyper_data — Modify Rows in Live-to-Hyper Datasources

datasources.update_hyper_data — Modify Rows in Live-to-Hyper Datasources

Push row-level updates into a published Hyper datasource (REST API 3.13+). Prepare a Hyper payload file with your changes.

⚠️ Warning
Row updates are impactful and not easily undone. Snapshot before changes and validate on a non-prod copy.
💡 Info
Use pantab or the Hyper API to build the payload. Track the returned job and surface status to stakeholders.
# Example using pantab or Hyper API to build payload.hyper, then:
with server.auth.sign_in(tableau_auth):
    ds = server.datasources.get_by_id('YOUR-DATASOURCE-ID')
    actions = [{ 'action': 'insert', 'table': {'schema': 'public', 'name': 'region_sales'} }]
    job = server.datasources.update_hyper_data(ds, request_id='unique-req-001', actions=actions, payload='payload.hyper')
    print('Update job started:', job.id)

Step 10datasources.delete — Permanently Remove a Datasource

datasources.delete — Permanently Remove a Datasource

Deletes a datasource permanently. Double-check the ID before running this—there is no undo.

🛑 Danger
This action is irreversible unless you have external backups or an archival workflow. Confirm ownership, consumers, and retention first.
💡 Info
Consider a soft-delete pattern: move to an 'Archive' project and expire after a cooling-off period.
with server.auth.sign_in(tableau_auth):
    server.datasources.delete('YOUR-DATASOURCE-ID')
    print('Datasource deleted.')

Got what you came for? Mark the stop and the line fills in beneath you.