Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Looker

Connect Bolt.new to Looker's REST API by creating API credentials in the Looker Admin panel, exchanging your client_id and client_secret for an access token via an API route, and then running Looks, dashboards, and inline queries server-side. Embed Looker dashboards using SSO embed URLs generated on the server. Looker requires a Google Cloud or Looker-licensed instance — it is not a free service.

What you'll learn

  • How to create Looker API credentials (client_id and client_secret) in the Looker Admin panel
  • How to authenticate with Looker's REST API using the OAuth 2.0 client credentials flow in a Next.js API route
  • How to run Looks and inline queries via the Looker API and display results in a Bolt.new dashboard
  • How to generate Looker SSO embed URLs to embed full interactive dashboards in an iframe
  • How to cache Looker API responses to avoid rate limits and improve performance
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read30 minutesAnalyticsApril 2026RapidDev Engineering Team
TL;DR

Connect Bolt.new to Looker's REST API by creating API credentials in the Looker Admin panel, exchanging your client_id and client_secret for an access token via an API route, and then running Looks, dashboards, and inline queries server-side. Embed Looker dashboards using SSO embed URLs generated on the server. Looker requires a Google Cloud or Looker-licensed instance — it is not a free service.

Embed Looker Analytics and Run API Queries from Bolt.new

Looker is Google Cloud's flagship business intelligence platform, built around LookML — a SQL-based data modeling language that lets data teams define metrics, dimensions, and relationships once and reuse them across reports. Looker's REST API is extensive: you can run any Explore, Look, or Dashboard programmatically, retrieve results as JSON, CSV, or Excel, manage users and groups, and generate signed SSO embed URLs that let you embed Looker's full interactive UI inside your own application. This makes Looker one of the most API-capable BI tools available, despite being an enterprise product. The query that surfaces users to this page — 'authorization: token looker api' — shows that developers are actively attempting the integration and running into the auth pattern.

The key technical detail to understand is Looker's auth flow. Unlike APIs that issue static API keys, Looker uses OAuth 2.0 client credentials: you POST your client_id and client_secret to Looker's /login endpoint, receive a short-lived access_token (valid for one hour), and include that token as a Bearer token in subsequent requests. Because your client_secret must never be exposed in the browser, every Looker API call must happen in a server-side context — a Next.js API route in your Bolt.new app. This API route fetches the token, makes the Looker API call, and returns the results to your frontend component. Caching the access token (until it expires) saves a round-trip on every request.

Looker is not a free or self-hosted product available to the general public. You need either a Looker instance on Google Cloud (billed through GCP), a Looker-licensed deployment through your organization, or access via a company that already uses Looker. If your organization uses Looker, your admin can provide API credentials. This tutorial assumes you have access to a Looker instance and focuses on the integration pattern.

Integration method

Bolt Chat + API Route

Looker's REST API uses OAuth 2.0 client credentials — you exchange a client_id and client_secret for a short-lived access token, then use that token to run queries, fetch Look results, and generate SSO embed URLs. Because the client_secret must never be exposed to the browser, all Looker API calls happen in a server-side API route in your Bolt.new app. The frontend fetches data from your own API route, which proxies requests to Looker. SSO embed URLs for dashboard embedding are also generated server-side and passed to an iframe in the frontend.

Prerequisites

  • Access to a Looker instance (Google Cloud Looker, Looker-licensed deployment, or organizational Looker access)
  • Admin access to the Looker instance to create API credentials (or have an admin create them for you)
  • A Bolt.new project using Next.js (required for server-side API routes that keep the client_secret secure)
  • Your Looker instance's base URL (e.g., https://yourcompany.looker.com) and API version (usually 4.0)
  • For SSO embedding: the Looker embed secret, found in Admin → Platform → Embed in the Looker UI

Step-by-step guide

1

Create Looker API Credentials

Looker API access requires API credentials tied to a Looker user account — either your own account or a dedicated service account. Log in to your Looker instance and navigate to Admin → Users (or your own profile if you are not an admin). Find the user you want to create API keys for and click 'Edit'. Scroll down to the 'API Keys' section and click 'New API Key'. Looker generates a client_id and client_secret pair. Copy both values immediately — the client_secret is shown only once and cannot be retrieved after leaving this page. If you lose it, you must generate a new key pair. The client_id is safe to identify your integration but the client_secret must be treated like a password. Store both in your .env file as LOOKER_CLIENT_ID and LOOKER_CLIENT_SECRET. Also note your Looker instance's base URL (e.g., https://yourcompany.looker.com) — you will need this for every API call. The Looker API base path is typically https://yourcompany.looker.com:19999/api/4.0 for Looker-licensed instances, or https://yourcompany.looker.com/api/4.0 for Looker on Google Cloud. If you are not a Looker admin and cannot access the Admin → Users panel, ask your Looker administrator to create an API key for you or for a dedicated service user with the permissions your app requires.

Bolt.new Prompt

I'm connecting my Next.js Bolt.new app to Looker's API. Create a .env file with placeholders: LOOKER_CLIENT_ID, LOOKER_CLIENT_SECRET, LOOKER_BASE_URL, and LOOKER_EMBED_SECRET. Create a lib/looker.ts file that exports a getLookerToken() async function. This function POSTs to ${LOOKER_BASE_URL}/api/4.0/login with client_id and client_secret as form-encoded body parameters. It returns the access_token string from the response. Cache the token in a module-level variable and only re-fetch when it expires (check the token_ttl field in the login response).

Paste this in Bolt.new chat

lib/looker.ts
1// lib/looker.ts
2let cachedToken: string | null = null;
3let tokenExpiresAt: number = 0;
4
5export async function getLookerToken(): Promise<string> {
6 // Return cached token if still valid (with 60s buffer)
7 if (cachedToken && Date.now() < tokenExpiresAt - 60_000) {
8 return cachedToken;
9 }
10
11 const baseUrl = process.env.LOOKER_BASE_URL;
12 const response = await fetch(`${baseUrl}/api/4.0/login`, {
13 method: 'POST',
14 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
15 body: new URLSearchParams({
16 client_id: process.env.LOOKER_CLIENT_ID!,
17 client_secret: process.env.LOOKER_CLIENT_SECRET!,
18 }),
19 });
20
21 if (!response.ok) {
22 throw new Error(`Looker auth failed: ${response.status} ${await response.text()}`);
23 }
24
25 const data = await response.json();
26 cachedToken = data.access_token;
27 tokenExpiresAt = Date.now() + data.token_ttl * 1000;
28 return cachedToken!;
29}

Pro tip: Caching the access_token in a module-level variable (server-side only in Next.js API routes) avoids a login round-trip on every request. The token_ttl in the login response is in seconds — typically 3600 (one hour). Subtract a 60-second buffer before expiry to avoid using a token that expires mid-request.

Expected result: The getLookerToken() function successfully authenticates with Looker and returns a valid Bearer token. The token is cached and reused until near expiry.

2

Build an API Route to Fetch Look Results

With authentication handled in lib/looker.ts, create a Next.js API route that fetches the results of a specific Looker Look (a saved query). The Looker API endpoint for running a Look is GET /looks/:look_id/run/:result_format — where result_format can be json, json_detail, csv, or xlsx. Using json returns an array of row objects where each key is a 'view_name.field_name' Looker field reference. For example, a Look on the orders model might return rows like { 'orders.count': 1500, 'orders.average_revenue': 250.00 }. Your API route fetches the token, calls the Looker run endpoint with the Bearer token, and returns the data to your frontend component. Add error handling for common Looker API errors: 404 (Look not found or permission denied), 422 (Look has an error in its definition), and 401 (token expired — clear the cache and retry). In Bolt's WebContainer during development, outbound API calls to your Looker instance work correctly as long as your Looker instance allows requests from your IP. Note that Bolt's WebContainer does not support incoming webhook connections — but Looker's API is purely outbound (your app calls Looker, not the other way around), so this limitation does not apply to this integration.

Bolt.new Prompt

Create a Next.js API route at app/api/looker/look/[lookId]/route.ts. It should GET the results of a Looker Look by calling the Looker API: GET ${LOOKER_BASE_URL}/api/4.0/looks/:lookId/run/json with Authorization: token {accessToken} header. Use the getLookerToken() function from lib/looker.ts. Return the results as JSON. Handle errors: 404 (Look not found), 401 (re-fetch token and retry once). Also create a React hook useLookData(lookId) in hooks/useLookData.ts that fetches from this API route and returns { data, loading, error }.

Paste this in Bolt.new chat

app/api/looker/look/[lookId]/route.ts
1// app/api/looker/look/[lookId]/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { getLookerToken } from '@/lib/looker';
4
5export async function GET(
6 request: NextRequest,
7 { params }: { params: { lookId: string } }
8) {
9 const { lookId } = params;
10 const baseUrl = process.env.LOOKER_BASE_URL;
11
12 try {
13 const token = await getLookerToken();
14 const response = await fetch(
15 `${baseUrl}/api/4.0/looks/${lookId}/run/json`,
16 {
17 headers: {
18 'Authorization': `token ${token}`,
19 'Content-Type': 'application/json',
20 },
21 }
22 );
23
24 if (response.status === 401) {
25 // Token expired — this shouldn't happen with caching, but handle it
26 return NextResponse.json(
27 { error: 'Looker authentication expired. Please retry.' },
28 { status: 401 }
29 );
30 }
31
32 if (!response.ok) {
33 const text = await response.text();
34 return NextResponse.json(
35 { error: `Looker API error: ${response.status}`, detail: text },
36 { status: response.status }
37 );
38 }
39
40 const data = await response.json();
41 return NextResponse.json({ data, count: data.length });
42 } catch (error) {
43 return NextResponse.json(
44 { error: 'Failed to fetch Look results' },
45 { status: 500 }
46 );
47 }
48}

Pro tip: Looker field names in API results use the format 'view_name.field_name' (e.g., 'orders.count'). When displaying this data in a React table, map the field names to human-readable column headers using a config object rather than displaying the raw Looker field references to users.

Expected result: Calling /api/looker/look/123 returns the JSON results of Looker Look #123. The data array can be passed directly to a Recharts component or displayed in a table.

3

Generate SSO Embed URLs for Dashboard Embedding

Looker's SSO embed feature lets you embed a full interactive Looker dashboard in an iframe inside your app, without requiring your users to have Looker accounts. The embed URL is cryptographically signed using your Looker embed secret — a separate credential from your API keys, found in Admin → Platform → Embed. The signing process creates a URL that includes the dashboard path, user identity parameters (external_user_id, permissions, models), an expiry timestamp, and a signature hash computed using HMAC-SHA1. Because the signature involves your embed_secret, the URL must be generated server-side — never in the browser. The signed URL is valid for a short window (typically 5 minutes) and can only be used once. Your API route generates the URL and returns it to the frontend, which sets it as the src of an iframe. The Looker documentation provides detailed pseudocode for the signing algorithm — implement it carefully, as a single field in the wrong order breaks the signature. The nonce (random string in the URL) must be unique per request to prevent replay attacks. Looker's embed URL format has specific quoting and encoding requirements — test with Looker's embed URL validator if available in your Admin panel.

Bolt.new Prompt

Create a Next.js API route at app/api/looker/embed-url/route.ts that generates a signed Looker SSO embed URL. Accept POST with body: { dashboardId, externalUserId, userDisplayName }. Use LOOKER_BASE_URL and LOOKER_EMBED_SECRET from environment variables. Implement the Looker SSO embed URL signing algorithm: build the URL with all required fields (external_user_id, permissions, models, nonce, time, session_length, force_logout_login), sign with HMAC-SHA1 using the embed secret, and return the full signed URL. The frontend will use this URL as an iframe src.

Paste this in Bolt.new chat

app/api/looker/embed-url/route.ts
1// app/api/looker/embed-url/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import * as crypto from 'crypto';
4
5function sign(stringToSign: string, secret: string): string {
6 return crypto.createHmac('sha1', secret).update(stringToSign).digest('hex');
7}
8
9export async function POST(request: NextRequest) {
10 const { dashboardId, externalUserId, userDisplayName } = await request.json();
11 const secret = process.env.LOOKER_EMBED_SECRET!;
12 const baseUrl = process.env.LOOKER_BASE_URL!;
13 const host = new URL(baseUrl).host;
14
15 const nonce = crypto.randomBytes(16).toString('hex');
16 const time = Math.floor(Date.now() / 1000);
17 const sessionLength = 3600; // 1 hour
18 const embedPath = `/embed/dashboards/${dashboardId}`;
19
20 const permissions = JSON.stringify(['access_data', 'see_looks', 'see_user_dashboards']);
21 const models = JSON.stringify(['all']); // Or specific model names
22 const userAttributes = JSON.stringify({});
23 const accessFilters = JSON.stringify({});
24
25 const stringToSign = [
26 host,
27 embedPath,
28 nonce,
29 time,
30 sessionLength,
31 externalUserId,
32 permissions,
33 models,
34 userAttributes,
35 accessFilters,
36 userDisplayName,
37 '', // group_ids
38 '', // external_group_id
39 ].join('\n');
40
41 const signature = sign(stringToSign, secret);
42
43 const params = new URLSearchParams({
44 nonce,
45 time: time.toString(),
46 session_length: sessionLength.toString(),
47 external_user_id: externalUserId,
48 permissions,
49 models,
50 user_attributes: userAttributes,
51 access_filters: accessFilters,
52 first_name: userDisplayName.split(' ')[0] || userDisplayName,
53 last_name: userDisplayName.split(' ')[1] || '',
54 force_logout_login: 'true',
55 signature,
56 });
57
58 const embedUrl = `${baseUrl}/login/embed/${encodeURIComponent(embedPath)}?${params.toString()}`;
59 return NextResponse.json({ embedUrl });
60}

Pro tip: The Looker SSO embed signing algorithm is order-sensitive — every field must appear in the exact sequence specified in Looker's documentation. If you get 'Invalid signature' errors, double-check field order, verify that your embed_secret is correct (it is different from your API client_secret), and ensure no extra whitespace is included in the string being signed.

Expected result: The API route returns a signed Looker SSO embed URL. Setting this URL as an iframe's src displays the full interactive Looker dashboard inside your Bolt.new app without requiring users to have Looker accounts.

4

Display Looker Data in Custom React Charts

Instead of embedding Looker's iframe, you may want to display Look query results in your own custom React components — giving you full control over styling, layout, and interactivity. Fetch Look data via your /api/looker/look/:lookId route, then pass the results to Recharts components. Looker returns JSON where each row is an object with field names as keys in 'view.field' format. Map these to chart-friendly data structures in your component. For a bar chart showing monthly revenue, Looker might return rows like [{ 'orders.month': '2025-01', 'orders.total_revenue': 125000 }, ...] — transform these into [{ month: 'Jan 2025', revenue: 125000 }, ...] before passing to Recharts. Build a reusable LookerChart component that accepts a lookId prop, fetches the data, and renders the appropriate chart type. Add loading skeletons and error states. For tables, use a generic DataTable component that dynamically generates columns from the Looker field names, with the option to pass a column label mapping object for human-readable headers. During development in Bolt's WebContainer, API calls to Looker work as long as your Looker instance is accessible over the internet — corporate Looker instances behind a VPN cannot be reached from the Bolt preview environment.

Bolt.new Prompt

Build a LookerBarChart component. It accepts props: lookId (string) and fieldMapping (object mapping Looker field names to display labels). It fetches data from /api/looker/look/:lookId and displays it as a Recharts BarChart. Show a loading skeleton while fetching. Show an error message if the fetch fails. The chart should be responsive (use ResponsiveContainer). Also build a LookerTable component that renders Look results in a sortable DataTable with column headers from the fieldMapping. Display both components on a /analytics page.

Paste this in Bolt.new chat

components/LookerChart.tsx
1// components/LookerChart.tsx
2import { useState, useEffect } from 'react';
3import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
4
5interface LookerBarChartProps {
6 lookId: string;
7 xField: string;
8 yField: string;
9 xLabel?: string;
10 yLabel?: string;
11}
12
13export function LookerBarChart({ lookId, xField, yField, xLabel, yLabel }: LookerBarChartProps) {
14 const [data, setData] = useState<Record<string, unknown>[]>([]);
15 const [loading, setLoading] = useState(true);
16 const [error, setError] = useState<string | null>(null);
17
18 useEffect(() => {
19 fetch(`/api/looker/look/${lookId}`)
20 .then(res => res.json())
21 .then(({ data: rawData, error }) => {
22 if (error) { setError(error); return; }
23 // Normalize Looker field names to simple keys
24 const normalized = rawData.map((row: Record<string, unknown>) => ({
25 x: row[xField],
26 y: Number(row[yField]) || 0,
27 }));
28 setData(normalized);
29 })
30 .catch(err => setError(err.message))
31 .finally(() => setLoading(false));
32 }, [lookId, xField, yField]);
33
34 if (loading) return <div className="h-64 bg-gray-100 animate-pulse rounded" />;
35 if (error) return <div className="text-red-500">Error loading chart: {error}</div>;
36
37 return (
38 <ResponsiveContainer width="100%" height={300}>
39 <BarChart data={data}>
40 <CartesianGrid strokeDasharray="3 3" />
41 <XAxis dataKey="x" label={{ value: xLabel, position: 'insideBottom', offset: -5 }} />
42 <YAxis label={{ value: yLabel, angle: -90, position: 'insideLeft' }} />
43 <Tooltip />
44 <Bar dataKey="y" fill="#3b82f6" />
45 </BarChart>
46 </ResponsiveContainer>
47 );
48}

Pro tip: Looker field names use the 'view_name.field_name' format with dots. When using these as React state keys or Recharts dataKey values, replace dots with underscores or map them to friendly names upfront, since some JavaScript operations handle dots in keys unexpectedly.

Expected result: Looker Look data displays in a Recharts bar chart and sortable table inside your Bolt.new app. The data comes from Looker's governed data model but is rendered in your custom UI components.

Common use cases

Embedded Analytics Dashboard

Embed a Looker dashboard directly inside your Bolt.new app using SSO embed URLs. Your users see a full interactive Looker dashboard — with filters, drilldowns, and visualizations — inside an iframe in your app, without being redirected to Looker's own UI. The embed URL is signed server-side with your Looker embed secret so users don't need Looker accounts.

Bolt.new Prompt

Build an embedded analytics page in my app that shows a Looker dashboard in an iframe. Create a Next.js API route at app/api/looker/embed-url/route.ts that generates a signed Looker SSO embed URL using the embed_secret from environment variables. The frontend page fetches this URL and renders it in an iframe that takes up the full content area. Add a loading skeleton while the URL is being fetched.

Copy this prompt to try it in Bolt.new

Custom KPI Dashboard from Looker Data

Fetch data from a specific Looker Look (saved query) and display it in your own custom React charts and tables rather than Looker's iframe. This approach gives you complete control over the presentation while using Looker as the governed data source. Query results come back as JSON arrays.

Bolt.new Prompt

Build a KPI dashboard that fetches data from Looker. Create a Next.js API route app/api/looker/look/[lookId]/route.ts that authenticates with Looker using client_id and client_secret from environment variables, runs the Look with the given ID using the /looks/:look_id/run/json endpoint, and returns the results. Display the results as a responsive table with sorting, and as a bar chart using Recharts. Cache the Looker token in memory to avoid re-authenticating on every request.

Copy this prompt to try it in Bolt.new

Inline Query Runner

Run an ad-hoc Looker inline query from your app — specify the model, view, dimensions, measures, and filters, and get back JSON results without needing a pre-saved Look. Useful for building dynamic report builders or allowing users to select their own dimensions and metrics.

Bolt.new Prompt

Build a query builder that sends inline queries to Looker. Create a Next.js API route app/api/looker/query/route.ts that accepts POST with a body containing model, view, fields (dimensions and measures), and filters. Authenticate with Looker, create a query using the /queries endpoint, run it with /queries/:query_id/run/json, and return the results. Build a simple UI where users select a model and fields from a dropdown, click 'Run Query', and see results in a table.

Copy this prompt to try it in Bolt.new

Troubleshooting

Looker login returns 401 Unauthorized — authentication fails

Cause: The client_id or client_secret is incorrect, the API key was deleted in the Looker Admin panel, or the user account associated with the key has been deactivated.

Solution: Verify the LOOKER_CLIENT_ID and LOOKER_CLIENT_SECRET values in your .env file match exactly what Looker showed when you created the key. Go to Looker Admin → Users → find the user → API Keys section to confirm the key exists. If the key was deleted, create a new one and update your .env file.

typescript
1// Test your Looker credentials directly:
2const resp = await fetch('https://yourcompany.looker.com/api/4.0/login', {
3 method: 'POST',
4 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
5 body: `client_id=${process.env.LOOKER_CLIENT_ID}&client_secret=${process.env.LOOKER_CLIENT_SECRET}`,
6});
7console.log(resp.status, await resp.json());

SSO embed URL shows 'Invalid signature' in the Looker iframe

Cause: The signing algorithm has an error — typically wrong field order, incorrect embed_secret (not the same as the API client_secret), extra whitespace, or incorrect URL encoding.

Solution: Verify you are using LOOKER_EMBED_SECRET, not LOOKER_CLIENT_SECRET — these are different credentials found in different places in the Admin panel. Check Looker's documentation for the exact field order in the string-to-sign. Remove any trailing whitespace from each field. Use Looker's built-in embed URL validator in Admin → Platform → Embed if available on your instance.

Looker API calls work locally in Bolt but fail after deploying to Netlify

Cause: The LOOKER_CLIENT_ID, LOOKER_CLIENT_SECRET, LOOKER_BASE_URL, and LOOKER_EMBED_SECRET environment variables were set in the .env file but not added to Netlify's environment variables.

Solution: In Netlify's dashboard, go to Site Configuration → Environment Variables and add all four Looker environment variables. The .env file is not deployed to Netlify — production environment variables must be set in the hosting dashboard. Trigger a redeploy after adding the variables.

Look results return fields with 'null' values where data is expected

Cause: The Looker Look's query returns NULL for some rows (e.g., empty dimensions), or the user's API credentials do not have access to the underlying data model or database connection.

Solution: In the Looker UI, run the Look manually with the same API user's permissions to verify the data returns correctly. Check that the API key user has the 'access_data' permission on the relevant model. For null numeric values, use Number(row[field]) || 0 when mapping data to chart-friendly formats.

typescript
1// Safe field extraction from Looker results
2const normalized = rawData.map((row) => ({
3 label: String(row[dimensionField] ?? 'Unknown'),
4 value: Number(row[measureField]) || 0,
5}));

Best practices

  • Cache the Looker access token in a server-side module variable until it expires — re-authenticating on every API call wastes 200-400ms per request
  • Never expose LOOKER_CLIENT_SECRET or LOOKER_EMBED_SECRET to the browser — all Looker API calls must happen in Next.js API routes
  • Use a dedicated service account for Looker API access with only the permissions your app needs — not your personal admin account
  • During development in Bolt's WebContainer, Looker API calls work as long as your Looker instance is publicly accessible — corporate VPN-protected Looker instances cannot be reached from the Bolt preview
  • Map Looker's 'view_name.field_name' keys to human-readable labels in a config object — never display raw Looker field references to end users
  • Set cache headers on your /api/looker routes for dashboard data that does not change frequently — Looker queries can be slow (1-5 seconds for complex models)
  • Test SSO embed URLs with a short session_length (300 seconds) during development to quickly identify expiry issues without waiting an hour

Alternatives

Frequently asked questions

How do I authenticate with the Looker API from a Bolt.new app?

Use the OAuth 2.0 client credentials flow: POST your client_id and client_secret (as form-encoded body parameters) to /api/4.0/login on your Looker instance URL. The response includes an access_token valid for one hour. Include this token as 'Authorization: token {access_token}' in all subsequent API requests. Because the client_secret must be kept private, do all of this in a Next.js API route — never in browser-side code.

Does Looker work with Bolt's WebContainer during development?

Yes, as long as your Looker instance is publicly accessible over the internet. Bolt's WebContainer can make outbound HTTP calls to Looker's API, and your API route code runs server-side in Next.js. The limitation is on incoming webhooks — Bolt's WebContainer cannot receive incoming connections. Looker's integration is entirely outbound (your app calls Looker), so the WebContainer limitation does not affect this integration.

What permissions does the Looker API user need?

For running Looks and inline queries, the API user needs the 'access_data' and 'see_looks' permissions on the relevant models. For SSO embedding, the user generating embed URLs needs the 'embed_browse_spaces' permission or admin access. For managing users and groups via API, admin permissions are required. Create a dedicated service user with only the permissions your app needs.

What is the difference between Looker's client_secret and embed_secret?

These are two completely separate credentials. The client_id and client_secret are API key credentials used to authenticate REST API requests — found in Admin → Users → API Keys. The embed_secret is a separate string used exclusively for signing SSO embed URLs — found in Admin → Platform → Embed. Using the client_secret to sign embed URLs will always result in 'Invalid signature' errors.

Can I use Looker without a Google Cloud account?

Looker is available in two forms: Looker (Google Cloud core), which is a SaaS product on Google Cloud, and Looker-licensed (the original standalone product). Both require a paid license — there is no free tier or trial that provides API access. If your organization already has a Looker instance, ask your Looker administrator to create API credentials for you.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.