
Research
Active Supply Chain Attack Compromises @antv Packages on npm
Active npm supply chain attack compromises @antv packages in a fast-moving malicious publish wave tied to Mini Shai-Hulud.
@cstar.help/js
Advanced tools
Official TypeScript SDK for the cStar customer support platform.
fetchnpm install @cstar.help/js
cStar has one package with six entry points, each designed for a different context:
| Import | Use Case | Runs On | Auth Required | Key Type |
|---|---|---|---|---|
@cstar.help/js | Admin dashboard / backend integration | Server only | Yes | Secret (sk_*) |
@cstar.help/js/chat | Customer chat widget | Browser | Yes | Publishable (pk_*) |
@cstar.help/js/library | Public knowledge base | Browser or server | No | None |
@cstar.help/js/community | Public community forum | Browser or server | No | None |
@cstar.help/js/webhook | Webhook signature verification | Server only | No | Signing secret |
@cstar.help/js/auth | Authentication utilities | Server only | Yes | Secret (sk_*) |
cStar uses two key types to control access ā the same pattern as Stripe:
Secret keys (sk_live_*, sk_test_*)
āāā Full CRUD on all resources
āāā Settings, billing, analytics, game system
āāā Team member management, audit log
āāā AI actions, automations, SLA rules
āāā NEVER expose in client-side code
Publishable keys (pk_live_*, pk_test_*)
āāā Read-only on public data (tickets, customers, articles)
āāā Used by the chat widget for customer-facing features
āāā Safe to include in browser bundles
āāā Cannot write, delete, or access sensitive endpoints
Rule of thumb: If you're building a custom support dashboard for your team, use
CStarClientwith a secret key on your backend. If you're adding chat to your website, useChatClientwith a publishable key in the browser.
ā ļø Server-side only.
CStarClientrequires a secret key (sk_*) and must never be used in browser code. The SDK will warn you if it detects a browser environment.
Manage tickets, customers, articles, team members, settings, game system, and everything else.
import { CStarClient } from '@cstar.help/js';
const cstar = new CStarClient({
apiKey: process.env.CSTAR_SECRET_KEY, // sk_live_... or sk_test_...
teamId: process.env.CSTAR_TEAM_ID
});
// List open tickets
const { data: tickets } = await cstar.tickets.list({ status: 'open' });
// Create a ticket
const { data: ticket } = await cstar.tickets.create({
title: 'Help with billing',
customerId: 'cus_abc123'
});
// Auto-paginate through all tickets
for await (const ticket of cstar.tickets.listAutoPaginating({ status: 'open' })) {
console.log(ticket.title);
}
Core Resources ā Tickets, customers, and knowledge base.
| Resource | Methods |
|---|---|
cstar.tickets | .list() .get(id) .create(params) .update(id, params) .del(id) .listAutoPaginating() |
cstar.tickets.messages | .list(ticketId) .create(ticketId, params) |
cstar.customers | .list() .get(id) .create(params) .update(id, params) .del(id) .listAutoPaginating() |
cstar.articles | .list() .get(id) .create(params) .update(id, params) .del(id) .listAutoPaginating() |
cstar.categories | .list() .get(id) .create(params) .update(id, params) .del(id) |
Team & Configuration ā Members, settings, and customization.
| Resource | Methods |
|---|---|
cstar.members | .list() .get(id) .update(id, params) .del(id) |
cstar.members.invites | .list() .create(params) .del(id) |
cstar.settings | .get() .update(params) .getBusinessHours() .updateBusinessHours(params) .getWidget() .updateWidget(params) |
cstar.settings.statuses | .list() .create(params) .update(key, params) .del(key) .reorder(keys) |
cstar.settings.quickReplies | .list() .create(params) .update(id, params) .del(id) .reorder(ids) |
cstar.customFields | .list() .get(id) .create(params) .update(id, params) .del(id) .reorder(ids) |
cstar.notifications | .list() .unreadCount() .markRead(id) .markAllRead() |
Operations ā Analytics, bulk actions, and data management.
| Resource | Methods |
|---|---|
cstar.analytics | .overview(params?) .agents(params?) .csatStats(params?) .csatResponses(params?) |
cstar.sla | .list() .get(id) .create(params) .update(id, params) .del(id) |
cstar.bulk | .update(params) .del(params) |
cstar.export | .create(params) |
cstar.import | .create(params) .logs(params?) .getLog(id) |
cstar.search | .query(params) |
cstar.tags | .list() .create(name) .del(name) |
cstar.activity | .list(params?) |
cstar.auditLog | .list(params?) |
cstar.customerGroups | .list() .get(id) .create(params) .update(id, params) .del(id) |
Gamification ā The full game system.
| Resource | Methods |
|---|---|
cstar.game | .player(params?) .getPlayer(memberId) .leaderboard(params?) .myRank(params?) |
cstar.game.boss | .current() .isActive() .spawn(params?) .damage(params) .defeats(params?) .getDefeat(id) |
cstar.game.achievements | .list(params?) .unlocked(params) .get(id, params?) |
cstar.game.quests | .today(params?) .history(params?) |
cstar.game.puzzles | .today(params?) .complete(params) .streak(params) .leaderboard(params?) |
cstar.game.oneUps | .list(params?) .send(params) .remaining(params) |
cstar.game.highFives | .list(params?) .send(params) .canSend(teamId, params) |
cstar.game.cosmetics | .list(params?) .getPreferences(params) .updatePreferences(params) |
cstar.game.seasons | .list() .current() .stats(seasonId, params) |
cstar.game.skills | .get(params) .allocate(params) .reset(params) |
Advanced ā AI, automations, views, billing, webhooks.
| Resource | Methods |
|---|---|
cstar.ai | .run(params) .autoTag(ticketId) .suggestReply(ticketId) .summarize(ticketId) .improve(text) |
cstar.automations | .list() .get(id) .create(params) .update(id, params) .del(id) .toggle(id) .reorder(ids) .test(id, params) .executions(id) .allExecutions() .evaluate(params) |
cstar.views | .list() .get(id) .create(params) .update(id, params) .del(id) .execute(id, params?) |
cstar.billing | .subscription() .portal(params?) |
cstar.webhooks | .list() .get(id) .create(params) .update(id, params) .del(id) .test(id) |
cstar.community.posts | .list() .get(id) .create(params) .update(id, params) .del(id) |
cstar.community.topics | .list() .get(id) |
cstar.attachments | .list(params?) .get(id) .del(id) |
// Team analytics
const { data: overview } = await cstar.analytics.overview({ period: 'week' });
console.log(`${overview.tickets.open} open tickets this week`);
// SLA rules
const { data: rules } = await cstar.sla.list();
// Boss battle
const { data: boss } = await cstar.game.boss.current();
if (boss.active) {
console.log(`${boss.name} ā ${boss.health}/${boss.maxHealth} HP`);
}
// AI-powered reply suggestion
const { data: suggestion } = await cstar.ai.suggestReply('tkt_abc123');
// Bulk close resolved tickets
await cstar.bulk.update({
resource: 'tickets',
ids: ['tkt_1', 'tkt_2', 'tkt_3'],
data: { status: 'closed' }
});
// Export data
const { data: exportResult } = await cstar.export.create({
resources: [{ type: 'tickets', filters: { status: 'closed' } }],
format: 'csv'
});
// Saved views
const { data: view } = await cstar.views.create({
name: 'Urgent Unresolved',
entityType: 'tickets',
filters: { priority: 'urgent', status: 'open' }
});
const { data: results } = await cstar.views.execute(view.id);
// Search across everything
const { data: searchResults } = await cstar.search.query({
query: 'billing issue',
types: ['tickets', 'customers']
});
Build custom chat experiences in the browser. Uses a publishable key ā safe for frontend code.
The chat client supports two authentication modes:
You don't have to pick the mode up-front. The first response from any cstar endpoint includes an X-Cstar-Auth-Mode header, which the SDK caches; chat.getAuthMode() returns 'hmac', 'session', or null after the first call.
import { ChatClient } from '@cstar.help/js/chat';
const chat = new ChatClient({ teamSlug: 'acme' });
await chat.identify(
{ externalId: 'usr_123', email: 'jane@example.com', name: 'Jane', timestamp: Date.now() / 1000 },
hmacSignature
);
const chat = new ChatClient({ teamSlug: 'acme' });
// Login with credentials ā returns the customer + tokens
const { customer, accessToken, refreshToken } = await chat.loginWithCredentials(
'jane@example.com',
'hunter2'
);
// Or rehydrate from previously stored tokens
await chat.loginWithSession(accessToken, refreshToken);
const { tickets } = await chat.tickets.list();
await chat.messages.send('tkt_abc123', 'Thanks for the help!');
const unsubscribe = chat.onMessage('tkt_abc123', (message) => {
console.log(`${message.sender_name}: ${message.content}`);
});
chat.disconnect();
Every ChatClient request throws a typed subclass of ChatClientError on failure. Each carries a requestId (from the X-Request-Id response header) so customer support can correlate against server logs.
import {
ChatClientError,
ChatClientAuthError,
ChatClientRateLimitError,
ChatClientServerError,
ChatClientNetworkError
} from '@cstar.help/js/chat';
try {
await chat.identify(customer, signature);
} catch (err) {
if (err instanceof ChatClientAuthError) {
// 401 / 403 ā bad signature, expired token, wrong team
} else if (err instanceof ChatClientRateLimitError) {
// 429 ā back off for err.retryAfter seconds
} else if (err instanceof ChatClientServerError) {
// 5xx ā usually transient, retry with backoff
} else if (err instanceof ChatClientNetworkError) {
// fetch() itself failed ā DNS, offline, CORS ā see err.originalError
} else if (err instanceof ChatClientError) {
console.log('Error', err.code, err.statusCode, 'requestId:', err.requestId);
}
}
Search and browse your public help center ā no authentication required.
import { LibraryClient } from '@cstar.help/js/library';
const library = new LibraryClient({ teamSlug: 'acme' });
const categories = await library.categories();
const results = await library.search('reset password');
const article = await library.article('how-to-reset-password');
Browse your public community forum ā no authentication required.
import { CommunityClient } from '@cstar.help/js/community';
const community = new CommunityClient({ teamSlug: 'acme' });
const topics = await community.topics();
const { posts } = await community.posts({ topicSlug: 'feature-requests', sort: 'votes' });
const { post, comments } = await community.post('dark-mode-support');
Verify incoming webhook signatures on your server.
import { constructEvent } from '@cstar.help/js/webhook';
// In your webhook handler
const event = constructEvent(rawBody, signature, 'whsec_your_secret');
switch (event.type) {
case 'ticket.created':
console.log('New ticket:', event.data.title);
break;
case 'customer.created':
console.log('New customer:', event.data.email);
break;
}
For edge runtimes (Cloudflare Workers, Deno), use the async variant:
import { constructEventAsync } from '@cstar.help/js/webhook';
const event = await constructEventAsync(rawBody, signature, secret);
const cstar = new CStarClient({
apiKey: 'sk_live_...', // Required ā must be a secret key (sk_*)
teamId: 'tm_...', // Required ā your team ID
baseUrl: 'https://...', // Optional ā defaults to https://www.cstar.help
version: '2026-03-01', // Optional ā API version header
maxRetries: 3, // Optional ā retry attempts for 5xx/429
timeout: 30000 // Optional ā request timeout in ms
});
Test mode is auto-detected from your API key prefix:
const cstar = new CStarClient({
apiKey: 'sk_test_abc123...',
teamId: 'tm_your_team_id'
});
console.log(cstar.isTestMode); // true
// All operations use test data ā no real customers affected
All API errors throw typed exceptions:
import {
CStarError,
CStarAuthenticationError,
CStarRateLimitError,
CStarNotFoundError,
CStarValidationError
} from '@cstar.help/js';
try {
await cstar.tickets.get('tkt_nonexistent');
} catch (err) {
if (err instanceof CStarNotFoundError) {
console.log('Ticket not found:', err.message);
} else if (err instanceof CStarValidationError) {
console.log('Invalid param:', err.param);
} else if (err instanceof CStarRateLimitError) {
console.log('Rate limited, retry after:', err.retryAfter, 'seconds');
} else if (err instanceof CStarAuthenticationError) {
console.log('Bad API key');
} else if (err instanceof CStarError) {
console.log('API error:', err.code, err.statusCode);
}
}
Safely retry create/update operations:
const { data: ticket } = await cstar.tickets.create(
{ title: 'Billing issue', customerId: 'cus_abc' },
{ idempotencyKey: 'create-billing-issue-usr123' }
);
fetch and AbortSignal.timeout)MIT
FAQs
Official TypeScript SDK for the cStar customer support platform
The npm package @cstar.help/js receives a total of 78 weekly downloads. As such, @cstar.help/js popularity was classified as not popular.
We found that @cstar.help/js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Ā It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Active npm supply chain attack compromises @antv packages in a fast-moving malicious publish wave tied to Mini Shai-Hulud.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.

Security News
TeamPCP and BreachForums are promoting a Shai-Hulud supply chain attack contest with a $1,000 prize for the biggest package compromise.