learning_ai_common_plat/services/mcp-server/src/lib/platform-client.ts

977 lines
28 KiB
TypeScript

import { config } from './config.js';
export interface PlatformClientOptions {
/** Bearer token for the upstream request */
token?: string;
/** x-request-id to propagate */
requestId?: string;
/** x-product-id to forward */
productId?: string;
}
export type RunKind = 'job' | 'agent';
export type RunStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';
export type RunStepStatus =
| 'pending'
| 'running'
| 'succeeded'
| 'failed'
| 'skipped'
| 'cancelled';
export async function platformFetch<T>(
path: string,
init: RequestInit,
opts: PlatformClientOptions
): Promise<T> {
const url = `${config.PLATFORM_SERVICE_URL}${path}`;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
...(opts.requestId ? { 'x-request-id': opts.requestId } : {}),
...(opts.productId ? { 'x-product-id': opts.productId } : {}),
};
const res = await fetch(url, {
...init,
headers: { ...headers, ...(init.headers ?? {}) },
signal: AbortSignal.timeout(10_000),
});
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`platform-service ${init.method ?? 'GET'} ${path}${res.status}: ${body}`);
}
return res.json() as Promise<T>;
}
// ── Telemetry ─────────────────────────────────────────────────────────────────
export interface TelemetryQueryResult {
events: unknown[];
total: number;
continuationToken?: string;
}
export async function telemetryQuery(
params: {
productId: string;
eventType?: string;
from?: string;
to?: string;
limit?: number;
continuationToken?: string;
},
opts: PlatformClientOptions
): Promise<TelemetryQueryResult> {
const qs = new URLSearchParams();
qs.set('productId', params.productId);
if (params.eventType) qs.set('eventType', params.eventType);
if (params.from) qs.set('from', params.from);
if (params.to) qs.set('to', params.to);
qs.set(
'limit',
String(Math.min(params.limit ?? config.QUERY_DEFAULT_LIMIT, config.QUERY_MAX_LIMIT))
);
if (params.continuationToken) qs.set('continuationToken', params.continuationToken);
return platformFetch<TelemetryQueryResult>(`/api/telemetry/query?${qs}`, { method: 'GET' }, opts);
}
export interface TelemetryCluster {
/** Cluster doc ID: ${fingerprint}:${yyyyMM} */
id: string;
/** Partition key: ${productId}:${platform}:${module} */
pk: string;
fingerprint: string;
severity: 'warn' | 'error' | 'fatal';
totalCount: number;
lastSeenAt: string;
firstSeenAt: string;
platform: string;
module: string;
eventName: string;
sampleMessage?: string;
status: 'open' | 'resolved' | 'ignored';
resolvedBy?: string;
resolvedAt?: string;
}
export async function telemetryClusters(
params: { from?: string; to?: string; platform?: string; module?: string },
opts: PlatformClientOptions
): Promise<{ clusters: TelemetryCluster[]; total: number }> {
const qs = new URLSearchParams();
if (params.from) qs.set('from', params.from);
if (params.to) qs.set('to', params.to);
if (params.platform) qs.set('platform', params.platform);
if (params.module) qs.set('module', params.module);
return platformFetch<{ clusters: TelemetryCluster[]; total: number }>(
`/api/telemetry/clusters?${qs}`,
{ method: 'GET' },
opts
);
}
export async function telemetryMetrics(opts: PlatformClientOptions): Promise<unknown> {
return platformFetch<unknown>('/api/telemetry/metrics', { method: 'GET' }, opts);
}
export async function telemetryListPolicies(opts: PlatformClientOptions): Promise<unknown> {
return platformFetch<unknown>('/api/telemetry/policies', { method: 'GET' }, opts);
}
export async function telemetryPreviewPolicy(
body: { targeting?: Record<string, unknown> },
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
'/api/telemetry/policies/preview',
{ method: 'POST', body: JSON.stringify(body) },
opts
);
}
export async function telemetryCreatePolicy(
body: Record<string, unknown>,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
'/api/telemetry/policies',
{ method: 'POST', body: JSON.stringify(body) },
opts
);
}
export async function telemetryUpdatePolicy(
policyId: string,
body: Record<string, unknown>,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
`/api/telemetry/policies/${encodeURIComponent(policyId)}`,
{ method: 'PUT', body: JSON.stringify(body) },
opts
);
}
export async function telemetryDeletePolicy(
policyId: string,
opts: PlatformClientOptions
): Promise<{ success: boolean }> {
return platformFetch<{ success: boolean }>(
`/api/telemetry/policies/${encodeURIComponent(policyId)}`,
{ method: 'DELETE' },
opts
);
}
export async function telemetryUpdateCluster(
clusterId: string,
pk: string,
status: 'open' | 'resolved' | 'ignored',
opts: PlatformClientOptions
): Promise<unknown> {
const qs = new URLSearchParams({ pk });
return platformFetch<unknown>(
`/api/telemetry/clusters/${encodeURIComponent(clusterId)}?${qs}`,
{ method: 'PATCH', body: JSON.stringify({ status }) },
opts
);
}
// ── Runs ──────────────────────────────────────────────────────────────────────
export async function runsCreate(
body: {
id: string;
kind: RunKind;
name: string;
source: string;
triggeredBy?: string;
parentRunId?: string;
queueName?: string;
queueJobId?: string;
input?: Record<string, unknown>;
metadata?: Record<string, unknown>;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch('/api/runs', { method: 'POST', body: JSON.stringify(body) }, opts);
}
export async function runsUpdate(
runId: string,
body: {
status: RunStatus;
output?: Record<string, unknown>;
error?: string;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch(
`/api/runs/${encodeURIComponent(runId)}`,
{ method: 'PATCH', body: JSON.stringify(body) },
opts
);
}
export async function runStepsCreate(
runId: string,
body: {
stepName: string;
order: number;
input?: Record<string, unknown>;
metadata?: Record<string, unknown>;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch(
`/api/runs/${encodeURIComponent(runId)}/steps`,
{ method: 'POST', body: JSON.stringify(body) },
opts
);
}
export async function runStepsUpdate(
runId: string,
stepName: string,
body: {
status: RunStepStatus;
output?: Record<string, unknown>;
error?: string;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch(
`/api/runs/${encodeURIComponent(runId)}/steps/${encodeURIComponent(stepName)}`,
{ method: 'PATCH', body: JSON.stringify(body) },
opts
);
}
// ── AI Budgets ───────────────────────────────────────────────────────────────
export async function aiBudgetsRecordSpend(
body: {
scopeType: 'product' | 'agent';
scopeId: string;
policyId?: string;
agentId?: string;
agentVersionId?: string;
runId?: string;
evaluationRunId?: string;
model?: string;
tokensUsed?: number;
costUsd: number;
source?: string;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch(
'/api/ai-budgets/spend',
{ method: 'POST', body: JSON.stringify(body) },
opts
);
}
// ── Support Cases ────────────────────────────────────────────────────────────
export async function supportCasesCreate(
body: {
orgId?: string;
workspaceId?: string;
requesterUserId?: string;
assignedTo?: string;
title: string;
description?: string;
priority?: 'critical' | 'high' | 'medium' | 'low';
source?: 'manual' | 'agent' | 'telemetry' | 'customer';
runId?: string;
reviewId?: string;
knowledgeBaseId?: string;
tags?: string[];
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch('/api/support/cases', { method: 'POST', body: JSON.stringify(body) }, opts);
}
// ── Diagnostics ───────────────────────────────────────────────────────────────
export interface DebugSession {
id: string;
productId: string;
status: string;
collectionLevel: string;
captureLogs: boolean;
captureNetwork: boolean;
captureScreenshots: boolean;
maxDurationMinutes: number;
logCount: number;
traceCount: number;
createdAt: string;
expiresAt: string;
targetUserId?: string;
targetAnonymousId?: string;
}
export async function diagnosticsListSessions(
params: {
productId?: string;
status?: string;
limit?: number;
offset?: number;
},
opts: PlatformClientOptions
): Promise<{ sessions: DebugSession[]; total: number }> {
const qs = new URLSearchParams();
if (params.productId) qs.set('productId', params.productId);
if (params.status) qs.set('status', params.status);
qs.set(
'limit',
String(Math.min(params.limit ?? config.QUERY_DEFAULT_LIMIT, config.QUERY_MAX_LIMIT))
);
if (params.offset) qs.set('offset', String(params.offset));
return platformFetch<{ sessions: DebugSession[]; total: number }>(
`/api/diagnostics/sessions?${qs}`,
{ method: 'GET' },
opts
);
}
// ── Reviews ──────────────────────────────────────────────────────────────────
export async function reviewsCreate(
body: {
title: string;
description: string;
category: string;
priority?: 'low' | 'normal' | 'high' | 'urgent';
scope?: 'org' | 'workspace';
orgId: string;
workspaceId?: string;
assignedTo?: string;
runId?: string;
source: string;
actionType: string;
metadata?: Record<string, unknown>;
dueAt?: string;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch('/api/reviews', { method: 'POST', body: JSON.stringify(body) }, opts);
}
export async function diagnosticsCreateSession(
body: {
productId: string;
targetUserId?: string;
targetAnonymousId?: string;
collectionLevel?: 'standard' | 'debug' | 'trace';
captureLogs?: boolean;
captureNetwork?: boolean;
maxDurationMinutes?: number;
},
opts: PlatformClientOptions
): Promise<DebugSession> {
return platformFetch<DebugSession>(
'/api/diagnostics/sessions',
{ method: 'POST', body: JSON.stringify(body) },
opts
);
}
export async function diagnosticsGetSession(
sessionId: string,
opts: PlatformClientOptions
): Promise<DebugSession> {
return platformFetch<DebugSession>(
`/api/diagnostics/sessions/${encodeURIComponent(sessionId)}`,
{ method: 'GET' },
opts
);
}
export async function diagnosticsUpdateSession(
sessionId: string,
body: { status?: string; collectionLevel?: string; maxDurationMinutes?: number },
opts: PlatformClientOptions
): Promise<DebugSession> {
return platformFetch<DebugSession>(
`/api/diagnostics/sessions/${encodeURIComponent(sessionId)}`,
{ method: 'PATCH', body: JSON.stringify(body) },
opts
);
}
export async function diagnosticsGetLogs(
sessionId: string,
params: { level?: string; from?: string; to?: string; limit?: number },
opts: PlatformClientOptions
): Promise<{ logs: unknown[]; continuationToken?: string }> {
const qs = new URLSearchParams();
if (params.level) qs.set('level', params.level);
if (params.from) qs.set('from', params.from);
if (params.to) qs.set('to', params.to);
qs.set(
'limit',
String(Math.min(params.limit ?? config.QUERY_DEFAULT_LIMIT, config.QUERY_MAX_LIMIT))
);
return platformFetch<{ logs: unknown[]; continuationToken?: string }>(
`/api/diagnostics/sessions/${encodeURIComponent(sessionId)}/logs?${qs}`,
{ method: 'GET' },
opts
);
}
export async function diagnosticsGetTraces(
sessionId: string,
params: { limit?: number; continuationToken?: string },
opts: PlatformClientOptions
): Promise<{ traces: unknown[]; continuationToken?: string }> {
const qs = new URLSearchParams();
qs.set(
'limit',
String(Math.min(params.limit ?? config.QUERY_DEFAULT_LIMIT, config.QUERY_MAX_LIMIT))
);
if (params.continuationToken) qs.set('continuationToken', params.continuationToken);
return platformFetch<{ traces: unknown[]; continuationToken?: string }>(
`/api/diagnostics/sessions/${encodeURIComponent(sessionId)}/traces?${qs}`,
{ method: 'GET' },
opts
);
}
// ── Tracker — items ───────────────────────────────────────────────────────────
export interface TrackerItemDoc {
id: string;
productId: string;
type: string;
status: string;
priority: string;
title: string;
description?: string;
labels?: string[];
assignee?: string | null;
reportedBy?: string;
source?: string;
visibility?: string;
voteCount: number;
commentCount: number;
targetRelease?: string | null;
createdAt: string;
updatedAt: string;
}
export function trackerItemsList(
params: {
productId?: string;
type?: string;
status?: string;
priority?: string;
q?: string;
labels?: string;
visibility?: string;
sortBy?: string;
sortOrder?: string;
limit?: number;
offset?: number;
},
opts: PlatformClientOptions
): Promise<{ items: TrackerItemDoc[]; total: number; limit: number; offset: number }> {
const qs = new URLSearchParams();
if (params.productId) qs.set('productId', params.productId);
if (params.type) qs.set('type', params.type);
if (params.status) qs.set('status', params.status);
if (params.priority) qs.set('priority', params.priority);
if (params.q) qs.set('q', params.q);
if (params.labels) qs.set('labels', params.labels);
if (params.visibility) qs.set('visibility', params.visibility);
if (params.sortBy) qs.set('sortBy', params.sortBy);
if (params.sortOrder) qs.set('sortOrder', params.sortOrder);
qs.set(
'limit',
String(Math.min(params.limit ?? config.QUERY_DEFAULT_LIMIT, config.QUERY_MAX_LIMIT))
);
if (params.offset !== undefined) qs.set('offset', String(params.offset));
return platformFetch<{ items: TrackerItemDoc[]; total: number; limit: number; offset: number }>(
`/api/items?${qs}`,
{ method: 'GET' },
opts
);
}
export function trackerItemsStats(opts: PlatformClientOptions): Promise<{
total: number;
byType: Record<string, number>;
byStatus: Record<string, number>;
byPriority: Record<string, number>;
}> {
return platformFetch<{
total: number;
byType: Record<string, number>;
byStatus: Record<string, number>;
byPriority: Record<string, number>;
}>('/api/items/stats', { method: 'GET' }, opts);
}
export function trackerItemsGet(
itemId: string,
opts: PlatformClientOptions
): Promise<TrackerItemDoc> {
return platformFetch<TrackerItemDoc>(
`/api/items/${encodeURIComponent(itemId)}`,
{ method: 'GET' },
opts
);
}
export function trackerItemsCreate(
input: {
productId?: string;
type: string;
priority: string;
title: string;
description?: string;
labels?: string[];
assignee?: string;
source?: string;
visibility?: string;
targetRelease?: string;
},
opts: PlatformClientOptions
): Promise<TrackerItemDoc> {
return platformFetch<TrackerItemDoc>(
'/api/items',
{ method: 'POST', body: JSON.stringify(input) },
opts
);
}
export function trackerItemsUpdateStatus(
itemId: string,
status: string,
opts: PlatformClientOptions
): Promise<TrackerItemDoc> {
return platformFetch<TrackerItemDoc>(
`/api/items/${encodeURIComponent(itemId)}/status`,
{ method: 'PATCH', body: JSON.stringify({ status }) },
opts
);
}
export function trackerItemsDelete(
itemId: string,
opts: PlatformClientOptions
): Promise<{ success: boolean }> {
return platformFetch<{ success: boolean }>(
`/api/items/${encodeURIComponent(itemId)}`,
{ method: 'DELETE' },
opts
);
}
// ── Tracker — votes ───────────────────────────────────────────────────────────
export function trackerVotesToggle(
itemId: string,
opts: PlatformClientOptions
): Promise<{ voted: boolean; voteCount: number }> {
return platformFetch<{ voted: boolean; voteCount: number }>(
`/api/items/${encodeURIComponent(itemId)}/vote`,
{ method: 'POST', body: '{}' },
opts
);
}
export function trackerVotesList(
itemId: string,
opts: PlatformClientOptions
): Promise<{ votes: unknown[]; count: number }> {
return platformFetch<{ votes: unknown[]; count: number }>(
`/api/items/${encodeURIComponent(itemId)}/votes`,
{ method: 'GET' },
opts
);
}
// ── Tracker — comments ────────────────────────────────────────────────────────
export function trackerCommentsList(
itemId: string,
opts: PlatformClientOptions
): Promise<{ comments: unknown[]; count: number }> {
return platformFetch<{ comments: unknown[]; count: number }>(
`/api/items/${encodeURIComponent(itemId)}/comments`,
{ method: 'GET' },
opts
);
}
export function trackerCommentsAdd(
itemId: string,
body: string,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
`/api/items/${encodeURIComponent(itemId)}/comments`,
{ method: 'POST', body: JSON.stringify({ body }) },
opts
);
}
export function trackerCommentsDelete(
itemId: string,
commentId: string,
opts: PlatformClientOptions
): Promise<{ success: boolean }> {
return platformFetch<{ success: boolean }>(
`/api/items/${encodeURIComponent(itemId)}/comments/${encodeURIComponent(commentId)}`,
{ method: 'DELETE' },
opts
);
}
// ── Tracker — public roadmap ──────────────────────────────────────────────────
export function trackerPublicRoadmap(
params: {
productId?: string;
type?: string;
status?: string;
q?: string;
sortBy?: string;
sortOrder?: string;
limit?: number;
offset?: number;
},
opts: PlatformClientOptions
): Promise<{ items: TrackerItemDoc[]; total: number }> {
const qs = new URLSearchParams();
if (params.productId) qs.set('productId', params.productId);
if (params.type) qs.set('type', params.type);
if (params.status) qs.set('status', params.status);
if (params.q) qs.set('q', params.q);
if (params.sortBy) qs.set('sortBy', params.sortBy);
if (params.sortOrder) qs.set('sortOrder', params.sortOrder);
qs.set(
'limit',
String(Math.min(params.limit ?? config.QUERY_DEFAULT_LIMIT, config.QUERY_MAX_LIMIT))
);
if (params.offset !== undefined) qs.set('offset', String(params.offset));
return platformFetch<{ items: TrackerItemDoc[]; total: number }>(
`/api/public/roadmap?${qs}`,
{ method: 'GET' },
opts
);
}
export function trackerPublicStats(opts: PlatformClientOptions): Promise<{
total: number;
byStatus: Record<string, number>;
byType: Record<string, number>;
totalVotes: number;
}> {
return platformFetch<{
total: number;
byStatus: Record<string, number>;
byType: Record<string, number>;
totalVotes: number;
}>('/api/public/roadmap/stats', { method: 'GET' }, opts);
}
// ── Flags ─────────────────────────────────────────────────────────────────────
export interface FeatureFlagDoc {
id: string;
productId: string;
key: string;
enabled: boolean;
percentage: number;
description?: string;
platforms: string[];
regions?: string[];
createdAt: string;
updatedAt: string;
}
export function flagsList(opts: PlatformClientOptions): Promise<{ flags: FeatureFlagDoc[] }> {
return platformFetch<{ flags: FeatureFlagDoc[] }>('/api/flags', { method: 'GET' }, opts);
}
export function flagsGet(key: string, opts: PlatformClientOptions): Promise<FeatureFlagDoc> {
return platformFetch<FeatureFlagDoc>(
`/api/flags/${encodeURIComponent(key)}`,
{ method: 'GET' },
opts
);
}
export async function flagsUpsert(
key: string,
input: {
enabled: boolean;
percentage?: number;
description?: string;
platforms?: string[];
regions?: string[];
},
opts: PlatformClientOptions
): Promise<FeatureFlagDoc> {
// Try update first; fall back to create if not found
try {
return await platformFetch<FeatureFlagDoc>(
`/api/flags/${encodeURIComponent(key)}`,
{ method: 'PUT', body: JSON.stringify(input) },
opts
);
} catch (err) {
if (err instanceof Error && err.message.includes('404')) {
return platformFetch<FeatureFlagDoc>(
'/api/flags',
{ method: 'POST', body: JSON.stringify({ key, ...input }) },
opts
);
}
throw err;
}
}
export function flagsDelete(
key: string,
opts: PlatformClientOptions
): Promise<{ success: boolean }> {
return platformFetch<{ success: boolean }>(
`/api/flags/${encodeURIComponent(key)}`,
{ method: 'DELETE' },
opts
);
}
export function flagsKillSwitch(
input: { platform?: string; keys?: string[] },
opts: PlatformClientOptions
): Promise<{ disabled: string[]; count: number }> {
return platformFetch<{ disabled: string[]; count: number }>(
'/api/flags/kill',
{ method: 'POST', body: JSON.stringify(input) },
opts
);
}
// ── Jobs ──────────────────────────────────────────────────────────────────────
export function jobsList(opts: PlatformClientOptions): Promise<unknown[]> {
return platformFetch<unknown[]>('/api/jobs', { method: 'GET' }, opts);
}
export function jobsGet(id: string, opts: PlatformClientOptions): Promise<unknown> {
return platformFetch<unknown>(`/api/jobs/${encodeURIComponent(id)}`, { method: 'GET' }, opts);
}
export function jobsTrigger(jobName: string, opts: PlatformClientOptions): Promise<unknown> {
return platformFetch<unknown>(
'/api/jobs/trigger',
{ method: 'POST', body: JSON.stringify({ jobName }) },
opts
);
}
export function jobsListRuns(
name: string,
limit: number,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
`/api/jobs/${encodeURIComponent(name)}/runs?limit=${limit}`,
{ method: 'GET' },
opts
);
}
// ── Maintenance ───────────────────────────────────────────────────────────────
export function maintenanceGetCurrent(opts: PlatformClientOptions): Promise<unknown> {
return platformFetch<unknown>('/api/settings/maintenance/full', { method: 'GET' }, opts);
}
export function maintenanceSet(
input: {
mode: 'none' | 'scheduled' | 'active' | 'emergency';
message?: string;
affectedServices?: string[];
scheduledStart?: string;
scheduledEnd?: string;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
'/api/settings/maintenance',
{ method: 'PUT', body: JSON.stringify(input) },
opts
);
}
export function maintenanceScheduleWindow(
input: {
title: string;
message: string;
mode: string;
scheduledStart: string;
scheduledEnd: string;
affectedServices?: string[];
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
'/api/settings/maintenance/schedule',
{ method: 'POST', body: JSON.stringify(input) },
opts
);
}
export function maintenanceGetSchedule(opts: PlatformClientOptions): Promise<unknown[]> {
return platformFetch<unknown[]>('/api/settings/maintenance/schedule', { method: 'GET' }, opts);
}
export function maintenanceDeleteWindow(
windowId: string,
opts: PlatformClientOptions
): Promise<{ success: boolean }> {
return platformFetch<{ success: boolean }>(
`/api/settings/maintenance/schedule/${encodeURIComponent(windowId)}`,
{ method: 'DELETE' },
opts
);
}
// ── Settings ──────────────────────────────────────────────────────────────────────────────────
export function settingsGet(opts: PlatformClientOptions): Promise<unknown> {
return platformFetch<unknown>('/api/settings', { method: 'GET' }, opts);
}
export function settingsUpdate(
settings: Record<string, unknown>,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
'/api/settings',
{ method: 'PUT', body: JSON.stringify({ settings }) },
opts
);
}
export function settingsCheckKillSwitch(
productId: string,
opts: Pick<PlatformClientOptions, 'requestId'>
): Promise<{ enabled: boolean; disabled: boolean; message: string }> {
return platformFetch<{ enabled: boolean; disabled: boolean; message: string }>(
`/api/settings/kill-switch?productId=${encodeURIComponent(productId)}`,
{ method: 'GET' },
opts
);
}
// ── Webhooks ──────────────────────────────────────────────────────────────────
export function webhooksListSubscriptions(
productId: string,
opts: PlatformClientOptions
): Promise<unknown[]> {
return platformFetch<unknown[]>(
`/api/webhooks/subscriptions?productId=${encodeURIComponent(productId)}`,
{ method: 'GET' },
opts
);
}
export function webhooksCreate(
input: {
productId: string;
url: string;
events: string[];
description?: string;
enabled?: boolean;
},
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
'/api/webhooks/subscriptions',
{ method: 'POST', body: JSON.stringify(input) },
opts
);
}
export function webhooksGet(
id: string,
productId: string,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
`/api/webhooks/subscriptions/${encodeURIComponent(id)}?productId=${encodeURIComponent(productId)}`,
{ method: 'GET' },
opts
);
}
export function webhooksUpdate(
id: string,
productId: string,
input: { url?: string; events?: string[]; enabled?: boolean; description?: string },
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
`/api/webhooks/subscriptions/${encodeURIComponent(id)}?productId=${encodeURIComponent(productId)}`,
{ method: 'PATCH', body: JSON.stringify(input) },
opts
);
}
export function webhooksDelete(
id: string,
productId: string,
opts: PlatformClientOptions
): Promise<{ success: boolean }> {
return platformFetch<{ success: boolean }>(
`/api/webhooks/subscriptions/${encodeURIComponent(id)}?productId=${encodeURIComponent(productId)}`,
{ method: 'DELETE' },
opts
);
}
export function webhooksListDeliveries(
id: string,
limit: number,
opts: PlatformClientOptions
): Promise<unknown> {
return platformFetch<unknown>(
`/api/webhooks/subscriptions/${encodeURIComponent(id)}/deliveries?limit=${limit}`,
{ method: 'GET' },
opts
);
}
export function webhooksTest(
id: string,
productId: string,
opts: PlatformClientOptions
): Promise<{ success: boolean; message: string }> {
return platformFetch<{ success: boolean; message: string }>(
`/api/webhooks/subscriptions/${encodeURIComponent(id)}/test?productId=${encodeURIComponent(productId)}`,
{ method: 'POST', body: '{}' },
opts
);
}
export function webhooksRotateSecret(
id: string,
productId: string,
opts: PlatformClientOptions
): Promise<{ secret: string; message: string }> {
return platformFetch<{ secret: string; message: string }>(
`/api/webhooks/subscriptions/${encodeURIComponent(id)}/rotate-secret?productId=${encodeURIComponent(productId)}`,
{ method: 'POST', body: '{}' },
opts
);
}