Beacon SDK
TypeScript SDK for the Beacon status page API. Interact with changelogs, monitors, incidents, and more.
Installation
pnpm add @deutschlandgpt/beacon-sdk
Requirements
- Node.js 18 or higher
- TypeScript 5.0+ (for TypeScript projects)
Quick Start
import { BeaconClient } from "@deutschlandgpt/beacon-sdk";
// Initialize the client
const beacon = new BeaconClient({
baseUrl: "https://your-beacon-instance.com",
apiKey: "your-api-key", // Optional, required for authenticated endpoints
});
// Fetch changelogs
const changelogs = await beacon.changelogs.list();
console.log(changelogs);
Configuration
The BeaconClient accepts the following configuration options:
const beacon = new BeaconClient({
baseUrl: string; // Your Beacon instance URL (required)
apiKey?: string; // API key for authenticated endpoints (optional)
fetch?: typeof fetch; // Custom fetch implementation (optional)
});
API Reference
Changelogs
List and retrieve changelogs from your Beacon instance.
// List all changelogs
const changelogs = await beacon.changelogs.list();
// List with filters
const filtered = await beacon.changelogs.list({
tag: "api", // Filter by tag: 'api' | 'chat' | 'workflows'
since: "2024-01-01", // Only changelogs after this date
breaking: true, // Only breaking changes
limit: 10, // Limit results
offset: 0, // Pagination offset
});
// Get a specific changelog by ID
const changelog = await beacon.changelogs.get("changelog-id");
Monitors
Check the status of monitored services.
// Get status of all monitors
const monitors = await beacon.monitors.status();
// Each monitor includes:
// - id, name, description
// - currentStatus: 'operational' | 'degraded' | 'outage' | 'unknown'
// - responseTime, statusCode, lastChecked
// - uptimePercent: 90-day uptime as a string (e.g. "99.95"), or null
// - dailySummaries: per-day check summaries (up to 90 days)
Incidents
Retrieve incident information.
// List all incidents
const incidents = await beacon.incidents.list();
// Get active incidents (requires API key)
const activeIncidents = await beacon.incidents.active();
// Incidents for display inside the host app (requires API key). Includes internal and
// audience-targeted incidents plus client scopes; filter per user on YOUR server and
// never forward `audience` to a browser.
const inApp = await beacon.incidents.inApp({ locale: 'de' });
// Incident properties include:
// - status: 'investigating' | 'identified' | 'monitoring' | 'resolved'
// - severity: 'minor' | 'major' | 'critical'
// - affectedMonitorIds: array of affected monitor IDs
Subscribers
Manage email subscriptions.
// Subscribe to updates
const response = await beacon.subscribers.subscribe({
email: "[email protected]",
subscribeTo: ["changelogs", "status_updates", "newsletters"],
});
// Subscription types:
// - 'changelogs': Product changelog updates
// - 'status_updates': Service status updates
// - 'newsletters': General newsletters
Feedback
Submit user feedback. submit() requires an API key and returns the created
feedback plus similar existing feedback; submitPublic() is unauthenticated
(for public/embedded forms), requires userEmail, and returns
{ success: true }.
// Submit feedback (requires API key)
const result = await beacon.feedback.submit({
type: "bug_report", // 'bug_report' | 'feature_request' | 'improvement' | 'support' | 'security' | 'other'
title: "Issue with login",
description: "Detailed description of the issue",
// Optional fields
userEmail: "[email protected]",
userName: "John Doe",
featureOrService: "Authentication",
planTier: "Pro",
browserInfo: navigator.userAgent,
deviceInfo: "Desktop",
pageUrl: "https://app.example.com/dashboard", // URL where the feedback was submitted
consentToNotify: true,
tags: { source: "widget", region: "eu" }, // Arbitrary key/value metadata
attachments: [file1, file2], // Array of File objects
// Authenticated-only (see below): where the reporter's organisation stands
// commercially, so support can prioritise a customer who is still evaluating.
reporterStage: "trial_business", // 'customer' | 'trial_business' | 'trial_enterprise'
reporterTrialEndsAt: "2026-08-24T00:00:00.000Z", // ISO 8601; snapshot at report time
});
// Response includes the created feedback and similar existing feedback
console.log(result.feedback);
console.log(result.similar);
// The returned feedback carries a lifecycle status and a server-assigned urgency:
// status: 'new' | 'investigating' | 'in_progress' | 'waiting_for_user' | 'planned' | 'resolved' | 'wont_fix'
// urgency: 'critical' | 'high' | 'medium' | 'low' | null (classified automatically, read-only)
// Submit feedback from a public form (no API key required — userEmail is required)
await beacon.feedback.submitPublic({
type: "feature_request",
title: "Add dark mode",
description: "Please add a dark theme",
userEmail: "[email protected]",
});
reporterStage and reporterTrialEndsAt are accepted only by submit().
submitPublic() posts to an unauthenticated endpoint, so a caller must never be
able to claim trial priority for their own ticket — Beacon strips both fields
there. They therefore live on SubmitFeedbackParams rather than the shared
FeedbackParamsBase, and SubmitPublicFeedbackParams does not accept them at all.
When feedback is submitted with a userEmail, the user can follow up through a
public conversation thread identified by the feedback's publicToken:
// Fetch the message thread for a feedback item
const messages = await beacon.feedback.messages("public-token");
// Post a user reply to the thread
const message = await beacon.feedback.sendMessage({
token: "public-token",
body: "Any update on this?",
});
Error Handling
The SDK provides typed error classes for different error scenarios:
import {
BeaconError,
BeaconValidationError,
BeaconAuthError,
BeaconNotFoundError,
} from "@deutschlandgpt/beacon-sdk";
try {
const changelogs = await beacon.changelogs.list();
} catch (error) {
if (error instanceof BeaconAuthError) {
console.error("Authentication failed:", error.message);
} else if (error instanceof BeaconNotFoundError) {
console.error("Resource not found:", error.message);
} else if (error instanceof BeaconValidationError) {
console.error("Validation error:", error.message);
console.error("Details:", error.details);
} else if (error instanceof BeaconError) {
console.error("API error:", error.message);
console.error("Status:", error.status);
}
}
Error Types
BeaconError: Base error class for all SDK errorsBeaconValidationError: Validation errors (400 status)BeaconAuthError: Authentication errors (401 status)BeaconNotFoundError: Resource not found errors (404 status)
TypeScript Support
The SDK is written in TypeScript and includes full type definitions. All API responses and parameters are typed:
import type {
Changelog,
MonitorStatusEntry,
Incident,
Feedback,
ChangelogListParams,
SubmitFeedbackParams,
FeedbackReporterStage,
} from "@deutschlandgpt/beacon-sdk";
// Types are automatically inferred
const changelogs: Changelog[] = await beacon.changelogs.list();
const monitor: MonitorStatusEntry = monitors[0];
Examples
Displaying System Status
const monitors = await beacon.monitors.status();
const activeIncidents = await beacon.incidents.list();
monitors.forEach((monitor) => {
console.log(`${monitor.name}: ${monitor.currentStatus}`);
console.log(`Response time: ${monitor.responseTime}ms`);
});
if (activeIncidents.length > 0) {
console.log("\nActive Incidents:");
activeIncidents.forEach((incident) => {
console.log(`[${incident.severity}] ${incident.title}`);
console.log(`Status: ${incident.status}`);
});
}
Fetching Recent Changelogs
const recentChanges = await beacon.changelogs.list({
limit: 5,
since: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(),
});
recentChanges.forEach((changelog) => {
console.log(`v${changelog.version} - ${changelog.title}`);
console.log(changelog.content);
console.log(`Tags: ${changelog.tags.join(", ")}`);
if (changelog.isBreakingChange) {
console.log("⚠️ Breaking Change");
}
});
User Feedback Collection
// Collect feedback with file attachments
const fileInput = document.querySelector<HTMLInputElement>("#file-input");
const files = Array.from(fileInput?.files ?? []);
const feedback = await beacon.feedback.submit({
type: "bug_report",
title: "Cannot upload files",
description: "Getting an error when uploading files larger than 10MB",
userEmail: "[email protected]",
featureOrService: "File Upload",
attachments: files,
});
console.log("Feedback submitted:", feedback.feedback.id);
if (feedback.similar.length > 0) {
console.log("Similar feedback found:");
feedback.similar.forEach((item) => {
console.log(`- ${item.title} (${item.status})`);
});
}
Releasing
Publishing is driven by git tags, not by the version field in package.json. Pushing a tag like 0.1.0 from a commit on master triggers the publish workflow, which derives the published version from the tag and overwrites package.json at build time. Manually bumping the version in package.json has no effect on what gets published.
git tag 0.1.0
git push origin 0.1.0
License
MIT
Author
DeutschlandGPT