openapi: 3.0.3 info: title: Telemt API gateway — aggregate API description: > Эндпоинты под префиксом /api/agg на шлюзе telemt-api. Базовый URL задаётся listen шлюза (например http://127.0.0.1:8080). version: 1.0.0 paths: /api/agg/summary: get: summary: Сводка флота и топы пользователей parameters: - $ref: '#/components/parameters/aliases' - name: top_n in: query schema: { type: integer, minimum: 1, maximum: 1000, default: 10 } responses: '200': description: OK content: application/json: schema: { $ref: '#/components/schemas/AggEnvelopeSummary' } /api/agg/traffic: get: summary: Трафик по пользователям и серверам parameters: - $ref: '#/components/parameters/aliases' responses: '200': description: OK content: application/json: schema: { $ref: '#/components/schemas/AggEnvelopeTrafficRows' } /api/agg/unique-ips: get: summary: Уникальные IP с привязкой к серверам (и опционально GeoIP) parameters: - $ref: '#/components/parameters/aliases' - name: geo in: query description: 'false — не обогащать GeoIP' schema: { type: string, enum: ['false', 'true'] } responses: '200': description: OK content: application/json: schema: { $ref: '#/components/schemas/AggEnvelopeUniqueIPs' } /api/agg/users: get: summary: Список пользователей с merge по серверам parameters: - $ref: '#/components/parameters/aliases' - name: include_links in: query schema: { type: string, enum: ['true', 'false'] } - name: min_total_megabytes in: query schema: { type: number, format: float } - name: min_total_octets in: query schema: { type: string } responses: '200': description: OK content: application/json: schema: { $ref: '#/components/schemas/AggEnvelopeUsersRows' } /api/agg/user/{username}: get: summary: Один пользователь (тот же объект, что в users[]) parameters: - name: username in: path required: true schema: type: string pattern: '^[A-Za-z0-9_.-]+$' - $ref: '#/components/parameters/aliases' - name: include_links in: query schema: { type: string, enum: ['true', 'false'] } responses: '200': description: OK content: application/json: schema: { $ref: '#/components/schemas/AggEnvelopeUsersRow' } '404': description: Пользователь не найден ни на одном upstream /api/agg/fleet-status: get: summary: Health + system/info по всем выбранным серверам parameters: - $ref: '#/components/parameters/aliases' responses: '200': description: OK content: application/json: schema: { $ref: '#/components/schemas/AggEnvelopeFleetStatus' } components: parameters: aliases: name: aliases in: query description: Список алиасов через запятую schema: { type: string } schemas: AggSuccessBase: type: object required: [ok, data, generated_at] properties: ok: { type: boolean, enum: [true] } generated_at: { type: string, format: date-time } partial: { type: boolean, description: true если часть upstream недоступна } AggEnvelopeSummary: allOf: - $ref: '#/components/schemas/AggSuccessBase' - type: object properties: data: type: object description: SummaryData (см. реализацию / доку AGGREGATE.md) AggEnvelopeTrafficRows: allOf: - $ref: '#/components/schemas/AggSuccessBase' - type: object properties: data: type: array items: { $ref: '#/components/schemas/TrafficRow' } AggEnvelopeUniqueIPs: allOf: - $ref: '#/components/schemas/AggSuccessBase' - type: object properties: data: type: array items: { $ref: '#/components/schemas/UniqueIPsRow' } AggEnvelopeUsersRows: allOf: - $ref: '#/components/schemas/AggSuccessBase' - type: object properties: data: type: array items: { $ref: '#/components/schemas/UsersRow' } AggEnvelopeUsersRow: allOf: - $ref: '#/components/schemas/AggSuccessBase' - type: object properties: data: { $ref: '#/components/schemas/UsersRow' } AggEnvelopeFleetStatus: allOf: - $ref: '#/components/schemas/AggSuccessBase' - type: object properties: data: { $ref: '#/components/schemas/FleetStatusData' } TrafficRow: type: object properties: username: { type: string } servers: type: object additionalProperties: $ref: '#/components/schemas/TrafficServerStats' TrafficServerStats: type: object properties: total_megabytes: { type: number, format: float } current_connections: { type: integer, format: int64 } revision: { type: string } UniqueIPsRow: type: object properties: username: { type: string } ips: type: array items: { $ref: '#/components/schemas/IPAssignments' } IPAssignments: type: object properties: ip: { type: string } active_on_servers: type: array items: { type: string } recent_on_servers: type: array items: { type: string } primary_server: { type: string, nullable: true } country_code: { type: string, nullable: true } country_name: { type: string, nullable: true } city_name: { type: string, nullable: true } latitude: { type: number, format: float, nullable: true } longitude: { type: number, format: float, nullable: true } asn: { type: integer, format: int64, nullable: true } as_organization: { type: string, nullable: true } UserLinks: type: object properties: classic: type: array items: { type: string } secure: type: array items: { type: string } tls: type: array items: { type: string } UsersRow: type: object properties: username: { type: string } total_megabytes: { type: number, format: float } by_server: type: object additionalProperties: $ref: '#/components/schemas/TrafficServerStats' links: { $ref: '#/components/schemas/UserLinks' } active_unique_ips: { type: integer, format: int64 } recent_unique_ips: { type: integer, format: int64 } user_ad_tag: { type: string, nullable: true } max_tcp_conns: { type: integer, format: int64, nullable: true } expiration_rfc3339: { type: string, nullable: true } data_quota_bytes: { type: integer, format: int64, nullable: true } max_unique_ips: { type: integer, format: int64, nullable: true } HealthData: type: object properties: status: { type: string } read_only: { type: boolean } SystemInfoData: type: object properties: version: { type: string } target_arch: { type: string } target_os: { type: string } build_profile: { type: string } git_commit: { type: string, nullable: true } build_time_utc: { type: string, nullable: true } rustc_version: { type: string, nullable: true } process_started_at_epoch_secs: { type: integer, format: int64 } uptime_seconds: { type: number, format: float } config_path: { type: string } config_hash: { type: string } config_reload_count: { type: integer, format: int64 } last_config_reload_epoch_secs: { type: integer, format: int64, nullable: true } FleetServerStatus: type: object properties: alias: { type: string } ok: { type: boolean } health_ok: { type: boolean } health_http_status: { type: integer } health_latency_ms: { type: integer, format: int64 } health_error: { type: string } health_revision: { type: string } health: { $ref: '#/components/schemas/HealthData' } system_info_ok: { type: boolean } system_info_http_status: { type: integer } system_info_latency_ms: { type: integer, format: int64 } system_info_error: { type: string } system_info_revision: { type: string } system_info: { $ref: '#/components/schemas/SystemInfoData' } FleetStatusData: type: object properties: servers: type: array items: { $ref: '#/components/schemas/FleetServerStatus' } servers_total: { type: integer } servers_all_ok: { type: integer } servers_failed: { type: integer }