# Tableau

> Find and organise Tableau content - browse projects, workbooks, views and data sources, read the numbers behind a view, and refresh an extract.

App · Analytics · 20 actions. Web page: https://docs.lodol.com/docs/integrations/tableau

## Actions

### Create a project

Create a project on the Tableau site, optionally nested inside an existing one. Use the id this returns in the next step - Tableau takes a second or two to include a new project in a list, so listing to find it can come back empty.

**Inputs**

- Project name (`name`, text, required): What to call the project. It has to be unique among the projects that share its parent.
- Description (`description`, text): What the project is for. Shown on its card in Tableau.
- Parent project (`parent_project_id`, text): Nest the project inside this one. Leave empty to create it at the top level. Creating a top-level project usually needs a Site Administrator role.
- Permissions are (`content_permissions`, text): Whether each item in the project keeps its own permissions or inherits the project's. Leave empty to keep Tableau's default. One of: `ManagedByOwner` (Managed by owner - each item's owner sets its permissions), `LockedToProject` (Locked to project - the project's permissions apply to everything in it), `LockedToProjectWithoutNested` (Locked to project, nested projects excluded).
- Publish Tableau's sample workbooks into it (`publish_samples`, true/false): Ask Tableau to publish its own sample workbooks into the new project. Useful for a scratch or demo project; leave off for a real one. Default: `false`.

**Outputs**

- `content_permissions` (text)
- `controlling_permissions_project_id` (text)
- `created_at` (text)
- `description` (text)
- `id` (text)
- `name` (text)
- `owner` (object)
- `parent_project_id` (text)
- `top_level_project` (true/false)
- `updated_at` (text)
- `writeable` (true/false)

**Example output**

```json
{
  "content_permissions": "ManagedByOwner",
  "controlling_permissions_project_id": null,
  "created_at": "2026-09-05T10:30:00Z",
  "description": "Dashboards for the quarterly review.",
  "id": "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d",
  "name": "Quarterly reporting",
  "owner": {
    "email": "ada@example.com",
    "full_name": "Ada Lovelace",
    "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
    "name": "ada@example.com"
  },
  "parent_project_id": null,
  "top_level_project": true,
  "updated_at": "2026-09-05T10:30:00Z",
  "writeable": true
}
```

### Delete a project

Delete a project. Everything published inside it - workbooks, views and data sources - is deleted with it, and Tableau offers no undo.

**Inputs**

- Project (`project_id`, text, required): Which project to act on. Pick one, or paste the id of a project made earlier in this workflow.

**Outputs**

- `deleted` (true/false)
- `id` (text)

**Example output**

```json
{
  "deleted": true,
  "id": "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d"
}
```

### Get a data source

Read one published data source, including whether it has an extract that can be refreshed.

**Inputs**

- Data source id (`datasource_id`, text, required): The published data source's Tableau id (a GUID). List data sources returns it.

**Outputs**

- `certification_note` (text)
- `content_url` (text)
- `created_at` (text)
- `description` (text)
- `encrypt_extracts` (text)
- `has_extracts` (true/false)
- `id` (text)
- `is_certified` (true/false)
- `name` (text)
- `owner` (object)
- `project` (object)
- `size` (number)
- `tags` (list)
- `type` (text)
- `updated_at` (text)
- `use_remote_query_agent` (true/false)
- `webpage_url` (text)

**Example output**

```json
{
  "certification_note": "Owned by the data team.",
  "content_url": "Salesextract",
  "created_at": "2026-03-02T11:00:00Z",
  "description": "Nightly extract of the sales warehouse.",
  "encrypt_extracts": "false",
  "has_extracts": true,
  "id": "89a82d78-664f-45a1-8256-d4d2961a070b",
  "is_certified": true,
  "name": "Sales extract",
  "owner": {
    "email": "ada@example.com",
    "full_name": "Ada Lovelace",
    "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
    "name": "ada@example.com"
  },
  "project": {
    "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
    "name": "Default"
  },
  "size": 41,
  "tags": [
    "certified"
  ],
  "type": "sqlserver",
  "updated_at": "2026-09-04T02:15:00Z",
  "use_remote_query_agent": false,
  "webpage_url": "https://10ax.online.tableau.com/#/site/acme/datasources/77"
}
```

### Get a job

Read one background job's progress and outcome. While it is running there is no finish code; when it ends, '0' means it succeeded, '1' that it failed and '2' that it was cancelled.

**Inputs**

- Job id (`job_id`, text, required): The job's Tableau id (a GUID). Refresh a data source extract returns it, and so does List background jobs.

**Outputs**

- `completed_at` (text)
- `created_at` (text)
- `finish_code` (text)
- `id` (text)
- `mode` (text)
- `notes` (list)
- `progress` (number)
- `started_at` (text)
- `status_notes` (list)
- `type` (text)
- `updated_at` (text)

**Example output**

```json
{
  "completed_at": "2026-09-05T10:31:22Z",
  "created_at": "2026-09-05T10:30:00Z",
  "finish_code": "0",
  "id": "5e6f7a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
  "mode": "Asynchronous",
  "notes": [
    "Data source Sales extract refreshed."
  ],
  "progress": 100,
  "started_at": "2026-09-05T10:30:04Z",
  "status_notes": [],
  "type": "RefreshExtract",
  "updated_at": "2026-09-05T10:31:22Z"
}
```

### Get a view

Read one view's details, and optionally how many times it has been opened.

**Inputs**

- View id (`view_id`, text, required): The view's Tableau id (a GUID). List views or List a workbook's views returns it.
- Include view counts (`include_usage_statistics`, true/false): Also return how many times each view has been opened. Tableau leaves this out unless it is asked for, because it costs an extra lookup. Default: `false`.

**Outputs**

- `content_url` (text)
- `created_at` (text)
- `id` (text)
- `name` (text)
- `owner` (object)
- `project` (object)
- `tags` (list)
- `total_view_count` (number)
- `updated_at` (text)
- `view_url_name` (text)
- `workbook_id` (text)

**Example output**

```json
{
  "content_url": "Superstore/sheets/Overview",
  "created_at": "2026-02-11T08:15:00Z",
  "id": "2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
  "name": "Overview",
  "owner": {
    "email": "ada@example.com",
    "full_name": "Ada Lovelace",
    "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
    "name": "ada@example.com"
  },
  "project": {
    "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
    "name": "Default"
  },
  "tags": [],
  "total_view_count": 412,
  "updated_at": "2026-08-30T16:02:00Z",
  "view_url_name": "Overview",
  "workbook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e"
}
```

### Get a view's data

Read the summary data behind a view - the same rows Tableau's own 'Download > Data' gives - as rows and as raw CSV.

**Inputs**

- View id (`view_id`, text, required): The view's Tableau id (a GUID). List views or List a workbook's views returns it.
- Filter the view first (`view_filters`, object): Apply the view's own filters before reading it, as an object of field name to value - {"Region": "West"}. Give a list to select several values. Leave empty to read the view as it is.
- Accept cached data up to (minutes) (`max_age_minutes`, number): How stale Tableau's cached copy may be before it recalculates. 0 forces a fresh read, which is slower. Leave empty to use the site's own caching. At least 0.
- Maximum rows (`max_rows`, number): How many rows to bring back. The result's 'truncated' field says whether the view had more. From 1 to 10000. Default: `500`.

**Outputs**

- `columns` (list)
- `csv` (text)
- `row_count` (number)
- `rows` (list)
- `truncated` (true/false)
- `view_id` (text)

**Example output**

```json
{
  "columns": [
    "Region",
    "Sales"
  ],
  "csv": "Region,Sales\nWest,120450\nEast,98230\n",
  "row_count": 2,
  "rows": [
    {
      "Region": "West",
      "Sales": "120450"
    },
    {
      "Region": "East",
      "Sales": "98230"
    }
  ],
  "truncated": false,
  "view_id": "2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f"
}
```

### Get a workbook

Read one workbook's details, including its project, owner, tags and web page URL.

**Inputs**

- Workbook id (`workbook_id`, text, required): The workbook's Tableau id (a GUID). List workbooks returns it, and it also appears in the address bar when you open the workbook.

**Outputs**

- `content_url` (text)
- `created_at` (text)
- `default_view_id` (text)
- `description` (text)
- `id` (text)
- `name` (text)
- `owner` (object)
- `project` (object)
- `show_tabs` (true/false)
- `size` (number)
- `tags` (list)
- `updated_at` (text)
- `webpage_url` (text)

**Example output**

```json
{
  "content_url": "Superstore",
  "created_at": "2026-02-11T08:15:00Z",
  "default_view_id": "2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
  "description": "",
  "id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
  "name": "Superstore",
  "owner": {
    "email": "ada@example.com",
    "full_name": "Ada Lovelace",
    "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
    "name": "ada@example.com"
  },
  "project": {
    "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
    "name": "Default"
  },
  "show_tabs": true,
  "size": 2,
  "tags": [
    "sales"
  ],
  "updated_at": "2026-08-30T16:02:00Z",
  "webpage_url": "https://10ax.online.tableau.com/#/site/acme/workbooks/1234"
}
```

### Get site settings

Read the settings of the Tableau site this connection is signed in to, including its state and storage. Needs a Site Administrator role.

**Inputs**: None.

**Outputs**

- `admin_mode` (text)
- `commenting_enabled` (true/false)
- `content_url` (text)
- `guest_access_enabled` (true/false)
- `id` (text)
- `name` (text)
- `num_users` (text)
- `revision_history_enabled` (true/false)
- `revision_limit` (text)
- `state` (text)
- `storage` (text)
- `storage_quota` (text)
- `subscribe_others_enabled` (true/false)
- `time_zone` (text)
- `user_quota` (text)

**Example output**

```json
{
  "admin_mode": "ContentAndUsers",
  "commenting_enabled": true,
  "content_url": "acme",
  "guest_access_enabled": false,
  "id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d",
  "name": "Acme Analytics",
  "num_users": "18",
  "revision_history_enabled": true,
  "revision_limit": "25",
  "state": "Active",
  "storage": "4096",
  "storage_quota": "102400",
  "subscribe_others_enabled": true,
  "time_zone": "Europe/London",
  "user_quota": "100"
}
```

### List a workbook's views

List the sheets and dashboards inside one workbook, with their ids for reading data or an image.

**Inputs**

- Workbook id (`workbook_id`, text, required): The workbook's Tableau id (a GUID). List workbooks returns it, and it also appears in the address bar when you open the workbook.
- Include view counts (`include_usage_statistics`, true/false): Also return how many times each view has been opened. Tableau leaves this out unless it is asked for, because it costs an extra lookup. Default: `false`.

**Outputs**

- `count` (number)
- `views` (list)
- `workbook_id` (text)

**Example output**

```json
{
  "count": 1,
  "views": [
    {
      "content_url": "Superstore/sheets/Overview",
      "created_at": "2026-02-11T08:15:00Z",
      "id": "2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
      "name": "Overview",
      "owner": {
        "email": "ada@example.com",
        "full_name": "Ada Lovelace",
        "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
        "name": "ada@example.com"
      },
      "project": {
        "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
        "name": "Default"
      },
      "tags": [],
      "total_view_count": 412,
      "updated_at": "2026-08-30T16:02:00Z",
      "view_url_name": "Overview",
      "workbook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e"
    }
  ],
  "workbook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e"
}
```

### List background jobs

List the site's background jobs - extract refreshes, flow runs and subscriptions - newest first.

**Inputs**

- Filter on (`filter_field`, text): Which job field to filter on. Leave the field empty to list everything. Choosing a field means the value below is required. One of: `args` (Job arguments (args)), `completedAt` (Completed at (completedAt)), `createdAt` (Created at (createdAt)), `jobType` (Job type (jobType)), `notes` (Notes (notes)), `priority` (Priority (priority)), `progress` (Progress (progress)), `startedAt` (Started at (startedAt)), `status` (Status (status)), `subtitle` (Subtitle (subtitle)), `title` (Title (title)).
- Filter operator (`filter_operator`, text): How the filter value is compared. Ignored when no field is chosen. Which operators a field accepts depends on the field: name and the other text fields take 'is exactly', date fields such as Created at take the before/after comparisons, and Tags takes 'is any of'. Tableau refuses a pairing it does not support, and the error says so. One of: `eq` (is exactly), `cieq` (is exactly, ignoring case), `gt` (is after / greater than), `gte` (is at or after / greater than or equal to), `lt` (is before / less than), `lte` (is at or before / less than or equal to), `has` (contains), `in` (is any of - a bracketed list, [alpha,beta]), `like` (matches a pattern using * as the wildcard). Default: `eq`.
- Filter value (`filter_value`, text): What to compare against. Dates are ISO-8601 (2026-01-31T00:00:00Z); a list for the 'is any of' operator is bracketed, like [alpha,beta].
- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `jobs` (list)
- `page_number` (number)
- `page_size` (number)
- `total_available` (number)

**Example output**

```json
{
  "count": 1,
  "jobs": [
    {
      "created_at": "2026-09-05T10:30:00Z",
      "ended_at": "2026-09-05T10:31:22Z",
      "id": "5e6f7a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
      "job_type": "refresh_extracts",
      "priority": 50,
      "started_at": "2026-09-05T10:30:04Z",
      "status": "Success"
    }
  ],
  "page_number": 1,
  "page_size": 100,
  "total_available": 1
}
```

### List data sources

List the published data sources on the Tableau site, optionally filtered by project, name or whether they have an extract.

**Inputs**

- Filter on (`filter_field`, text): Which data source field to filter on. Leave the field empty to list everything. Choosing a field means the value below is required. One of: `authenticationType` (Authentication type (authenticationType)), `connectedWorkbookType` (Connected workbook type (connectedWorkbookType)), `connectionTo` (Connects to (connectionTo)), `connectionType` (Connection type (connectionType)), `contentUrl` (Content URL (contentUrl)), `createdAt` (Created at (createdAt)), `databaseName` (Database name (databaseName)), `databaseUserName` (Database user name (databaseUserName)), `description` (Description (description)), `favoritesTotal` (Times favourited (favoritesTotal)), and 20 more.
- Filter operator (`filter_operator`, text): How the filter value is compared. Ignored when no field is chosen. Which operators a field accepts depends on the field: name and the other text fields take 'is exactly', date fields such as Created at take the before/after comparisons, and Tags takes 'is any of'. Tableau refuses a pairing it does not support, and the error says so. One of: `eq` (is exactly), `cieq` (is exactly, ignoring case), `gt` (is after / greater than), `gte` (is at or after / greater than or equal to), `lt` (is before / less than), `lte` (is at or before / less than or equal to), `has` (contains), `in` (is any of - a bracketed list, [alpha,beta]), `like` (matches a pattern using * as the wildcard). Default: `eq`.
- Filter value (`filter_value`, text): What to compare against. Dates are ISO-8601 (2026-01-31T00:00:00Z); a list for the 'is any of' operator is bracketed, like [alpha,beta].
- Sort by (`sort_field`, text): Which data source field to sort on. Leave empty for Tableau's order. One of: `authenticationType` (Authentication type (authenticationType)), `connectedWorkbookType` (Connected workbook type (connectedWorkbookType)), `connectionTo` (Connects to (connectionTo)), `connectionType` (Connection type (connectionType)), `contentUrl` (Content URL (contentUrl)), `createdAt` (Created at (createdAt)), `databaseName` (Database name (databaseName)), `databaseUserName` (Database user name (databaseUserName)), `description` (Description (description)), `favoritesTotal` (Times favourited (favoritesTotal)), and 20 more.
- Sort direction (`sort_direction`, text): Which way to sort. Ignored when no sort field is chosen. One of: `asc` (Ascending), `desc` (Descending). Default: `asc`.
- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `datasources` (list)
- `page_number` (number)
- `page_size` (number)
- `total_available` (number)

**Example output**

```json
{
  "count": 1,
  "datasources": [
    {
      "certification_note": "Owned by the data team.",
      "content_url": "Salesextract",
      "created_at": "2026-03-02T11:00:00Z",
      "description": "Nightly extract of the sales warehouse.",
      "encrypt_extracts": "false",
      "has_extracts": true,
      "id": "89a82d78-664f-45a1-8256-d4d2961a070b",
      "is_certified": true,
      "name": "Sales extract",
      "owner": {
        "email": "ada@example.com",
        "full_name": "Ada Lovelace",
        "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
        "name": "ada@example.com"
      },
      "project": {
        "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
        "name": "Default"
      },
      "size": 41,
      "tags": [
        "certified"
      ],
      "type": "sqlserver",
      "updated_at": "2026-09-04T02:15:00Z",
      "use_remote_query_agent": false,
      "webpage_url": "https://10ax.online.tableau.com/#/site/acme/datasources/77"
    }
  ],
  "page_number": 1,
  "page_size": 100,
  "total_available": 1
}
```

### List groups

List the groups on the Tableau site with how many users each holds. Needs a Site Administrator role.

**Inputs**

- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `groups` (list)
- `page_number` (number)
- `page_size` (number)
- `total_available` (number)

**Example output**

```json
{
  "count": 1,
  "groups": [
    {
      "domain_name": "local",
      "id": "7f8a9b0c-1d2e-3f4a-5b6c-7d8e9f0a1b2c",
      "minimum_site_role": null,
      "name": "All Users",
      "user_count": 18
    }
  ],
  "page_number": 1,
  "page_size": 100,
  "total_available": 1
}
```

### List projects

List the projects on the Tableau site, optionally filtered by name, owner or parent project.

**Inputs**

- Filter on (`filter_field`, text): Which project field to filter on. Leave the field empty to list everything. Choosing a field means the value below is required. One of: `createdAt` (Created at (createdAt)), `name` (Name (name)), `ownerDomain` (Owner domain (ownerDomain)), `ownerEmail` (Owner email (ownerEmail)), `ownerName` (Owner name (ownerName)), `parentProjectId` (Parent project id (parentProjectId)), `topLevelProject` (Is a top-level project (topLevelProject)), `updatedAt` (Updated at (updatedAt)).
- Filter operator (`filter_operator`, text): How the filter value is compared. Ignored when no field is chosen. Which operators a field accepts depends on the field: name and the other text fields take 'is exactly', date fields such as Created at take the before/after comparisons, and Tags takes 'is any of'. Tableau refuses a pairing it does not support, and the error says so. One of: `eq` (is exactly), `cieq` (is exactly, ignoring case), `gt` (is after / greater than), `gte` (is at or after / greater than or equal to), `lt` (is before / less than), `lte` (is at or before / less than or equal to), `has` (contains), `in` (is any of - a bracketed list, [alpha,beta]), `like` (matches a pattern using * as the wildcard). Default: `eq`.
- Filter value (`filter_value`, text): What to compare against. Dates are ISO-8601 (2026-01-31T00:00:00Z); a list for the 'is any of' operator is bracketed, like [alpha,beta].
- Sort by (`sort_field`, text): Which project field to sort on. Leave empty for Tableau's order. Not every field that can be filtered can also be sorted on - Name works everywhere. One of: `createdAt` (Created at (createdAt)), `name` (Name (name)), `ownerDomain` (Owner domain (ownerDomain)), `ownerEmail` (Owner email (ownerEmail)), `ownerName` (Owner name (ownerName)), `parentProjectId` (Parent project id (parentProjectId)), `topLevelProject` (Is a top-level project (topLevelProject)), `updatedAt` (Updated at (updatedAt)).
- Sort direction (`sort_direction`, text): Which way to sort. Ignored when no sort field is chosen. One of: `asc` (Ascending), `desc` (Descending). Default: `asc`.
- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `page_number` (number)
- `page_size` (number)
- `projects` (list)
- `total_available` (number)

**Example output**

```json
{
  "count": 1,
  "page_number": 1,
  "page_size": 100,
  "projects": [
    {
      "content_permissions": "ManagedByOwner",
      "controlling_permissions_project_id": null,
      "created_at": "2026-01-04T09:00:00Z",
      "description": "The default project that was automatically created by Tableau.",
      "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
      "name": "Default",
      "owner": {
        "email": "ada@example.com",
        "full_name": "Ada Lovelace",
        "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
        "name": "ada@example.com"
      },
      "parent_project_id": null,
      "top_level_project": true,
      "updated_at": "2026-01-04T09:00:00Z",
      "writeable": true
    }
  ],
  "total_available": 1
}
```

### List users

List the users on the Tableau site with their site roles. Needs a Site Administrator role.

**Inputs**

- Filter on (`filter_field`, text): Which user field to filter on. Leave the field empty to list everything. Choosing a field means the value below is required. One of: `domainName` (Domain name (domainName)), `friendlyName` (Friendly name (friendlyName)), `isLocal` (Is a local user (isLocal)), `lastLogin` (Last login (lastLogin)), `luid` (User id (luid)), `name` (Name (name)), `siteRole` (Site role (siteRole)).
- Filter operator (`filter_operator`, text): How the filter value is compared. Ignored when no field is chosen. Which operators a field accepts depends on the field: name and the other text fields take 'is exactly', date fields such as Created at take the before/after comparisons, and Tags takes 'is any of'. Tableau refuses a pairing it does not support, and the error says so. One of: `eq` (is exactly), `cieq` (is exactly, ignoring case), `gt` (is after / greater than), `gte` (is at or after / greater than or equal to), `lt` (is before / less than), `lte` (is at or before / less than or equal to), `has` (contains), `in` (is any of - a bracketed list, [alpha,beta]), `like` (matches a pattern using * as the wildcard). Default: `eq`.
- Filter value (`filter_value`, text): What to compare against. Dates are ISO-8601 (2026-01-31T00:00:00Z); a list for the 'is any of' operator is bracketed, like [alpha,beta].
- Sort by (`sort_field`, text): Which user field to sort on. Leave empty for Tableau's order. One of: `domainName` (Domain name (domainName)), `friendlyName` (Friendly name (friendlyName)), `isLocal` (Is a local user (isLocal)), `lastLogin` (Last login (lastLogin)), `luid` (User id (luid)), `name` (Name (name)), `siteRole` (Site role (siteRole)).
- Sort direction (`sort_direction`, text): Which way to sort. Ignored when no sort field is chosen. One of: `asc` (Ascending), `desc` (Descending). Default: `asc`.
- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `page_number` (number)
- `page_size` (number)
- `total_available` (number)
- `users` (list)

**Example output**

```json
{
  "count": 1,
  "page_number": 1,
  "page_size": 100,
  "total_available": 1,
  "users": [
    {
      "auth_setting": "ServerDefault",
      "domain_name": "local",
      "email": "ada@example.com",
      "full_name": "Ada Lovelace",
      "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
      "language": "en",
      "last_login": "2026-09-05T09:12:00Z",
      "locale": "en_GB",
      "name": "ada@example.com",
      "site_role": "SiteAdministratorCreator"
    }
  ]
}
```

### List views

List every view on the Tableau site, across all workbooks, optionally filtered by workbook, project or name.

**Inputs**

- Filter on (`filter_field`, text): Which view field to filter on. Leave the field empty to list everything. Choosing a field means the value below is required. One of: `caption` (Caption (caption)), `contentUrl` (Content URL (contentUrl)), `createdAt` (Created at (createdAt)), `favoritesTotal` (Times favourited (favoritesTotal)), `fields` (Fields used (fields)), `hitsTotal` (Total views (hitsTotal)), `name` (Name (name)), `ownerDomain` (Owner domain (ownerDomain)), `ownerEmail` (Owner email (ownerEmail)), `ownerName` (Owner name (ownerName)), and 9 more.
- Filter operator (`filter_operator`, text): How the filter value is compared. Ignored when no field is chosen. Which operators a field accepts depends on the field: name and the other text fields take 'is exactly', date fields such as Created at take the before/after comparisons, and Tags takes 'is any of'. Tableau refuses a pairing it does not support, and the error says so. One of: `eq` (is exactly), `cieq` (is exactly, ignoring case), `gt` (is after / greater than), `gte` (is at or after / greater than or equal to), `lt` (is before / less than), `lte` (is at or before / less than or equal to), `has` (contains), `in` (is any of - a bracketed list, [alpha,beta]), `like` (matches a pattern using * as the wildcard). Default: `eq`.
- Filter value (`filter_value`, text): What to compare against. Dates are ISO-8601 (2026-01-31T00:00:00Z); a list for the 'is any of' operator is bracketed, like [alpha,beta].
- Sort by (`sort_field`, text): Which view field to sort on. Leave empty for Tableau's order. One of: `caption` (Caption (caption)), `contentUrl` (Content URL (contentUrl)), `createdAt` (Created at (createdAt)), `favoritesTotal` (Times favourited (favoritesTotal)), `fields` (Fields used (fields)), `hitsTotal` (Total views (hitsTotal)), `name` (Name (name)), `ownerDomain` (Owner domain (ownerDomain)), `ownerEmail` (Owner email (ownerEmail)), `ownerName` (Owner name (ownerName)), and 9 more.
- Sort direction (`sort_direction`, text): Which way to sort. Ignored when no sort field is chosen. One of: `asc` (Ascending), `desc` (Descending). Default: `asc`.
- Include view counts (`include_usage_statistics`, true/false): Also return how many times each view has been opened. Tableau leaves this out unless it is asked for, because it costs an extra lookup. Default: `false`.
- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `page_number` (number)
- `page_size` (number)
- `total_available` (number)
- `views` (list)

**Example output**

```json
{
  "count": 1,
  "page_number": 1,
  "page_size": 100,
  "total_available": 1,
  "views": [
    {
      "content_url": "Superstore/sheets/Overview",
      "created_at": "2026-02-11T08:15:00Z",
      "id": "2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
      "name": "Overview",
      "owner": {
        "email": "ada@example.com",
        "full_name": "Ada Lovelace",
        "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
        "name": "ada@example.com"
      },
      "project": {
        "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
        "name": "Default"
      },
      "tags": [],
      "total_view_count": 412,
      "updated_at": "2026-08-30T16:02:00Z",
      "view_url_name": "Overview",
      "workbook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e"
    }
  ]
}
```

### List workbooks

List the workbooks on the Tableau site, optionally filtered by project, owner, name or tag.

**Inputs**

- Filter on (`filter_field`, text): Which workbook field to filter on. Leave the field empty to list everything. Choosing a field means the value below is required. One of: `contentUrl` (Content URL (contentUrl)), `createdAt` (Created at (createdAt)), `displayTabs` (Shows tabs (displayTabs)), `favoritesTotal` (Times favourited (favoritesTotal)), `hasAlerts` (Has alerts (hasAlerts)), `hasExtracts` (Has extracts (hasExtracts)), `name` (Name (name)), `ownerDomain` (Owner domain (ownerDomain)), `ownerEmail` (Owner email (ownerEmail)), `ownerName` (Owner name (ownerName)), and 6 more.
- Filter operator (`filter_operator`, text): How the filter value is compared. Ignored when no field is chosen. Which operators a field accepts depends on the field: name and the other text fields take 'is exactly', date fields such as Created at take the before/after comparisons, and Tags takes 'is any of'. Tableau refuses a pairing it does not support, and the error says so. One of: `eq` (is exactly), `cieq` (is exactly, ignoring case), `gt` (is after / greater than), `gte` (is at or after / greater than or equal to), `lt` (is before / less than), `lte` (is at or before / less than or equal to), `has` (contains), `in` (is any of - a bracketed list, [alpha,beta]), `like` (matches a pattern using * as the wildcard). Default: `eq`.
- Filter value (`filter_value`, text): What to compare against. Dates are ISO-8601 (2026-01-31T00:00:00Z); a list for the 'is any of' operator is bracketed, like [alpha,beta].
- Sort by (`sort_field`, text): Which workbook field to sort on. Leave empty for Tableau's order. One of: `contentUrl` (Content URL (contentUrl)), `createdAt` (Created at (createdAt)), `displayTabs` (Shows tabs (displayTabs)), `favoritesTotal` (Times favourited (favoritesTotal)), `hasAlerts` (Has alerts (hasAlerts)), `hasExtracts` (Has extracts (hasExtracts)), `name` (Name (name)), `ownerDomain` (Owner domain (ownerDomain)), `ownerEmail` (Owner email (ownerEmail)), `ownerName` (Owner name (ownerName)), and 6 more.
- Sort direction (`sort_direction`, text): Which way to sort. Ignored when no sort field is chosen. One of: `asc` (Ascending), `desc` (Descending). Default: `asc`.
- Results per page (`page_size`, number): How many results to return, between 1 and 1000. Tableau's own default is 100. From 1 to 1000. Default: `100`.
- Page (`page_number`, number): Which page to return, starting at 1. Compare the result's count with its total available to know whether there is another one. At least 1. Default: `1`.

**Outputs**

- `count` (number)
- `page_number` (number)
- `page_size` (number)
- `total_available` (number)
- `workbooks` (list)

**Example output**

```json
{
  "count": 1,
  "page_number": 1,
  "page_size": 100,
  "total_available": 1,
  "workbooks": [
    {
      "content_url": "Superstore",
      "created_at": "2026-02-11T08:15:00Z",
      "default_view_id": "2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
      "description": "",
      "id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
      "name": "Superstore",
      "owner": {
        "email": "ada@example.com",
        "full_name": "Ada Lovelace",
        "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
        "name": "ada@example.com"
      },
      "project": {
        "id": "1f2f3e4e-5d6d-7c8c-9b0b-1a2a3f4f5e6e",
        "name": "Default"
      },
      "show_tabs": true,
      "size": 2,
      "tags": [
        "sales"
      ],
      "updated_at": "2026-08-30T16:02:00Z",
      "webpage_url": "https://10ax.online.tableau.com/#/site/acme/workbooks/1234"
    }
  ]
}
```

### Refresh a data source extract

Rebuild a published data source's extract and wait for it to finish. Tableau only *queues* a refresh when asked, so this follows the job to completion and fails if the rebuild failed - a refresh that cannot reach the underlying data still starts cleanly and reports the failure only on the job afterwards. The data source has to have an extract; a live connection queries its source directly and has nothing to rebuild.

**Inputs**

- Data source id (`datasource_id`, text, required): The published data source's Tableau id (a GUID). List data sources returns it.
- Wait for the refresh to finish (`wait_for_completion`, true/false): Keep the step running until Tableau reports the extract rebuilt, and fail if it did not. Turn this off only if you want to start the refresh and follow it yourself with Get a job - Tableau accepts the request and answers with a queued job either way, so with this off the step cannot tell you whether the rebuild worked. Default: `true`.
- Give up waiting after (seconds) (`timeout_seconds`, number): How long to wait for the rebuild before returning. A big extract can take longer than this; if it does, the result comes back with 'timed_out' set and the refresh carries on in Tableau - follow it with Get a job. From 1 to 3600. Default: `300`.

**Outputs**

- `completed_at` (text)
- `created_at` (text)
- `finish_code` (text)
- `id` (text)
- `mode` (text)
- `notes` (list)
- `progress` (number)
- `started_at` (text)
- `status_notes` (list)
- `timed_out` (true/false)
- `type` (text)
- `updated_at` (text)

**Example output**

```json
{
  "completed_at": "2026-09-05T10:31:22Z",
  "created_at": "2026-09-05T10:30:00Z",
  "finish_code": "0",
  "id": "5e6f7a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
  "mode": "Asynchronous",
  "notes": [
    "Finished refresh of extracts."
  ],
  "progress": 100,
  "started_at": "2026-09-05T10:30:04Z",
  "status_notes": [],
  "timed_out": false,
  "type": "RefreshExtract",
  "updated_at": "2026-09-05T10:31:22Z"
}
```

### Remove a workbook tag

Remove a single tag from a workbook.

**Inputs**

- Workbook id (`workbook_id`, text, required): The workbook's Tableau id (a GUID). List workbooks returns it, and it also appears in the address bar when you open the workbook.
- Tag (`tag`, text, required): The tag to remove, spelled exactly as it appears.

**Outputs**

- `deleted` (true/false)
- `tag` (text)
- `workbook_id` (text)

**Example output**

```json
{
  "deleted": true,
  "tag": "reviewed",
  "workbook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e"
}
```

### Tag a workbook

Add one or more tags to a workbook. Tags it already has are kept, and the result lists the full set.

**Inputs**

- Workbook id (`workbook_id`, text, required): The workbook's Tableau id (a GUID). List workbooks returns it, and it also appears in the address bar when you open the workbook.
- Tags (`tags`, list, required): The tags to add. Give a list, or separate them with commas.

**Outputs**

- `count` (number)
- `tags` (list)
- `workbook_id` (text)

**Example output**

```json
{
  "count": 2,
  "tags": [
    "sales",
    "reviewed"
  ],
  "workbook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e"
}
```

### Update a project

Rename a project, change its description, move it under another project, or change how its permissions are managed. Anything left empty keeps the value it already has.

**Inputs**

- Project (`project_id`, text, required): Which project to act on. Pick one, or paste the id of a project made earlier in this workflow.
- New name (`name`, text): Rename the project. Leave empty to keep its name.
- New description (`description`, text): Replace the project's description. Leave empty to keep the current one.
- Parent project (`parent_project_id`, text): Nest the project inside this one. Leave empty to create it at the top level. Creating a top-level project usually needs a Site Administrator role.
- Permissions are (`content_permissions`, text): Whether each item in the project keeps its own permissions or inherits the project's. Leave empty to keep Tableau's default. One of: `ManagedByOwner` (Managed by owner - each item's owner sets its permissions), `LockedToProject` (Locked to project - the project's permissions apply to everything in it), `LockedToProjectWithoutNested` (Locked to project, nested projects excluded).

**Outputs**

- `content_permissions` (text)
- `controlling_permissions_project_id` (text)
- `created_at` (text)
- `description` (text)
- `id` (text)
- `name` (text)
- `owner` (object)
- `parent_project_id` (text)
- `top_level_project` (true/false)
- `updated_at` (text)
- `writeable` (true/false)

**Example output**

```json
{
  "content_permissions": "LockedToProject",
  "controlling_permissions_project_id": "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d",
  "created_at": "2026-09-05T10:30:00Z",
  "description": "Dashboards for the quarterly review.",
  "id": "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d",
  "name": "Quarterly reporting (FY26)",
  "owner": {
    "email": "ada@example.com",
    "full_name": "Ada Lovelace",
    "id": "abc12e4e-5d6d-7c8c-9b0b-1a2a3f4f5e90",
    "name": "ada@example.com"
  },
  "parent_project_id": null,
  "top_level_project": true,
  "updated_at": "2026-09-05T10:45:00Z",
  "writeable": true
}
```
