# Looker

You can use the Looker integration to query Looker models and view directly from your Stack AI workflows.

***

## Connect to Looker

### Prerequisites

* A running Looker instance (Looker Core, Looker (Google Cloud core), or self-hosted)
* Admin access, or permission to manage API credentials for your user account
* Your Looker instance must be network-accessible from Stack AI (not restricted to a private VPN)

### Step 1: Generate API Credentials in Looker

Looker API access uses a per-user **Client ID** and **Client Secret**, not a shared OAuth app. You generate these in the Looker Admin panel.

**If you are a Looker Admin**

1. In Looker, go to **Admin > Users**.
2. Click on the user you want to use for the API connection (create a dedicated service user if preferred).
3. Scroll to the **API Keys** section and click **Edit Keys**.
4. Click **New API3 Key**.
5. Copy both the **Client ID** and **Client Secret.** Note: the secret is only shown once.

**If you are generating keys for your own account**

1. Go to your Looker account settings (click your avatar > **Account**).
2. Scroll to the **API Keys** section.
3. Click **New API3 Key** and copy the **Client ID** and **Client Secret**.

{% hint style="info" %}
For production use, create a dedicated Looker service account user rather than tying the API key to a personal account. If that user is deactivated, the connection will break.
{% endhint %}

### Step 2: Find Your Looker Base URL

Your Base URL is the root address of your Looker instance, without any path suffix.

<table><thead><tr><th width="216.21875">Looker Deployment Type</th><th>Base URL Format</th><th>Example</th></tr></thead><tbody><tr><td>Looker (Google Cloud core)</td><td><code>https://&#x3C;instance>.looker.com</code></td><td><code>https://mycompany.looker.com</code></td></tr><tr><td>Looker hosted on GCP</td><td><code>https://&#x3C;instance>.cloud.looker.com</code></td><td><code>https://mycompany.cloud.looker.com</code></td></tr><tr><td>Self-hosted</td><td>Your custom domain</td><td><code>https://looker.mycompany.com</code></td></tr></tbody></table>

Stack AI appends `/api/4.0` to this URL for all API calls. Do not include a trailing slash or path.

### Step 3: Connect in Stack AI

In the Stack AI connector setup, provide the following three fields:

<table><thead><tr><th width="148.80078125">Field</th><th width="579.79296875">Description</th></tr></thead><tbody><tr><td><strong>Base URL</strong></td><td>Root URL of your Looker instance</td></tr><tr><td><strong>Client ID</strong></td><td>API key Client ID from your Looker user settings</td></tr><tr><td><strong>Client Secret</strong></td><td>API key Client Secret (treated as a password)</td></tr></tbody></table>

Click **Connect**. A green status indicator confirms the connection is healthy.

### Looker User Permissions Required

The Looker user whose API key you use must have sufficient permissions to run queries. Looker's permission model is role-based.

<table><thead><tr><th width="265.03125">Operation</th><th>Required Looker Permission</th></tr></thead><tbody><tr><td>Authenticate (connect)</td><td>Any valid API key — no special role needed</td></tr><tr><td>Health check (<code>/api/4.0/user</code>)</td><td>Any active user account</td></tr><tr><td>Create and run queries</td><td><code>access_data</code> + <code>explore</code> on the relevant models</td></tr><tr><td>View query results</td><td><code>see_looks</code> or direct model access via model sets</td></tr></tbody></table>

The minimum role for querying data is one that includes **`access_data`** and **`explore`** on the models you want to query. Your Looker admin configures this through **Admin > Roles**.

### Troubleshooting

**401 Unauthorized on connect**

* Double-check that the Client ID and Client Secret are copied correctly with no extra whitespace.
* Confirm the user account is active and not locked out.
* Verify the Base URL is correct and reachable. Try opening `{base_url}/api/4.0/login` in a browser.

**403 Forbidden when querying**

* The connected user does not have `access_data` or `explore` permission on the model/view you are querying. Ask your Looker admin to assign the appropriate role.

**Connection times out**

* Looker may be behind a firewall or VPN that blocks inbound requests from Stack AI. Ensure Stack AI's IP range is allowlisted in your network configuration.

**Token expired mid-workflow**

* Stack AI automatically refreshes the token 60 seconds before expiry. If you see auth errors mid-run, it is likely a network issue preventing the refresh call from completing.

***

## Available Actions

### 1. Query Looker

Run a query against a Looker model and view, and return the results as structured data. This is the primary way to pull data out of Looker into a Stack AI workflow.

**Input Parameters**

<table><thead><tr><th width="147.296875">Parameter</th><th width="117.99609375">Required</th><th width="134.87109375">Type</th><th>Description</th></tr></thead><tbody><tr><td><strong>Model Name</strong></td><td>Yes</td><td>String</td><td>The name of the Looker model to query (e.g. <code>ecommerce</code>, <code>thelook</code>)</td></tr><tr><td><strong>View Name</strong></td><td>Yes</td><td>String</td><td>The name of the view within the model (e.g. <code>orders</code>, <code>users</code>)</td></tr><tr><td><strong>Fields</strong></td><td>Yes</td><td>String array</td><td>List of fields to return, in <code>view.field_name</code> format (e.g. <code>["orders.count", "orders.created_date"]</code>)</td></tr><tr><td><strong>Filters</strong></td><td>No</td><td>Key-value pairs</td><td> Field-level filters to apply (e.g. <code>{"orders.status": "complete", "orders.created_date": "7 days"}</code>)</td></tr><tr><td><strong>Limit</strong></td><td>No</td><td>Number</td><td>Maximum number of rows to return</td></tr></tbody></table>

**Finding model and view names:** In Looker, open the **Explore** menu. The top-level menu item is the model name; the section within the explore is the view name. Field names follow the pattern `view_name.field_name`.

**Output Parameters**

| Parameter          | Type             | Description                                                                                                   |
| ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------- |
| **Query Results**  | Array of objects | Each object is one row of results, with field names as keys                                                   |
| **Field Metadata** | Array of objects | Metadata for each field in the result: `name`, `label`, and `type` (dimension, measure, or table calculation) |
| **Row Count**      | Number           | Total number of rows returned                                                                                 |

**Example**

To get the count of completed orders grouped by creation date for the last 7 days:

* **Model Name:** `ecommerce`
* **View Name:** `orders`
* **Fields:** `["orders.count", "orders.created_date"]`
* **Filters:** `{"orders.status": "complete", "orders.created_date": "7 days"}`
* **Limit:** `500`
