JavaScript / TypeScript
No SDK installation is required. The Sentro API is a standard REST API that works with the built-in fetch function available in Node.js 18+ and all modern browsers.
Client Wrapper
Create a reusable API client:
// sentro.ts
const BASE_URL = 'https://api.sentro.dev/v1';
class SentroClient {
private apiKey: string;
constructor(apiKey: string) {
this.apiKey = apiKey;
}
private async request<T>(path: string, options: RequestInit = {}): Promise<T> {
const url = `${BASE_URL}${path}`;
const response = await fetch(url, {
...options,
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...options.headers,
},
});
const body = await response.json();
if (!response.ok) {
throw new Error(`API Error [${response.status}]: ${body.error?.message ?? 'Unknown error'}`);
}
return body;
}
// ── Monitors ──────────────────────────────────────────
async listMonitors() {
return this.request<{
data: Monitor[];
meta: { total: number };
}>('/monitors');
}
async getMonitor(id: string) {
return this.request<{ data: Monitor & { latestChecks: Check[] } }>(`/monitors/${id}`);
}
async createMonitor(input: CreateMonitorInput) {
return this.request<{ data: Monitor }>('/monitors', {
method: 'POST',
body: JSON.stringify(input),
});
}
async updateMonitor(id: string, input: Partial<CreateMonitorInput>) {
return this.request<{ data: Monitor }>(`/monitors/${id}`, {
method: 'PATCH',
body: JSON.stringify(input),
});
}
async deleteMonitor(id: string) {
return this.request<{ data: { id: string; deleted: boolean } }>(`/monitors/${id}`, {
method: 'DELETE',
});
}
// ── Checks ────────────────────────────────────────────
async listChecks(monitorId: string, params?: { limit?: number; offset?: number }) {
const query = new URLSearchParams();
if (params?.limit) query.set('limit', String(params.limit));
if (params?.offset) query.set('offset', String(params.offset));
const qs = query.toString();
return this.request<{
data: Check[];
meta: { total: number; limit: number; offset: number };
}>(`/monitors/${monitorId}/checks${qs ? `?${qs}` : ''}`);
}
// ── Incidents ─────────────────────────────────────────
async listIncidents(params?: { limit?: number; offset?: number; monitorId?: string }) {
const query = new URLSearchParams();
if (params?.limit) query.set('limit', String(params.limit));
if (params?.offset) query.set('offset', String(params.offset));
if (params?.monitorId) query.set('monitorId', params.monitorId);
const qs = query.toString();
return this.request<{
data: Incident[];
meta: { total: number; limit: number; offset: number };
}>(`/incidents${qs ? `?${qs}` : ''}`);
}
async getIncident(id: string) {
return this.request<{ data: Incident & { updates: IncidentUpdate[] } }>(`/incidents/${id}`);
}
// ── Alert Channels ────────────────────────────────────
async listAlertChannels() {
return this.request<{
data: AlertChannel[];
meta: { total: number };
}>('/alert-channels');
}
async createAlertChannel(input: CreateAlertChannelInput) {
return this.request<{ data: AlertChannel }>('/alert-channels', {
method: 'POST',
body: JSON.stringify(input),
});
}
async deleteAlertChannel(id: string) {
return this.request<{ data: { id: string; deleted: boolean } }>(`/alert-channels/${id}`, {
method: 'DELETE',
});
}
}
// ── Types ───────────────────────────────────────────────
interface Monitor {
id: string;
orgId: string;
name: string;
url: string;
method: string;
intervalSeconds: number;
timeoutSeconds: number;
status: string;
expectedStatusCode: number;
followRedirects: boolean;
headers: Record<string, string> | null;
createdAt: string;
updatedAt: string;
}
interface CreateMonitorInput {
name: string;
url: string;
method?: string;
intervalSeconds?: number;
timeoutSeconds?: number;
expectedStatusCode?: number;
followRedirects?: boolean;
headers?: Record<string, string>;
}
interface Check {
id: string;
monitorId: string;
statusCode: number | null;
latencyMs: number;
isUp: boolean;
error: string | null;
checkedAt: string;
}
interface Incident {
id: string;
monitorId: string;
startedAt: string;
resolvedAt: string | null;
durationSeconds: number | null;
cause: string | null;
acknowledgedAt: string | null;
acknowledgedBy: string | null;
createdAt: string;
monitor?: { id: string; name: string; url: string };
}
interface IncidentUpdate {
id: string;
status: string;
message: string;
createdBy: string;
createdAt: string;
}
interface AlertChannel {
id: string;
orgId: string;
type: string;
name: string;
enabled: boolean;
createdAt: string;
updatedAt: string;
}
interface CreateAlertChannelInput {
type: string;
name: string;
config: Record<string, unknown>;
enabled?: boolean;
}
export { SentroClient };
Usage Examples
Initialize the Client
const client = new SentroClient(process.env.SENTRO_API_KEY!);
List All Monitors
const { data: monitors, meta } = await client.listMonitors();
console.log(`Total monitors: ${meta.total}`);
for (const monitor of monitors) {
console.log(`${monitor.name} (${monitor.status}) - ${monitor.url}`);
}
Create a Monitor
const { data: monitor } = await client.createMonitor({
name: 'Production API',
url: 'https://api.example.com/health',
method: 'GET',
intervalSeconds: 60,
timeoutSeconds: 30,
expectedStatusCode: 200,
headers: {
Accept: 'application/json',
},
});
console.log(`Created monitor: ${monitor.id}`);
Get Check History
const { data: checks, meta } = await client.listChecks('mon_abc123', {
limit: 100,
offset: 0,
});
const upCount = checks.filter((c) => c.isUp).length;
const uptime = ((upCount / checks.length) * 100).toFixed(2);
console.log(`Uptime: ${uptime}% over ${checks.length} checks`);
console.log(`Total checks available: ${meta.total}`);
List Recent Incidents
const { data: incidents } = await client.listIncidents({ limit: 5 });
for (const incident of incidents) {
const status = incident.resolvedAt ? 'RESOLVED' : 'ONGOING';
console.log(`[${status}] ${incident.cause} (${incident.monitor?.name})`);
}
Create a Slack Alert Channel
const { data: channel } = await client.createAlertChannel({
type: 'SLACK',
name: 'Engineering Alerts',
config: {
webhookUrl: 'https://hooks.slack.com/services/T00/B00/xxx',
},
});
console.log(`Created alert channel: ${channel.id}`);
Error Handling
try {
const { data } = await client.getMonitor('non_existent_id');
} catch (error) {
if (error instanceof Error) {
console.error(error.message);
// "API Error [404]: Monitor with id 'non_existent_id' not found"
}
}
Using with Plain Fetch
If you prefer not to use a wrapper, you can call the API directly:
const API_KEY = process.env.SENTRO_API_KEY!;
const response = await fetch('https://api.sentro.dev/v1/monitors', {
headers: {
Authorization: `Bearer ${API_KEY}`,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const { data: monitors } = await response.json();
console.log(monitors);