npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

boostgpt

v8.5.0

Published

BoostGPT client library for nodejs.

Readme

Features

  • Full ES Modules (ESM) and CommonJS (CJS) support
  • Complete coverage of the public /v1 API — every bot/* and mcp/* endpoint has a method
  • Bot/Agent management (create, read, update, delete)
  • Chat operations, including server-sent streaming and reconnection
  • Training source management
  • Workflows (create, run, and monitor multi-step automations)
  • Scheduled tasks (autonomous agent runs, recurring or one-shot)
  • Workspaces (sandbox file system — read, write, publish)
  • Email inbox management (read, reply, configure)
  • MCP connector management (deploy from catalog, OpenAPI, or Postman)
  • Tools management (MCP server integration)
  • Message voting and feedback
  • Comprehensive analytics and statistics
  • TypeScript-friendly (type definitions coming soon)

Table of Contents

Requirements

  • Node.js >= 12.20.0
  • For ES Modules: Node.js >= 14.0.0 recommended
  • BoostGPT API Key

Installation

npm install boostgpt

Usage

ES Modules (Recommended)

import { BoostGPT } from 'boostgpt';

const client = new BoostGPT({
    project_id: 'your-project-id',
    key: 'your-api-key'
});

// Create a bot
const botResponse = await client.createBot({
    name: 'My Bot',
    model: 'gpt-5.6-luna',
    instruction: 'You are a helpful assistant',
    max_reply_tokens: 1000,
    status: 1
});

if (botResponse.err) {
    console.error('Error:', botResponse.err);
} else {
    console.log('Bot created:', botResponse.response);
}

// Chat with the bot
const chatResponse = await client.chat({
    bot_id: 'bot-id',
    message: 'Hello, how are you?'
});

console.log('Response:', chatResponse.response);

CommonJS (Legacy Support)

const { BoostGPT } = require('boostgpt');

const client = new BoostGPT({
    project_id: 'your-project-id',
    key: 'your-api-key'
});

// Use async/await or promises
(async () => {
    const botResponse = await client.createBot({
        name: 'My Bot',
        model: 'gpt-5.6-luna',
        instruction: 'You are a helpful assistant'
    });
    
    console.log(botResponse.response);
})();

API Reference

Constructor

const client = new BoostGPT({
    project_id: 'your-project-id',  // Required
    key: 'your-api-key'              // Required
});

Bot Management

Create Bot

await client.createBot({
    name: 'Bot Name',
    model: 'gpt-5.6-luna',
    instruction: 'System instruction',
    max_reply_tokens: 1000,
    status: 1
});

Fetch Bot

await client.fetchBot(bot_id);

Fetch All Bots

await client.fetchBots({
    page: 1,
    per_page: 10
});

Update Bot

await client.updateBot({
    bot_id: 'bot-id',
    name: 'Updated Name',
    model: 'gpt-5.6-luna',
    instruction: 'Updated instruction',
    max_reply_tokens: 1500,
    status: "0" // 1 = online, 0 = offline
});

Reset Bot

await client.resetBot(bot_id);

Delete Bot

await client.deleteBot(bot_id);

Chat Operations

Send Chat Message

await client.chat({
    bot_id: 'bot-id',
    model: 'gpt-5.6-luna',  //Optional
    provider_key: 'optional-provider-key', //Optional
    provider_host: 'optionl-provider-host', // Only needed and required when using ollama models
    instruction: 'Optional override instruction',
    label_instruction: 'Optional: how to word each tool step, e.g. "a short progressive phrase like Searching the web"',
    reasoning_mode: 'optional-reasoning-mode', //Default to standard
    source_ids: ['source1', 'source2'], //Optional
    message: 'Your message here',
    max_reply_tokens: 1000,  //Optional
    chat_id: 'optional-chat-id',
    stream: false,  //Optional
    memory: false, // Optional: Disables the agents memory
    purpose: 'service',       // Optional: this call is YOUR backend, acting for many end users
    workspace_uuid: 'ws-uuid' // Optional: pin the turn to a workspace (requires purpose: 'service')
});
Calling as a service

Most calls represent one person chatting. When your own backend is calling on behalf of many end users — a WhatsApp assistant, a helpdesk, a community bot — say so with purpose: 'service'.

It grants two things an ordinary call does not get:

  • A workspace of your choosing. Pass workspace_uuid and the turn runs there, so your agent can keep durable notes and read them back in a later conversation.
  • A chat mode that sticks. chat_mode: 'edit' survives the request, so the agent can write files.

And withholds one on purpose: a service call is not a builder conversation. It never receives the Site builder persona, and never gets read_conversations — the tool that reads what other people have asked. Workspace scope, never cross-conversation reach.

await client.chat({
    bot_id: 'bot-id',
    chat_id: 'community-42',
    message: 'What did we decide about the venue?',
    purpose: 'service',
    workspace_uuid: 'ws-abc123',
    path_scope: '/groups/community-42',  // Optional: confine this turn to one folder
    chat_mode: 'edit'
});

path_scope confines the turn's file tools — read, write, edit, grep, glob, ls and bash — to one folder of the workspace. Anything outside it reads as absent rather than forbidden, so one customer's folder cannot reveal that another's exists. Only honoured for purpose: 'service'.

purpose is a request, not a credential: it is granted only when your API key belongs to someone who runs the project, and asking for it otherwise changes nothing. It is opt-in too — omit it and your existing integration behaves exactly as before.

A pinned workspace is remembered against the chat_id, so a turn that pauses for tool execution resumes in the same workspace. You do not re-send workspace_uuid to executeTool().

Service workspaces count against their own plan allowance, separate from the workspaces you create in the dashboard, and are shown in your account usage. Neither allowance can be spent by the other.

Search

await client.search({
    bot_id: 'bot-id',
    source_ids: ['source1', 'source2'],
    keywords: 'search terms'
});

Fetch Chat

await client.fetchChat({
    bot_id: 'bot-id',
    chat_id: 'chat-id',
    page: 1,
    per_page: 10
});

Fetch All Chats

await client.fetchChats({
    bot_id: 'bot-id',
    page: 1,
    per_page: 10
});

Delete Chat

await client.deleteChat({
    chat_id: 'chat-id',
    bot_id: 'bot-id'
});

Execute Tool

When a chat() response comes back needing a tool run, it carries the execution details. Pass them straight back as execution_data — it must contain executionId, toolName and parameters.

const { response } = await client.chat({ bot_id: 'bot-id', message: 'What is 5 + 3?' });

if (response.chat?.type === 'tool_approval_required') {
    await client.executeTool({
        bot_id: 'bot-id',
        chat_id: 'chat-id',
        execution_data: {
            executionId: response.chat.executionId,
            toolName: response.chat.tool.name,
            parameters: response.chat.tool.parameters,
            serverLabel: response.chat.tool.server_label,   // Optional
            originalQuery: 'What is 5 + 3?'                 // Optional
        },
        memory: true,          // Optional: overrides the turn's setting
        source_ids: ['src-1'], // Optional: overrides the turn's scope ([] clears it)
        tags: ['docs'],        // Optional: overrides the turn's tags
        label_instruction: '...', // Optional: as on chat(), and sent per call
        stream: false          // Optional: returns an event stream when true
    });
}

A continuation resumes the turn that asked for the tool and inherits that turn's memory, source_ids and tags, plus the chat's saved chat_mode — so a scoped chat() call stays scoped for every tool step that follows, with nothing to re-send. The three parameters above are overrides: send one only to change it, and send [] to clear an inherited scope.

label_instruction is not one of them. Like instruction, it is sent per call: it shapes the prompt rather than the retrieval, so a continuation that omits it falls back to the default wording rather than inheriting the turn's. Send it on every hop if you want one voice across a whole turn.

Wording the tool steps

Each tool call carries a LABEL the agent writes for the person watching. By default the model is asked for it with imperative examples, so it produces "Search the web for X" — which suits a tool card sitting beside a result, and reads oddly as a live status line where "Searching the web" is wanted. label_instruction replaces that guidance:

await client.chat({
    bot_id: 'bot-id',
    message: 'what is the fuel price?',
    reasoning_mode: 'agent',
    label_instruction: 'a very short phrase in the present continuous, e.g. Searching the web or Reading the page'
});

It is guidance for the model, not a template — the label is still written per call and still names what that step is doing. Newlines and the LABEL:/REASONING:/PARAMS: markers are stripped server-side, because the reply is parsed on those, and the text is capped at 300 characters.

Before 8.0.1 this method sent tool_calls, which the endpoint does not read — every call returned 400.

Vote on Message

await client.voteMessage({
    bot_id: 'bot-id',
    message_id: 'message-id',
    voter_id: 'user-id',
    voter_type: 'member',
    vote_type: 'upvote' // or 'downvote'
});

Fetch Vote Status

await client.fetchVoteStatus({
    bot_id: 'bot-id',
    message_id: 'message-id',
    voter_id: 'user-id',
    voter_type: 'member'
});

Delete Message

await client.deleteMessage({
    bot_id: 'bot-id',
    chat_id: 'chat-id',
    message_id: 'message-id'
});

Rename a Chat

await client.renameChat({ bot_id: 'bot-id', chat_id: 'chat-id', name: 'Onboarding questions' });

Set the Chat Mode

// ask  — reads and answers
// edit — may change files in the agent's workspace
// plan — proposes a plan first, then executes what you approve
await client.setChatMode({ bot_id: 'bot-id', chat_id: 'chat-id', mode: 'plan' });

chat() also accepts chat_mode per message, if you would rather not change the conversation's stored mode:

await client.chat({ bot_id: 'bot-id', message: 'Add a pricing page', chat_mode: 'edit' });

Cancel a Reply in Progress

await client.cancelChat({ bot_id: 'bot-id', chat_id: 'chat-id' });

Stream State

await client.fetchStreamStatus({ bot_id: 'bot-id', chat_id: 'chat-id' });
await client.fetchActiveStreams({ bot_id: 'bot-id' });

Subscribe to a Conversation

Both subscribe methods answer text/event-stream, so response is the raw stream rather than a parsed object. This is how a client that dropped its connection mid-reply picks up the rest of it.

const { err, response } = await client.subscribeChat({ bot_id: 'bot-id', chat_id: 'chat-id' });

if (!err) {
    for await (const chunk of response) {
        process.stdout.write(chunk.toString());
    }
}

// Notifications for the whole agent; chat_id is optional.
await client.subscribeNotifications({ bot_id: 'bot-id' });

chat({ stream: true }) returns a stream the same way.

Schedules Attached to a Conversation

await client.fetchChatScheduledTasks({ bot_id: 'bot-id', chat_id: 'chat-id' });
// A toggle, not a setter: it flips the schedule's current state.
await client.toggleChatScheduledTask({
    bot_id: 'bot-id',
    chat_id: 'chat-id',
    task_id: 'task-id'
});

The Plan Behind a Conversation

await client.fetchChatPlan({ bot_id: 'bot-id', chat_id: 'chat-id' });
// No accept method: a plan is accepted through the agent's review question in the conversation.
await client.cancelChatPlan({ bot_id: 'bot-id', chat_id: 'chat-id' });

Agents Delegated in a Conversation

// This turn's agents…
const { response } = await client.fetchChatAgents({ bot_id: 'bot-id', chat_id: 'chat-id' });
// …or every turn's, the way the dashboard's agent map shows them
await client.fetchChatAgents({ bot_id: 'bot-id', chat_id: 'chat-id', scope: 'chat' });

// One agent in full: brief, report, and the tools it ran
await client.fetchChatAgent({ bot_id: 'bot-id', chat_id: 'chat-id', agent_id: response.agents[0].uuid });
// Remove its record; a running one is stopped first
await client.deleteChatAgent({ bot_id: 'bot-id', chat_id: 'chat-id', agent_id: response.agents[0].uuid });

Training/Source Management

Start Training

await client.startTraining({
    bot_id: 'bot-id',
    type: 'text',
    source: 'Training content here',
    title: 'Optional title',            // Optional
    description: 'Optional summary',    // Optional
    tags: ['docs'],                     // Optional
    forget_after: 'never',              // Optional: when to drop this source
    sync_frequency: 'never'             // Optional: how often to re-crawl it
});

Fetch Training

await client.fetchTraining({
    source_id: 'source-id',
    bot_id: 'bot-id'
});

Fetch All Trainings

await client.fetchTrainings({
    bot_id: 'bot-id',
    page: 1,
    per_page: 10
});

Update Training

await client.updateTraining({
    source_id: 'source-id',
    bot_id: 'bot-id',
    source: 'Updated content',
    title: 'Optional title',            // Optional
    description: 'Optional summary',    // Optional
    tags: ['docs'],                     // Optional
    forget_after: 'never',              // Optional
    sync_frequency: 'never'             // Optional
});

A source's type is fixed when it is created. updateTraining has no type parameter — passing one is silently ignored, because the request is built from named parameters only.


#### Delete Training
```javascript
await client.deleteTraining({
    source_id: 'source-id',
    bot_id: 'bot-id'
});

Tools Management

Fetch Tools

await client.fetchTools({
    bot_id: 'bot-id',
    page: 1,
    per_page: 10,
    filter: { type: 'mcp' } // Optional filter
});

Create Tool

await client.createTool({
    bot_id: 'bot-id',
    name: 'My Tool',
    description: 'Tool description',
    config: {
        url: 'https://api.example.com',
        auth: 'bearer_token'
    },
    type: 'mcp'
});

Fetch Tool

await client.fetchTool({
    tool_id: 'tool-id',
    bot_id: 'bot-id'
});

Update Tool

await client.updateTool({
    tool_id: 'tool-id',
    bot_id: 'bot-id',
    name: 'Updated Tool Name',
    description: 'Updated description',
    config: { /* updated config */ },
    type: 'mcp'
});

Delete Tool

await client.deleteTool({
    tool_id: 'tool-id',
    bot_id: 'bot-id'
});

Configure Tools

await client.configureTools({
    tool_id: 'tool-id',
    bot_id: 'bot-id',
    settings: {
        enabled: true,
        timeout: 30000
    }
});

Refresh Tools

await client.refreshTools({
    tool_id: 'tool-id',
    bot_id: 'bot-id'
});

Toggle Tool

await client.toggleTool({
    tool_id: 'tool-id',
    bot_id: 'bot-id',
    tool_name: 'specific-tool',
    active: true
});

Test Tool Connection

await client.testToolConnection({
    tool_id: 'tool-id',
    bot_id: 'bot-id'
});

Workflows

Fetch Workflow Catalog

await client.fetchWorkflowCatalog({ bot_id: 'bot-id' });

List Workflows

await client.fetchWorkflows({ bot_id: 'bot-id' });

Get a Workflow

await client.fetchWorkflow({ bot_id: 'bot-id', workflow_id: 'wf-id' });

Create a Workflow

await client.createWorkflow({
    bot_id: 'bot-id',
    name: 'Lead Qualification',
    trigger: 'webhook',
    steps: [/* step objects */]
});

Update a Workflow

await client.updateWorkflow({
    bot_id: 'bot-id',
    workflow_id: 'wf-id',
    enabled: true
});

Delete a Workflow

await client.deleteWorkflow({ bot_id: 'bot-id', workflow_id: 'wf-id' });

Run a Workflow

await client.runWorkflow({ bot_id: 'bot-id', workflow_id: 'wf-id' });

Fetch Workflow Logs

await client.fetchWorkflowLogs({ bot_id: 'bot-id' });

Workflow Templates

// The prebuilt workflows available to this agent
await client.fetchWorkflowTemplates({ bot_id: 'bot-id' });

// Create one from a template
await client.applyWorkflowTemplate({ bot_id: 'bot-id', template_key: 'weekly-digest' });

Scheduled tasks

Recurring or one-shot runs the agent performs on its own. They appear on the agent's Tasks board in the dashboard — recurring ones under Schedules.

Create a task

await client.createTask({
    bot_id: 'bot-id',
    name: 'Triage support tickets',
    prompt: 'Check for new support tickets and summarize urgent ones',
    cron_pattern: '0 9 * * 1-5',   // weekdays at 9am
    enabled: true,
    timezone: 'America/New_York',
    max_consecutive_errors: 5
});

cron_pattern is a convenience for a recurring schedule. For anything else, pass schedule_type and schedule_config directly:

await client.createTask({
    bot_id: 'bot-id',
    name: 'Hourly inbox check',
    prompt: 'Check the inbox',
    schedule_type: 'interval',            // interval | daily | weekly | cron | once
    schedule_config: { interval_minutes: 60 }
});

Schedule frequency

Every plan enforces a minimum interval of 15 minutes. It is an infrastructure limit, not a tier: credits are what meter automation, and the floor exists to stop a schedule firing faster than a run can finish. A schedule below it is refused:

const { err } = await client.createTask({
    bot_id: 'bot-id',
    name: 'Too eager',
    prompt: 'Check the inbox',
    schedule_type: 'interval',
    schedule_config: { interval_minutes: 1 }
});

err.status;   // 400
err.message;  // "The shortest interval on this plan is 15 minutes; 1 was requested."

Cron is measured the same way — the shortest gap between fires has to clear the floor, so * * * * * is refused and 0 9 * * 1-5 is not.

Update a task

await client.updateTask({
    bot_id: 'bot-id',
    task_id: 'task-id',
    prompt: 'Check for new tickets and summarize the urgent ones',
    schedule_config: { interval_minutes: 60 },   // subject to the same floor
    enabled: true
});

Get a task

await client.fetchTask({ bot_id: 'bot-id', task_id: 'task-id' });

List tasks

await client.fetchTasks({ bot_id: 'bot-id' });

Enable / Disable

await client.enableTask({ bot_id: 'bot-id', task_id: 'task-id' });
await client.disableTask({ bot_id: 'bot-id', task_id: 'task-id' });

Trigger Manually

await client.triggerTask({ bot_id: 'bot-id', task_id: 'task-id' });

Delete a task

await client.deleteTask({ bot_id: 'bot-id', task_id: 'task-id' });

Fetch Logs & Stats

await client.fetchTaskLogs({ bot_id: 'bot-id' });
await client.fetchTaskStats({ bot_id: 'bot-id' });

// Narrowed to one task, one status, one page
await client.fetchTaskLogs({
    bot_id: 'bot-id',
    task_id: 'task-id',
    status: 'interrupted',
    page: 1,
    per_page: 20
});

Each run carries a status:

| status | meaning | |---|---| | success | The run finished. | | error | The run started and failed. Consecutive errors eventually pause the schedule. | | skipped | The run was declined before starting; reason says why. | | interrupted | The run was killed mid-flight, normally by a deploy or restart. Not counted as an error. |

Common reason values on a skip: already_running (the previous fire has not finished), schedule_clamped (the schedule was below the plan floor and was slowed to it), no_credits, outside_active_hours, max_executions_reached, assigned_to_member, bot_offline.

Delete a run

await client.deleteTaskLog({ bot_id: 'bot-id', run_id: 'run-uuid' });

Upgrading from 5.x: these replace the *Heartbeat methods, and heartbeat_id is now task_id. See the CHANGELOG for the full mapping.

Workspaces

List Workspaces

await client.fetchWorkspaces({ bot_id: 'bot-id' });

Create / Delete Workspace

await client.createWorkspace({ bot_id: 'bot-id', name: 'My Workspace' });

// Integrations: put the workspace in the SERVICE allowance rather than the dashboard one — the
// pool to spend when you create one workspace per customer you serve. Granted only when your key
// belongs to someone who runs the project; otherwise it lands in the usual pool.
await client.createWorkspace({ bot_id: 'bot-id', name: 'acme-corp', purpose: 'service' });
await client.deleteWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });

File Operations

// List files
await client.fetchFiles({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });

// Read a file
await client.readFile({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', file_uuid: 'file-uuid' });

// Create a file
await client.createFile({
    bot_id: 'bot-id',
    workspace_uuid: 'ws-uuid',
    file_path: '/src/app.js',
    content: 'console.log("hello");',
    language: 'javascript'
});

// Update a file
await client.updateFile({
    bot_id: 'bot-id',
    workspace_uuid: 'ws-uuid',
    file_uuid: 'file-uuid',
    content: '// updated content'
});

// Rename / move a file
await client.renameFile({
    bot_id: 'bot-id',
    workspace_uuid: 'ws-uuid',
    old_path: '/src/app.js',
    new_path: '/src/main.js'
});

// Delete a file
await client.deleteFile({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', file_uuid: 'file-uuid' });

// Download workspace as ZIP
await client.downloadWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });

Publishing

await client.suggestSubdomain({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
await client.publishWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', subdomain: 'my-app' });
await client.unpublishWorkspace({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });

// Custom domain
await client.addCustomDomain({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid', custom_domain: 'app.example.com' });
await client.removeCustomDomain({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
await client.refreshDomainStatus({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });
await client.getDomainInfo({ bot_id: 'bot-id', workspace_uuid: 'ws-uuid' });

Email Inbox

Get Email Address

await client.fetchEmailAddress({ bot_id: 'bot-id' });

Update Settings

await client.updateEmailSettings({
    bot_id: 'bot-id',
    auto_reply: true,
    signature: 'Best, Support Team'
});

Stats, List, Read, Reply, Delete

await client.fetchEmailStats({ bot_id: 'bot-id' });

await client.fetchEmails({ bot_id: 'bot-id', page: 1, per_page: 20 });

await client.fetchEmail({ bot_id: 'bot-id', email_id: 'email-uuid' });

await client.replyToEmail({
    bot_id: 'bot-id',
    email_id: 'email-uuid',
    content: 'Thanks for reaching out!'
});

await client.deleteEmail({ bot_id: 'bot-id', email_id: 'email-uuid' });

MCP Connectors

Connector Catalog

// List all available connectors
await client.fetchConnectors();

// Get connector details (auth requirements, tools)
await client.fetchConnector('jamendo');

Deploy MCP Servers

// From a pre-built connector
await client.createMcpFromPredefined({
    name: 'My Jamendo Server',
    connectorName: 'jamendo',
    credentials: { client_id: 'your_client_id' }
});

// From an OpenAPI spec
await client.createMcpFromOpenApi({
    name: 'My API Server',
    openApiSpec: { /* OpenAPI 3.0 object */ },
    credentials: { api_key: 'sk-xxx' }
});

// From a Postman collection
await client.createMcpFromPostman({
    name: 'My Postman Server',
    postmanCollection: { /* Postman Collection v2.1 */ }
});

Manage Servers

await client.fetchMcpServers();
await client.fetchMcpServer('server-uuid');
await client.updateMcpServer({ id: 'server-uuid', name: 'Renamed' });
await client.cloneMcpServer({ id: 'server-uuid', name: 'Clone' });
await client.deleteMcpServer('server-uuid');
await client.fetchMcpUsage('server-uuid');

Validate Specs

await client.validateOpenApi({ spec: openApiObject });
await client.validatePostman({ collection: postmanObject });

Widget

Serves the embeddable chat widget, so a backend can read the same configuration the widget reads.

// Branding and widget settings for an embedded agent
await client.fetchWidgetConfig({ bot_id: 'bot-id' });

Analytics

Fetch Vote Statistics

await client.fetchVoteStats({
    bot_id: 'bot-id'
});

Fetch Summary Statistics

await client.fetchSummaryStats({
    bot_id: 'bot-id'
});

Fetch Dashboard Statistics

await client.fetchDashboardStats({
    bot_id: 'bot-id'
});

Fetch Tool Usage Statistics

await client.fetchToolUsageStats({
    bot_id: 'bot-id'
});

Fetch Workflow Statistics

await client.fetchWorkflowStats({
    bot_id: 'bot-id'
});

Fetch Performance Metrics

await client.fetchPerformanceMetrics({
    bot_id: 'bot-id'
});

Fetch User Behavior Statistics

await client.fetchBehaviorStats({
    bot_id: 'bot-id'
});

Fetch Error Analysis

await client.fetchErrorAnalysis({
    bot_id: 'bot-id'
});

Fetch Reasoning Summary

await client.fetchReasoningSummary({
    bot_id: 'bot-id'
});

Response Format

All methods return a BoostGPTResponse object:

{
    err: null | Error,        // Set when the request failed
    response: null | Object   // The parsed body when it succeeded
}

Methods never throw. A request that came back with a non-2xx status populates err:

const result = await client.createBot({ name: 'My Bot' });

if (result.err) {
    console.error(result.err.message);   // what the server said
    console.error(result.err.status);    // 400, 403, 429, 500 …
    console.error(result.err.code);      // e.g. 'schedule_too_frequent', when the API sends one
} else {
    console.log(result.response);
}

For a streaming call — chat({ stream: true }), subscribeChat, subscribeNotifications — response is the raw event stream instead of a parsed object; iterate it with for await.

Changed in 8.0.0. Earlier versions decided whether a request had failed by reading a field the API only populates in development, so against production err was always null and a failed call returned the error body as though it were data. If your code inspects response.message to detect failures, it can now check err instead.

Not covered

Sites (/v1/sites)

Development

Building the Package

# Install dependencies
npm install

# Build CommonJS files from ESM source
npm run build

The build process converts the ES Module source files in src/ to CommonJS in dist/.

Project Structure

  • src/ - ES Module source code (edit these files)
  • dist/ - Generated CommonJS build (don't edit, auto-generated)
  • build.js - Build script that transpiles ESM to CJS
  • package.json - Configured with "type": "module" and dual exports

Making Changes

  1. Edit files in src/ (ESM format)
  2. Run npm run build to generate CJS in dist/
  3. Run npm test — it stands up a local stub server, so it needs no API key and spends no credits. The suite also checks this README and QUICKSTART against the source: a documented parameter the SDK would silently drop, or a method shown nowhere, fails the build.
  4. The prepublishOnly script automatically builds before publishing

TypeScript Support

While this package is written in JavaScript, it works with TypeScript. Type definitions may be added in a future release.

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes in src/
  4. Run npm run build
  5. Test both ESM and CJS usage
  6. Submit a Pull Request

License

MIT

Links

Support

For support, please visit the GitHub Issues page.