Перейти к основному содержимому

API-контракты

Endpoint coverage

api-map.md является endpoint registry. Этот файл не дублирует полный DTO для каждой CRUD-строки; все endpoints из api-map.md покрываются platform envelope, pagination, error и idempotency rules плюс DTO/feature docs из таблицы.

API map sectionEndpoint rows coveredContract source
Metrics/metrics*Metrics; features/analytics.md
Dashboards/dashboards*, /widgets/{widgetId}Dashboards; features/dashboards.md
Plans/plans*, /plan-targets/{targetId}/factsPlans; features/planning.md
Tasks/tasks*, /task-templatesTasks; features/task-manager.md
Alerts/alert-rules*, /alerts*Alerts; features/management-tools.md
Data quality/data-sources*, /ingestion-runs, /data-quality/issues*Data quality; features/analytics.md
Management actions/goal-profiles, /goals*, /recommendations*, /diagnostics, /actions*Management action; features/management-tools.md
Admin/settings, /audit-logs, /exportscommon envelope/error/idempotency rules; features/admin.md

Общие DTO

type PaginationQuery = {
page?: number;
perPage?: number;
sort?: string;
};

type PaginationMeta = {
page: number;
perPage: number;
total: number;
};

type SourceRef = {
domain: 'crm' | 'lms' | 'storefront' | 'competitions' | 'task-bank' | 'identity' | 'management';
type: string;
id: string;
};

type Segment = Record<string, string | number | boolean>;

type ApiEnvelope<TData, TMeta = Record<string, unknown>> = {
data: TData | null;
meta?: TMeta;
error?: {
code: string;
message: string;
details?: Record<string, unknown>;
};
};

Metrics

POST /api/v2/management/metrics

type CreateMetricRequest = {
key: string;
title: string;
description?: string;
owner: string;
sourceDomain: SourceRef['domain'];
formula: string;
grain: 'day' | 'week' | 'month' | 'quarter' | 'year';
unit: 'count' | 'rub' | 'percent' | 'minutes' | 'score' | 'ratio';
sensitivityLevel: 'public' | 'internal' | 'financial' | 'personal' | 'restricted';
sourceContract?: Record<string, unknown>;
};

Validation:

  • key в snake.case или domain.metric.name;
  • formula не пустая;
  • sourceDomain входит в разрешённый список;
  • financial, personal, restricted требуют отдельного permission для чтения.

Response 201:

type MetricDto = {
id: string;
key: string;
title: string;
owner: string;
sourceDomain: SourceRef['domain'];
grain: string;
unit: string;
sensitivityLevel: string;
status: 'draft' | 'active' | 'deprecated' | 'archived';
currentVersion: number;
};

GET /api/v2/management/metrics/{metricKey}/values

Query:

type MetricValuesQuery = PaginationQuery & {
periodStart: string;
periodEnd: string;
segment?: Segment;
};

Response:

type MetricValueDto = {
metricKey: string;
periodStart: string;
periodEnd: string;
segment: Segment;
value: string;
qualityStatus: 'complete' | 'partial' | 'stale' | 'failed' | 'unknown';
calculatedAt: string;
};

Dashboards

POST /api/v2/management/dashboards

type CreateDashboardRequest = {
slug: string;
title: string;
description?: string;
audience: 'executive' | 'product' | 'operations' | 'finance' | 'education' | 'custom';
defaultPeriod?: 'day' | 'week' | 'month' | 'quarter' | 'year';
visibilityRule?: Record<string, unknown>;
};

GET /api/v2/management/dashboards/{dashboardId}

type DashboardDto = {
id: string;
slug: string;
title: string;
audience: string;
status: 'draft' | 'review' | 'published' | 'archived';
widgets: DashboardWidgetDto[];
};

type DashboardWidgetDto = {
id: string;
type: 'kpi' | 'line_chart' | 'bar_chart' | 'table' | 'funnel' | 'alert_list' | 'markdown';
title: string;
metricKey?: string;
position: number;
config: Record<string, unknown>;
drilldown?: {
source?: SourceRef;
url?: string;
};
};

POST /api/v2/management/dashboards/{dashboardId}/widgets

type CreateWidgetRequest = {
type: DashboardWidgetDto['type'];
title: string;
metricKey?: string;
position: number;
config?: Record<string, unknown>;
drilldown?: DashboardWidgetDto['drilldown'];
};

Validation:

  • chart/table/kpi widgets требуют metricKey;
  • metricKey должен быть active или deprecated;
  • drilldown.source проверяется через permissions исходного домена.

Plans

POST /api/v2/management/plans

type CreatePlanRequest = {
title: string;
type: 'sales' | 'learning' | 'operations' | 'finance' | 'staffing' | 'product_launch';
ownerUserId: string;
periodStart: string;
periodEnd: string;
scope?: Segment;
};

POST /api/v2/management/plans/{planId}/targets

type CreatePlanTargetRequest = {
metricKey: string;
targetValue: string;
comparisonOperator: 'gte' | 'lte' | 'eq' | 'range';
rangeMin?: string;
rangeMax?: string;
segment?: Segment;
};

Plan response

type PlanDto = {
id: string;
title: string;
type: string;
ownerUserId: string;
periodStart: string;
periodEnd: string;
status: 'draft' | 'review' | 'approved' | 'active' | 'closed' | 'archived' | 'cancelled';
targets: PlanTargetDto[];
};

type PlanTargetDto = {
id: string;
metricKey: string;
targetValue: string;
comparisonOperator: string;
latestFact?: {
factValue: string;
variance: string;
status: 'on_track' | 'at_risk' | 'off_track' | 'unknown';
calculatedAt: string;
};
};

Tasks

POST /api/v2/management/tasks

type CreateTaskRequest = {
title: string;
description?: string;
priority?: 'low' | 'normal' | 'high' | 'urgent';
assigneeUserId?: string;
dueAt?: string;
source?: SourceRef;
deduplicationKey?: string;
};

Validation:

  • title обязателен;
  • dueAt не может быть раньше текущего времени без management.tasks.backdate;
  • deduplicationKey должен быть стабильным для задач из events/alerts;
  • если source указан, пользователь должен иметь доступ к связанному объекту или service scope.

PATCH /api/v2/management/tasks/{taskId}/status

type ChangeTaskStatusRequest = {
status: 'todo' | 'in_progress' | 'blocked' | 'review' | 'done' | 'cancelled';
reason?: string;
};

Response:

type TaskDto = {
id: string;
title: string;
description?: string;
status: 'todo' | 'in_progress' | 'blocked' | 'review' | 'done' | 'cancelled';
priority: 'low' | 'normal' | 'high' | 'urgent';
assigneeUserId?: string;
reporterUserId?: string;
dueAt?: string;
source?: SourceRef;
completedAt?: string;
};

Alerts

POST /api/v2/management/alert-rules

type CreateAlertRuleRequest = {
key: string;
metricKey: string;
condition: {
operator: 'gt' | 'gte' | 'lt' | 'lte' | 'eq' | 'change_percent';
value: string;
window?: string;
};
severity: 'info' | 'warning' | 'critical';
deduplicationKeyTemplate: string;
taskTemplateId?: string;
};

Alert response

type AlertDto = {
id: string;
ruleKey: string;
status: 'open' | 'acknowledged' | 'resolved' | 'dismissed';
severity: 'info' | 'warning' | 'critical';
payload: Record<string, unknown>;
taskId?: string;
openedAt: string;
acknowledgedAt?: string;
resolvedAt?: string;
};

Data quality

type DataQualityIssueDto = {
id: string;
dataSourceKey?: string;
severity: 'info' | 'warning' | 'critical';
status: 'open' | 'acknowledged' | 'resolved' | 'dismissed';
title: string;
details: Record<string, unknown>;
openedAt: string;
resolvedAt?: string;
};

Management action

type ExecuteManagementActionRequest = {
actionType: 'create_task' | 'request_metric_recalculation' | 'send_report' | 'start_plan_approval' | 'create_escalation';
source?: SourceRef;
payload: Record<string, unknown>;
};

type ManagementActionDto = {
id: string;
actionType: string;
status: 'requested' | 'validated' | 'executed' | 'completed' | 'rejected' | 'failed' | 'retried';
source?: SourceRef;
createdAt: string;
completedAt?: string;
};