Skip to main content

TypeScript API Client

Glean's TypeScript API client provides full type safety for integrating Glean's search and AI capabilities into web applications and Node.js services.

@gleanwork/api-client

Official TypeScript/JavaScript client for Glean's Client API

Installation

npm install @gleanwork/api-client

Quick Start

import { Glean } from "@gleanwork/api-client";

const client = new Glean({
apiToken: process.env.GLEAN_API_TOKEN,
instance: process.env.GLEAN_INSTANCE,
});

const result = await client.client.chat.create({
messages: [{
fragments: [{ text: "What are our company values?" }]
}]
});

Core Features

Chat API

// Simple chat
const response = await client.client.chat.create({
messages: [{ fragments: [{ text: "Explain our Q4 strategy" }] }]
});

// Streaming responses
const stream = client.client.chat.stream({
messages: [{ fragments: [{ text: "What are our priorities?" }] }]
});

for await (const chunk of stream) {
console.log(chunk.text);
}

Search API

const results = await client.client.search.search({
query: "quarterly business review",
pageSize: 10
});

results.results?.forEach(result => {
console.log(`Title: ${result.title}`);
console.log(`URL: ${result.url}`);
});

Framework Integrations

Next.js API Route

// app/api/chat/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { Glean } from '@gleanwork/api-client';

export async function POST(request: NextRequest) {
const { message } = await request.json();

const client = new Glean({
apiToken: process.env.GLEAN_API_TOKEN!,
instance: process.env.GLEAN_INSTANCE!,
});

const response = await client.client.chat.create({
messages: [{ fragments: [{ text: message }] }]
});

return NextResponse.json({ response: response.text });
}

React Component

import React, { useState } from 'react';
import { Glean } from '@gleanwork/api-client';

export function ChatComponent({ apiToken, instance }) {
const [input, setInput] = useState('');
const [response, setResponse] = useState('');

const client = new Glean({ apiToken, instance });

const handleSubmit = async (e) => {
e.preventDefault();
const result = await client.client.chat.create({
messages: [{ fragments: [{ text: input }] }]
});
setResponse(result.text || '');
};

return (
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Ask a question..."
/>
<button type="submit">Send</button>
{response && <div>{response}</div>}
</form>
);
}

Express.js

import express from 'express';
import { Glean } from '@gleanwork/api-client';

const app = express();
app.use(express.json());

const client = new Glean({
apiToken: process.env.GLEAN_API_TOKEN!,
instance: process.env.GLEAN_INSTANCE!,
});

app.post('/api/chat', async (req, res) => {
const { message } = req.body;

const response = await client.client.chat.create({
messages: [{ fragments: [{ text: message }] }]
});

res.json({ response: response.text });
});

Authentication

const client = new Glean({
apiToken: "your-user-token",
instance: "your-company"
});

Global Tokens with ActAs

const response = await client.client.chat.create({
messages: [{ fragments: [{ text: "Hello" }] }]
}, {
headers: { "X-Glean-ActAs": "user@company.com" }
});

OAuth Authentication

OAuth allows you to use access tokens from your identity provider (Google, Azure, Okta, etc.) instead of Glean-issued tokens.

Prerequisites

OAuth requests require these headers:

HeaderValue
AuthorizationBearer <oauth_access_token>
X-Glean-Auth-TypeOAUTH

Example: Authorization Code Flow

This example uses openid-client with Express:

import express from 'express';
import * as client from 'openid-client';
import { Glean } from '@gleanwork/api-client';

const config = {
clientId: process.env.OAUTH_CLIENT_ID!,
clientSecret: process.env.OAUTH_CLIENT_SECRET!,
redirectUri: 'http://localhost:3000/callback',
issuer: process.env.OAUTH_ISSUER!, // e.g., https://accounts.google.com
};

const app = express();
let oidcConfig: client.Configuration;

// Initialize OIDC client
async function init() {
oidcConfig = await client.discovery(
new URL(config.issuer),
config.clientId,
config.clientSecret
);
}

app.get('/login', (req, res) => {
const authUrl = client.buildAuthorizationUrl(oidcConfig, {
redirect_uri: config.redirectUri,
scope: 'openid email',
});
res.redirect(authUrl.href);
});

app.get('/callback', async (req, res) => {
const callbackUrl = new URL(req.url, `http://${req.headers.host}`);
const tokens = await client.authorizationCodeGrant(oidcConfig, callbackUrl, {
expectedState: client.skipStateCheck,
});

// Use OAuth token with Glean
const glean = new Glean({ instance: process.env.GLEAN_INSTANCE! });

const results = await glean.client.search.search({
query: 'quarterly reports',
pageSize: 10,
}, {
headers: {
'Authorization': `Bearer ${tokens.access_token}`,
'X-Glean-Auth-Type': 'OAUTH',
},
});

res.json(results);
});

init().then(() => app.listen(3000));
tip

Access tokens typically expire after ~1 hour. For production use, implement token refresh using tokens.refresh_token.

Error Handling

try {
const response = await client.client.chat.create({
messages: [{ fragments: [{ text: "Hello" }] }]
});
} catch (error) {
console.error('API error:', error);
}

Testing

import { jest } from '@jest/globals';
import { Glean } from '@gleanwork/api-client';

jest.mock('@gleanwork/api-client');

const MockedGlean = Glean as jest.MockedClass<typeof Glean>;

test('chat service', async () => {
const mockCreate = jest.fn().mockResolvedValue({
text: 'Test response'
});

MockedGlean.mockImplementation(() => ({
client: { chat: { create: mockCreate } }
} as any));

// Test your code here
});

Additional Resources