{"openapi":"3.1.0","info":{"title":"Linkostar Backend API","description":"# Linkostar IoT Hub Management Platform API\n\nThis API provides comprehensive management for IoT hubs, devices, and telemetry data.\n\n## API Structure\n\n### /platform/** - Platform Administration\n- **Authentication**: Platform Admin JWT required\n- **Features**: Agent release management, Update policies, Hub jobs, Audit logs, Hub blocking\n- **Scope**: Global platform operations\n\n### /tenant/** - Tenant Management\n- **Authentication**: User JWT with persona_uuid or API Key (X-API-Key header)\n- **Features**: Hub management, Device management, BLE routes, Tenant audit logs\n- **Scope**: Tenant-specific (tenant_uuid based)\n\n### /v1/** - Hub API\n- **Authentication**: Hub authentication token required\n- **Features**: Telemetry upload, Log upload, BLE event upload, Agent updates, Job execution\n- **Scope**: Single hub operations\n- **Rate Limits**: 100 requests/minute per endpoint per unit\n\n### /auth/** - Authentication\n- **Authentication**: Public or user credentials\n- **Features**: User login/registration, Token refresh\n\n## Authentication Methods\n\n### 1. User JWT (Bearer-JWT)\n- **Used for**: `/platform/**`, `/tenant/**` endpoints\n- **Header**: `Authorization: Bearer <jwt_token>`\n- **Token contains**: user_uuid, persona_uuid, roles\n- **Obtain via**: `POST /auth/login`\n\n### 2. Hub Token (Bearer-Hub)\n- **Used for**: `/v1/**` endpoints\n- **Header**: `Authorization: Bearer <hub_token>`\n- **Token contains**: hub_uuid, tenant_uuid\n- **Obtain via**: Hub claiming process\n\n### 3. API Key (ApiKeyAuth)\n- **Used for**: `/tenant/**` endpoints (Open API)\n- **Header**: `X-API-Key: ls_your_key_here`\n- **Obtain via**: Web portal `/tenant/api-keys`\n\n## Pagination\n\nList endpoints support pagination with query parameters:\n- `page`: Page number (0-indexed, default: 0)\n- `size`: Items per page (default: 20, max: 100)\n\n## Rate Limiting\n\nHub upload endpoints are rate limited per tenant_uuid:\n- **Telemetry**: 100 requests/minute\n- **Logs**: 100 requests/minute\n- **BLE events**: 100 requests/minute\n- **Response**: 429 Too Many Requests when exceeded\n","contact":{"name":"Makeisle","url":"https://makeisle.com","email":"support@makeisle.com"},"license":{"name":"Proprietary","url":"https://makeisle.com/license"},"version":"1.0.0"},"servers":[{"url":"http://localhost:8080","description":"Local Development Server"},{"url":"https://api.linkostar.com","description":"Production Server"}],"tags":[{"name":"Tenant - Supplier OAuth Config (self-service)","description":"TENANT_ADMIN이 자기 supplier의 OAuth client config을 직접 등록"},{"name":"Tenant - Device Protocols","description":"Device protocol catalog management"},{"name":"Tenant - Consent","description":"Consent settings and records management"},{"name":"Tenant Transfer","description":"Tenant 소유권 이전 응답 API"},{"name":"Hub - Agent","description":"Agent release information for hubs"},{"name":"Hub - Adapter Inventory","description":"Hub Agent → backend BlueZ adapter snapshot"},{"name":"Tenant - Supplier Bundles","description":"Hub release-package management"},{"name":"Tenant - Personas","description":"Persona membership + invitations for current tenant"},{"name":"Tenant - Downloads","description":"Tenant-gated installer/OS/agent downloads"},{"name":"Invitations","description":"Accept flow for member invitations"},{"name":"Tenant - Device Versions","description":"Device version catalog management"},{"name":"Webhook - Supplier Permission","description":"Supplier 권한 변경 알림 수신"},{"name":"Tenant - Agent Releases","description":"Read-only browsing of hub-agent OTA releases"},{"name":"Tenant - Device UI","description":"Device UI (D3) schema management"},{"name":"App - Devices","description":"Device management for app users"},{"name":"Tenant - Dashboard","description":"Aggregate stats for the console dashboard / monitoring"},{"name":"App - Bundle Catalog","description":"Published supplier bundle 카탈로그 (계정 연동 진입점 포함)"},{"name":"Platform - Supplier OAuth Config","description":"Supplier OAuth client config registration"},{"name":"Platform - Activation Events","description":"device_activation_event audit + sdx-web sync 상태 조회"},{"name":"App - Device UI Invoke (M4)","description":"device_ui http_get/http_post invoke 서버측 프록시"},{"name":"Hub - Claim & Auth","description":"Hub claim and token management"},{"name":"Tenant - Agent Update Policies","description":"Hub-agent OTA rollout policies (tenant-scoped)"},{"name":"Hub - Scan Config","description":"BLE scan 대상(matcher 패턴 + protocol JSON + hub-layer routes) 일괄 조회"},{"name":"App - Profile","description":"User profile management for app users"},{"name":"Tenant - Setup Delegation","description":"Delegate hub setup rights to other users"},{"name":"Tenant Audit Logs","description":"Tenant-level audit log management"},{"name":"Platform - Registration Events (Outbox)","description":"supplier_registration_event outbox 진단/재시도"},{"name":"App - Consent","description":"Consent management for app users"},{"name":"Tenant - Hub Adapters","description":"tenant 별 hub adapter inventory + role / supplier 할당"},{"name":"App - Supplier Link","description":"Supplier OAuth account linking for the app"},{"name":"Tenant - Action Definitions","description":"Protocol action definition management for D3 UI state machines"},{"name":"Tenants","description":"Tenant(=Supplier) 관리 API"},{"name":"App - Action Definitions","description":"Read-only access to protocol action definitions for app users"},{"name":"App - Notifications","description":"Notification management for app users"},{"name":"Hub Monitoring","description":"APIs for monitoring hub operations (tenant scope)"},{"name":"Hub - DesiredState","description":"Pull-based fallback for the desired state hub-agent reconciler consumes"},{"name":"Platform - Agent Update Policies","description":"Agent update policy management (admin only)"},{"name":"Tenant - Device Catalog","description":"Device model (catalog header) management"},{"name":"Tenant - Device Match Identifiers","description":"AUTO_ON_MATCH 디바이스 식별자(iBeacon/serviceUuid/manufacturer prefix 등) CRUD"},{"name":"Tenant - Hub Installed Apps","description":"Monitor supplier apps installed on a hub"},{"name":"Tenant - Hubs","description":"Hub management for tenant users"},{"name":"Tenant - Notification Settings","description":"Notification preference management"},{"name":"Hub - Jobs","description":"Hub job event reporting"},{"name":"Tenant - API Keys","description":"API key management for Open API access"},{"name":"App - Hubs","description":"Hub management for app users"},{"name":"Platform Admin","description":"Platform administration endpoints"},{"name":"Me - Notifications","description":"Per-persona session notifications"},{"name":"Platform - Agent Releases","description":"Agent release management (admin only)"},{"name":"Public - Installer Auto-Update","description":"electron-updater generic provider endpoint (latest.yml + binary)"},{"name":"Tenant - Billing/Entitlement","description":"Subscription entitlements + sdx-web billing"},{"name":"Platform Hub Management","description":"Platform-level hub management operations"},{"name":"Tenant - Devices","description":"Device instance management for tenant users"},{"name":"Hub - Telemetry & Logs","description":"Hub telemetry and log recording"},{"name":"Tenant - Manuals","description":"Device manual management"},{"name":"Hub API","description":"Hub/Agent API endpoints"},{"name":"Platform - Hub Jobs","description":"Hub job management (admin only)"},{"name":"Hub - mTLS","description":"X.509 client certificate provisioning"},{"name":"Health","description":"Application health check"},{"name":"Tenant","description":"Tenant user endpoints"},{"name":"Tenant - External Endpoints (M4)","description":"device_ui invoke 대상 외부 엔드포인트 등록·도메인 인증·관리"},{"name":"SSE Stream","description":"Server-Sent Events for real-time monitoring"},{"name":"Platform Audit Logs","description":"Platform-level audit log management"},{"name":"BLE Query (Legacy)","description":"Legacy BLE query APIs - use /tenant/ble instead"},{"name":"Platform - Permission Cache","description":"supplier_permission_cache 조회/무효화"},{"name":"Hub - Device Query","description":"Hub-side device discovery + activation"}],"paths":{"/tenant/supplier-oauth-config":{"get":{"tags":["Tenant - Supplier OAuth Config (self-service)"],"summary":"현재 tenant의 OAuth config 조회 (없으면 404)","description":"secret 값은 응답에 노출되지 않음. registrationSharedSecretSet 플래그로 존재 여부만.","operationId":"get","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}},"put":{"tags":["Tenant - Supplier OAuth Config (self-service)"],"summary":"UPSERT — 즉시 등록 또는 (require-approval=true일 때) 승인 큐 적재","description":"client_secret + registration_shared_secret은 plaintext로 받아 즉시 AES-GCM 암호화 저장. 응답에 secret 미노출.","operationId":"upsert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierOauthConfigRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}},"delete":{"tags":["Tenant - Supplier OAuth Config (self-service)"],"summary":"현재 tenant의 OAuth config 삭제","operationId":"delete","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}}},"/tenant/supplier-bundles/{bundleUuid}/pipelines":{"get":{"tags":["Tenant - Supplier Bundles"],"summary":"번들에 포함된 파이프라인 uuid 목록","operationId":"listPipelines","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListUUID"}}}}}},"put":{"tags":["Tenant - Supplier Bundles"],"summary":"번들 포함 파이프라인 목록 교체 (uuid 배열)","operationId":"replacePipelines","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"type":"string","format":"uuid"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListUUID"}}}}}}},"/tenant/supplier-bundles/{bundleUuid}/devices":{"get":{"tags":["Tenant - Supplier Bundles"],"operationId":"listDevices","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListObject"}}}}}},"put":{"tags":["Tenant - Supplier Bundles"],"summary":"Replace devices list (full overwrite)","operationId":"replaceDevices","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BundleDeviceRefRequest"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListObject"}}}}}}},"/tenant/supplier-bundles/{bundleUuid}/apps":{"get":{"tags":["Tenant - Supplier Bundles"],"operationId":"listApps","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListObject"}}}}}},"put":{"tags":["Tenant - Supplier Bundles"],"summary":"Replace apps list (full overwrite)","operationId":"replaceApps","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BundleAppRefRequest"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListObject"}}}}}}},"/tenant/notification-settings":{"get":{"tags":["Tenant - Notification Settings"],"summary":"List notification settings for current user within tenant context","operationId":"listSettings","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListNotificationSettingResponse"}}}}}},"put":{"tags":["Tenant - Notification Settings"],"summary":"Upsert a single notification setting (by type+channel)","operationId":"upsertSetting","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertNotificationSettingRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseNotificationSettingResponse"}}}}}}},"/tenant/external-endpoints/{id}":{"get":{"tags":["Tenant - External Endpoints (M4)"],"summary":"외부 엔드포인트 단건 조회","operationId":"get_1","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}},"put":{"tags":["Tenant - External Endpoints (M4)"],"summary":"외부 엔드포인트 수정","description":"baseUrl 이 바뀌면 domain 재계산 + domain_verified 리셋(재인증 필요). authConfig 비면 기존 ciphertext 유지.","operationId":"update","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalEndpointRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}},"delete":{"tags":["Tenant - External Endpoints (M4)"],"summary":"외부 엔드포인트 삭제","operationId":"delete_1","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}}},"/tenant/data-pipelines/{pipelineUuid}":{"get":{"tags":["tenant-data-pipeline-controller"],"operationId":"getPipeline","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePipelineConfigResponse"}}}}}},"put":{"tags":["tenant-data-pipeline-controller"],"operationId":"updatePipeline","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePipelineRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePipelineConfigResponse"}}}}}},"delete":{"tags":["tenant-data-pipeline-controller"],"operationId":"deletePipeline","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"}}}},"/tenant/ble/route":{"get":{"tags":["tenant-ble-controller"],"operationId":"getBleRoute","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBleRouteConfigResponse"}}}}}},"put":{"tags":["tenant-ble-controller"],"operationId":"configureBleRoute","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BleRouteConfigRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBleRouteConfigResponse"}}}}}}},"/tenant/billing/charge-settings":{"get":{"tags":["Tenant - Billing/Entitlement"],"summary":"[DEPRECATED] auto-charge settings — sdx-web으로 이동","operationId":"getChargeSettingsGone","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}},"put":{"tags":["Tenant - Billing/Entitlement"],"summary":"[DEPRECATED] auto-charge settings — sdx-web으로 이동","operationId":"updateChargeSettingsGone","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}}},"/tenant/api-keys/{apiKeyId}":{"put":{"tags":["Tenant - API Keys"],"summary":"Update API key","description":"Update name, scopes, or rate limit of an existing API key.","operationId":"updateKey","parameters":[{"name":"apiKeyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyUpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseApiKeyListResponse"}}}}}},"delete":{"tags":["Tenant - API Keys"],"summary":"Revoke API key","description":"Deactivates an API key. The key can no longer be used for authentication.","operationId":"revokeKey","parameters":[{"name":"apiKeyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}},"/tenant/agent-update-policies":{"get":{"tags":["Tenant - Agent Update Policies"],"summary":"List agent update policies belonging to current tenant","operationId":"list","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAgentUpdatePolicyResponse"}}}}}},"put":{"tags":["Tenant - Agent Update Policies"],"summary":"Upsert UNIT/HUB scoped policy (tenant_uuid auto-set on UNIT scope)","operationId":"upsert_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentUpdatePolicyRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentUpdatePolicyResponse"}}}}}}},"/platform/supplier-oauth-configs":{"put":{"tags":["Platform - Supplier OAuth Config"],"summary":"Register or update supplier OAuth config","description":"UPSERT keyed by supplier_uuid. client_secret + registration_shared_secret 은 plaintext로 받아 즉시 AES-GCM 암호화 후 저장. 응답에는 secret 값 미노출 — registrationSharedSecretSet 플래그로 존재 여부만 표시.","operationId":"upsert_2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupplierOauthConfigRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/platform/agent-update-policies":{"get":{"tags":["Platform - Agent Update Policies"],"summary":"List agent update policies","description":"List agent update policies with optional scope filter","operationId":"listPolicies","parameters":[{"name":"scope","in":"query","description":"Filter by scope type (GLOBAL, UNIT, HUB)","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAgentUpdatePolicyResponse"}}}}}},"put":{"tags":["Platform - Agent Update Policies"],"summary":"Upsert agent update policy","description":"Create or update an agent update policy","operationId":"upsertPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentUpdatePolicyRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentUpdatePolicyResponse"}}}}}}},"/app/profile":{"get":{"tags":["App - Profile"],"summary":"Get profile","description":"Get current user profile","operationId":"getProfile","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserProfileResponse"}}}}}},"put":{"tags":["App - Profile"],"summary":"Update profile","description":"Update current user profile (nickname, etc.)","operationId":"updateProfile","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileUpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUserProfileResponse"}}}}}}},"/app/notifications/{notificationId}/read":{"put":{"tags":["App - Notifications"],"summary":"Mark as read","description":"Mark a notification as read","operationId":"markAsRead","parameters":[{"name":"notificationId","in":"path","description":"Notification ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}},"/app/consent/{consentId}/retention":{"get":{"tags":["App - Consent"],"summary":"Get retention settings","description":"Get retention settings for a consent record","operationId":"getRetention","parameters":[{"name":"consentId","in":"path","description":"Consent record ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRetentionSettingResponse"}}}}}},"put":{"tags":["App - Consent"],"summary":"Update retention period","description":"Update retention period for a consent record","operationId":"updateRetention","parameters":[{"name":"consentId","in":"path","description":"Consent record ID","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionUpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRetentionSettingResponse"}}}}}}},"/webhook/supplier-permission/{supplierUuid}":{"post":{"tags":["Webhook - Supplier Permission"],"summary":"Receive supplier permission change notification","description":"HMAC-SHA256 서명을 X-LinkOStar-Signature 헤더로 검증 후 body의 user_sub로 active SupplierLink들을 찾아 그 사용자의 권한 cache를 통째 invalidate. 401: 서명 불일치 / 404: supplier_oauth_config 없음 / 412: shared_secret 미설정 / 400: missing user_sub.","operationId":"receive","parameters":[{"name":"supplierUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-LinkOStar-Signature","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}}}}},"/v1/hubs/{hubUuid}/telemetry":{"post":{"tags":["Hub - Telemetry & Logs"],"summary":"Record telemetry","description":"Record telemetry data from hub","operationId":"recordTelemetry","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonNode"}}},"required":true},"responses":{"204":{"description":"No Content"}}}},"/v1/hubs/{hubUuid}/logs":{"post":{"tags":["Hub - Telemetry & Logs"],"summary":"Record log","description":"Record log entry from hub","operationId":"recordLog","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonNode"}}},"required":true},"responses":{"204":{"description":"No Content"}}}},"/v1/hubs/{hubUuid}/jobs/{hubJobUuid}/events":{"post":{"tags":["Hub - Jobs"],"summary":"Record job event","description":"Record job event and update job status","operationId":"recordJobEvent","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"hubJobUuid","in":"path","description":"Hub Job UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubJobEventRequest"}}},"required":true},"responses":{"204":{"description":"No Content"}}}},"/v1/hubs/{hubUuid}/device-query":{"post":{"tags":["Hub - Device Query"],"summary":"Resolve a scanned BLE asset to a device instance and activate it","operationId":"query","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceQueryRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceQueryResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/v1/hubs/{hubUuid}/certificates":{"post":{"tags":["Hub - mTLS"],"summary":"Sign hub CSR","description":"Hub 가 device-local keypair 로 만든 PKCS#10 CSR 를 제출. LinkOStar 가 sign 후 client cert 를 돌려줌. cert 의 CN/SAN 은 backend 가 신뢰하는 hub_uuid 로 강제 — CSR 의 subject 는 무시.","operationId":"issueCertificate","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertificateIssueRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseCertificateIssueResponse"}}}}}}},"/v1/hubs/refresh":{"post":{"tags":["Hub - Claim & Auth"],"summary":"Refresh hub access token","description":"Refresh hub access token using refresh token.\n\n**Process:**\n1. Validates hub authentication (must be authenticated)\n2. Checks if hub is blocked (rejects if blocked)\n3. Verifies refresh token matches stored token\n4. Checks if token is revoked\n5. Generates new access_token (refresh token remains the same)\n6. Updates hub_auth_token table\n7. Records audit log\n\n**Security:**\n- Requires hub authentication (Bearer token)\n- Blocked hubs cannot refresh\n- Revoked tokens cannot be refreshed\n\n**Token Expiration:**\n- Access token: 24 hours (configurable)\n- Refresh token: 30 days (configurable)\n","operationId":"refreshToken","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubRefreshRequest"}}},"required":true},"responses":{"200":{"description":"Tokens refreshed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"examples":{"Success":{"description":"Success","value":{"data":{"hubUuid":"550e8400-e29b-41d4-a716-446655440000","accessToken":"new_access_token_here","expiresAt":"2026-02-27T10:00:00Z"}}}}}}},"401":{"description":"Hub authentication required or invalid refresh token","content":{"application/json":{"examples":{"Invalid Token":{"description":"Invalid Token","value":{"message":"Invalid refresh token"}}}}}},"403":{"description":"Hub is blocked or token is revoked","content":{"application/json":{"examples":{"Blocked Hub":{"description":"Blocked Hub","value":{"message":"This hub has been blocked. Please contact support."}}}}}}}}},"/v1/hubs/claim":{"post":{"tags":["Hub - Claim & Auth"],"summary":"Claim hub instance","description":"Register a hub to a usage unit using a claim code.\n\n**Process:**\n1. Validates the claim code (expiration, revocation, usage limits)\n2. Creates new hub_instance or updates existing one by device_instance_id\n3. Checks if hub is blocked (rejects if blocked)\n4. Generates access_token and refresh_token\n5. Saves to hub_auth_token table\n6. Records audit log\n\n**Security:**\n- No authentication required (public endpoint)\n- Claim code acts as authorization\n- Blocked hubs cannot claim\n\n**Rate Limiting:** None (one-time operation)\n","operationId":"claimHub","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubClaimRequest"}}},"required":true},"responses":{"201":{"description":"Hub claimed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"examples":{"Success":{"description":"Success","value":{"data":{"hubUuid":"550e8400-e29b-41d4-a716-446655440000","tenantUuid":"650e8400-e29b-41d4-a716-446655440000","accessToken":"eyJhbGci...truncated...","refreshToken":"eyJhbGci...truncated...","expiresAt":"2026-02-27T10:00:00Z"}}}}}}},"400":{"description":"Invalid claim code (expired, revoked, or max uses reached)","content":{"application/json":{"examples":{"Expired Code":{"description":"Expired Code","value":{"message":"Claim code has expired"}}}}}},"409":{"description":"Conflict - Hub already belongs to different unit","content":{"application/json":{"examples":{"Unit Conflict":{"description":"Unit Conflict","value":{"message":"Hub already belongs to different unit"}}}}}},"423":{"description":"Hub is blocked/locked","content":{"application/json":{"examples":{"Blocked Hub":{"description":"Blocked Hub","value":{"message":"This hub has been blocked. Please contact support."}}}}}}}}},"/v1/hubs/adapters":{"post":{"tags":["Hub - Adapter Inventory"],"summary":"Snapshot inventory upsert + missing-row power-off","description":"Idempotent: replays produce the same end-state. supplier_uuid / role 같은 운영자 지정 값은 보존 (덮어쓰지 않음).","operationId":"upsert_3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payload"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseResult"}}}}}}},"/v1/ble/events":{"post":{"tags":["hub-ble-controller"],"operationId":"uploadBleEvent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BleEventUploadRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBleEventUploadResponse"}}}}}}},"/v1/ble/events/windowed":{"post":{"tags":["hub-ble-controller"],"operationId":"uploadWindowedBleEvent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WindowedBleEventRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseWindowedBleEventResponse"}}}}}}},"/tenant/transfer-requests/{requestUuid}/reject":{"post":{"tags":["Tenant Transfer"],"summary":"이전 요청 거부 (받는 unit의 멤버 persona)","operationId":"reject","parameters":[{"name":"requestUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantTransferRequestResponse"}}}}}}},"/tenant/transfer-requests/{requestUuid}/cancel":{"post":{"tags":["Tenant Transfer"],"summary":"이전 요청 취소 (요청자 본인 또는 OWNER)","operationId":"cancel","parameters":[{"name":"requestUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantTransferRequestResponse"}}}}}}},"/tenant/transfer-requests/{requestUuid}/accept":{"post":{"tags":["Tenant Transfer"],"summary":"이전 요청 승인 (받는 unit의 멤버 persona)","operationId":"accept","parameters":[{"name":"requestUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantTransferRequestResponse"}}}}}}},"/tenant/tenants":{"get":{"tags":["Tenants"],"summary":"List my accessible tenants","operationId":"listMine","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListTenantResponse"}}}}}},"post":{"tags":["Tenants"],"summary":"Create a new tenant under my current sdx unit","operationId":"create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantResponse"}}}}}}},"/tenant/tenants/{tenantUuid}/transfer":{"post":{"tags":["Tenants"],"summary":"Initiate ownership transfer (current OWNER)","operationId":"initiateTransfer","parameters":[{"name":"tenantUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitiateTransferRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantTransferRequestResponse"}}}}}}},"/tenant/tenants/{tenantUuid}/members":{"get":{"tags":["Tenants"],"summary":"List tenant members (any access)","operationId":"listMembers","parameters":[{"name":"tenantUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListTenantMemberResponse"}}}}}},"post":{"tags":["Tenants"],"summary":"Grant access (ADMIN+; OWNER for OWNER role)","operationId":"grantMember","parameters":[{"name":"tenantUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrantAccessRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantMemberResponse"}}}}}}},"/tenant/supplier-bundles":{"get":{"tags":["Tenant - Supplier Bundles"],"summary":"List supplier bundles (optionally filter by status)","operationId":"list_1","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListBundleResponse"}}}}}},"post":{"tags":["Tenant - Supplier Bundles"],"summary":"Create bundle (DRAFT)","operationId":"create_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBundleRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBundleResponse"}}}}}}},"/tenant/supplier-bundles/{bundleUuid}/publish":{"post":{"tags":["Tenant - Supplier Bundles"],"summary":"Publish bundle (DRAFT → PUBLISHED)","operationId":"publish","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBundleResponse"}}}}}}},"/tenant/supplier-bundles/{bundleUuid}/archive":{"post":{"tags":["Tenant - Supplier Bundles"],"summary":"Archive bundle (PUBLISHED → ARCHIVED)","operationId":"archive","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBundleResponse"}}}}}}},"/tenant/simulator/stream":{"post":{"tags":["tenant-simulator-controller"],"operationId":"runStream","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamSimulationRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListSimulationResult"}}}}}}},"/tenant/simulator/run":{"post":{"tags":["tenant-simulator-controller"],"operationId":"runSimulation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulationRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseSimulationResult"}}}}}}},"/tenant/personas/invite":{"post":{"tags":["Tenant - Personas"],"summary":"Invite by email (creates PENDING invitation) or grant by personaUuid","operationId":"invite","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonaInviteRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseInviteResponse"}}}}}}},"/tenant/personas/invitations/{invitationId}/resend":{"post":{"tags":["Tenant - Personas"],"summary":"Rotate token + resend invitation email","operationId":"resendInvitation","parameters":[{"name":"invitationId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantInvitationResponse"}}}}}}},"/tenant/notification-settings/bulk":{"post":{"tags":["Tenant - Notification Settings"],"summary":"Bulk upsert notification settings","operationId":"bulkUpsert","requestBody":{"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UpsertNotificationSettingRequest"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListNotificationSettingResponse"}}}}}}},"/tenant/manuals":{"get":{"tags":["Tenant - Manuals"],"summary":"List device manuals (optionally filter by deviceUuid)","operationId":"listManuals","parameters":[{"name":"deviceUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceManualResponse"}}}}}},"post":{"tags":["Tenant - Manuals"],"summary":"Create device manual","operationId":"createManual","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceManualRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceManualResponse"}}}}}}},"/tenant/hubs/{hubUuid}/setup-delegations":{"get":{"tags":["Tenant - Setup Delegation"],"summary":"List setup delegations","description":"List all setup delegations for a hub","operationId":"listDelegations","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListSetupDelegationResponse"}}}}}},"post":{"tags":["Tenant - Setup Delegation"],"summary":"Create setup delegation","description":"Delegate hub setup rights to another user","operationId":"createDelegation","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDelegationRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseSetupDelegationResponse"}}}}}}},"/tenant/hubs/{hubUuid}/jobs/app-remove":{"post":{"tags":["tenant-app-controller"],"operationId":"createRemoveJob","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"appUuid","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUUID"}}}}}}},"/tenant/hubs/{hubUuid}/jobs/app-install":{"post":{"tags":["tenant-app-controller"],"operationId":"createInstallJob","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppInstallRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseUUID"}}}}}}},"/tenant/hubs/claim-codes":{"get":{"tags":["Tenant - Hubs"],"summary":"List my claim codes","description":"Newest first; status is derived (PENDING/USED/EXPIRED/REVOKED)","operationId":"listClaimCodes","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListClaimCodeListItem"}}}}}},"post":{"tags":["Tenant - Hubs"],"summary":"Generate claim code","description":"Generate a new hub claim code for this tenant","operationId":"generateClaimCode","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimCodeGenerateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseClaimCodeResponse"}}}}}}},"/tenant/external-endpoints":{"get":{"tags":["Tenant - External Endpoints (M4)"],"summary":"현재 tenant 의 외부 엔드포인트 목록","operationId":"list_2","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListMapStringObject"}}}}}},"post":{"tags":["Tenant - External Endpoints (M4)"],"summary":"외부 엔드포인트 등록","description":"baseUrl host 로 domain 추출 + verify_token 발급. 등록 시점엔 domain_verified=false.","operationId":"create_2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalEndpointRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/tenant/external-endpoints/{id}/verify":{"post":{"tags":["Tenant - External Endpoints (M4)"],"summary":"도메인 소유 검증 실행","description":"설정된 verify_method 로 DNS TXT / well-known 을 조회해 verify_token 게시 여부 확인. 성공 시 domain_verified=true.","operationId":"verify","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/tenant/devices":{"get":{"tags":["Tenant - Devices"],"summary":"List device instances (optionally filter by activationStatus)","operationId":"listDevices_1","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"activationStatus","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceInstanceResponse"}}}}}},"post":{"tags":["Tenant - Devices"],"summary":"Register new device instance","operationId":"createDevice","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceInstanceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceInstanceResponse"}}}}}}},"/tenant/devices/{deviceInstanceId}/suspend":{"post":{"tags":["Tenant - Devices"],"summary":"Suspend device instance","operationId":"suspend","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceInstanceResponse"}}}}}}},"/tenant/devices/{deviceInstanceId}/retire":{"post":{"tags":["Tenant - Devices"],"summary":"Retire device instance (terminal state)","operationId":"retire","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceInstanceResponse"}}}}}}},"/tenant/devices/{deviceInstanceId}/activate":{"post":{"tags":["Tenant - Devices"],"summary":"Force-activate device instance (manual override)","operationId":"activate","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceInstanceResponse"}}}}}}},"/tenant/device-versions":{"get":{"tags":["Tenant - Device Versions"],"summary":"List device versions (optionally filter by deviceUuid)","operationId":"listVersions","parameters":[{"name":"deviceUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceVersionResponse"}}}}}},"post":{"tags":["Tenant - Device Versions"],"summary":"Create device version entry","operationId":"createVersion","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceVersionRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceVersionResponse"}}}}}}},"/tenant/device-ui-schemas":{"get":{"tags":["Tenant - Device UI"],"summary":"List device UI schemas (optionally filter by deviceUuid)","operationId":"listUiSchemas","parameters":[{"name":"deviceUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceUiResponse"}}}}}},"post":{"tags":["Tenant - Device UI"],"summary":"Create device UI schema","operationId":"createUiSchema","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceUiRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceUiResponse"}}}}}}},"/tenant/device-protocols":{"get":{"tags":["Tenant - Device Protocols"],"summary":"List device protocols (optionally filter by deviceUuid)","operationId":"listProtocols","parameters":[{"name":"deviceUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceProtocolResponse"}}}}}},"post":{"tags":["Tenant - Device Protocols"],"summary":"Create device protocol entry","operationId":"createProtocol","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceProtocolRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceProtocolResponse"}}}}}}},"/tenant/device-catalog":{"get":{"tags":["Tenant - Device Catalog"],"summary":"List device catalog entries (Device models)","operationId":"listDevices_2","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceCatalogResponse"}}}}}},"post":{"tags":["Tenant - Device Catalog"],"summary":"Create device catalog entry (deviceUuid auto-issued)","operationId":"createDevice_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceCatalogResponse"}}}}}}},"/tenant/device-catalog/{deviceUuid}/identifiers":{"get":{"tags":["Tenant - Device Match Identifiers"],"summary":"List identifier hints registered under a device","operationId":"list_3","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceMatchIdentifierResponse"}}}}}},"post":{"tags":["Tenant - Device Match Identifiers"],"summary":"Add an identifier hint","operationId":"create_3","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceMatchIdentifierRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceMatchIdentifierResponse"}}}}}}},"/tenant/data-pipelines":{"get":{"tags":["tenant-data-pipeline-controller"],"operationId":"listPipelines_1","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListPipelineConfigResponse"}}}}}},"post":{"tags":["tenant-data-pipeline-controller"],"operationId":"createPipeline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePipelineRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePipelineConfigResponse"}}}}}}},"/tenant/data-pipelines/{pipelineUuid}/test-run":{"post":{"tags":["tenant-data-pipeline-controller"],"operationId":"testRun","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineTestRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePipelineTestResult"}}}}}}},"/tenant/data-pipelines/{pipelineUuid}/dlq/{dlqId}/retry":{"post":{"tags":["tenant-data-pipeline-controller"],"operationId":"retryDlqMessage","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"dlqId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}},"/tenant/data-pipelines/transpile":{"post":{"tags":["tenant-data-pipeline-controller"],"operationId":"transpile","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonNode"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseObject"}}}}}}},"/tenant/consent-settings":{"get":{"tags":["Tenant - Consent"],"summary":"Get consent settings","description":"Get active consent settings for the current tenant (or pinned supplier)","operationId":"getConsentSettings","parameters":[{"name":"supplierUuid","in":"query","description":"Supplier UUID (defaults to current tenant)","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseConsentSettingResponse"}}}}}},"post":{"tags":["Tenant - Consent"],"summary":"Create or update consent settings","description":"Create or update consent settings for a supplier","operationId":"upsertConsentSettings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentSettingRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseConsentSettingResponse"}}}}}}},"/tenant/apps":{"get":{"tags":["tenant-app-controller"],"operationId":"listApps_1","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAppResponse"}}}}}},"post":{"tags":["tenant-app-controller"],"operationId":"createApp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppCreateRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAppResponse"}}}}}}},"/tenant/apps/{appUuid}/releases":{"get":{"tags":["tenant-app-controller"],"operationId":"listReleases","parameters":[{"name":"appUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAppReleaseResponse"}}}}}},"post":{"tags":["tenant-app-controller"],"operationId":"createRelease","parameters":[{"name":"appUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppReleaseCreateRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAppReleaseResponse"}}}}}}},"/tenant/api-keys":{"get":{"tags":["Tenant - API Keys"],"summary":"List API keys","description":"List all active API keys. Key hashes are never exposed.","operationId":"listKeys","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListApiKeyListResponse"}}}}}},"post":{"tags":["Tenant - API Keys"],"summary":"Generate new API key","description":"Creates a new API key. The raw key is returned ONCE and cannot be retrieved again.","operationId":"generateKey","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseApiKeyCreateResponse"}}}}}}},"/tenant/action-definitions":{"get":{"tags":["Tenant - Action Definitions"],"summary":"List action definitions for current tenant (auto-resolved supplier)","operationId":"list_4","parameters":[{"name":"supplierUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListActionDefinitionResponse"}}}}}},"post":{"tags":["Tenant - Action Definitions"],"summary":"Create action definition","description":"Create a new protocol action definition","operationId":"create_4","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionDefinitionCreateRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseActionDefinitionResponse"}}}}}}},"/platform/registration-events/{id}/retry":{"post":{"tags":["Platform - Registration Events (Outbox)"],"summary":"특정 outbox row 강제 재시도","description":"status를 PENDING으로 되돌리고 next_attempt_at=now 설정. SupplierRegistrationRetryJob의 다음 tick에서 즉시 픽업.","operationId":"retry","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/platform/hubs/{hub_uuid}/unblock":{"post":{"tags":["Platform Hub Management"],"summary":"Unblock a hub","description":"Unblock a hub to allow new token generation","operationId":"unblockHub","parameters":[{"name":"hub_uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}}}}},"/platform/hubs/{hub_uuid}/block":{"post":{"tags":["Platform Hub Management"],"summary":"Block a hub","description":"Block a hub by revoking all its auth tokens","operationId":"blockHub","parameters":[{"name":"hub_uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}}}}},"/platform/hubs/{hubUuid}/jobs/self-update":{"post":{"tags":["Platform - Hub Jobs"],"summary":"Create forced update job","description":"Create a forced self-update job for a hub","operationId":"createForcedUpdateJob","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateForcedUpdateJobRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseHubJobResponse"}}}}}}},"/platform/agent-releases":{"get":{"tags":["Platform - Agent Releases"],"summary":"List agent releases","description":"List agent releases with optional channel filter","operationId":"listReleases_1","parameters":[{"name":"channel","in":"query","description":"Filter by channel (e.g., stable, beta)","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAgentReleaseResponse"}}}}}},"post":{"tags":["Platform - Agent Releases"],"summary":"Create agent release","description":"Create a new agent release for a channel","operationId":"createRelease_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentReleaseResponse"}}}}}}},"/invitations/accept":{"post":{"tags":["Invitations"],"summary":"Redeem an invitation as the currently-authenticated persona","operationId":"accept_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAcceptResult"}}}}}}},"/app/supplier-link/authorize":{"post":{"tags":["App - Supplier Link"],"summary":"Begin OAuth authorize flow","description":"state + PKCE INSERT 후 외부 브라우저로 열 authorize URL 반환. 사용자 계정 연결은 hub와 무관 — hub/device 단위 권한은 별도 모델로 처리.","operationId":"beginAuthorize","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}}},"/app/devices/{deviceInstanceId}/commands":{"post":{"tags":["App - Devices"],"summary":"Send control command","description":"Send a control command to a device","operationId":"sendCommand","parameters":[{"name":"deviceInstanceId","in":"path","description":"Device instance ID","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceCommandRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceCommandResponse"}}}}}}},"/app/device-ui/invoke":{"post":{"tags":["App - Device UI Invoke (M4)"],"summary":"device_ui invoke 실행","description":"hubUuid 소유권 검증 → supplier resolve → 인증된 external_endpoint 로 프록시 호출.","operationId":"invoke","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceUiInvokeRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/app/consent":{"get":{"tags":["App - Consent"],"summary":"List consent records","description":"List all consent records for current user","operationId":"listConsents","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListConsentRecordResponse"}}}}}},"post":{"tags":["App - Consent"],"summary":"Grant consent","description":"Grant consent for a supplier and consent type","operationId":"grantConsent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentGrantRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseConsentRecordResponse"}}}}}}},"/tenant/tenants/{tenantUuid}":{"delete":{"tags":["Tenants"],"summary":"Soft-delete tenant (OWNER only)","operationId":"delete_2","parameters":[{"name":"tenantUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenants"],"summary":"Update tenant name (ADMIN+)","operationId":"update_1","parameters":[{"name":"tenantUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTenantRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantResponse"}}}}}}},"/tenant/supplier-bundles/{bundleUuid}":{"get":{"tags":["Tenant - Supplier Bundles"],"summary":"Get bundle detail","operationId":"get_2","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBundleResponse"}}}}}},"delete":{"tags":["Tenant - Supplier Bundles"],"summary":"Delete bundle (DRAFT only)","operationId":"delete_3","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Supplier Bundles"],"summary":"Update bundle fields (DRAFT only)","operationId":"update_2","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBundleRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBundleResponse"}}}}}}},"/tenant/personas/{personaUuid}":{"delete":{"tags":["Tenant - Personas"],"summary":"Revoke a persona's access to this tenant","operationId":"revoke","parameters":[{"name":"personaUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Personas"],"summary":"Change role of a tenant persona","operationId":"updateRole","parameters":[{"name":"personaUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePersonaRoleRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantMemberResponse"}}}}}}},"/tenant/manuals/{deviceManualId}":{"get":{"tags":["Tenant - Manuals"],"summary":"Get device manual detail","operationId":"getManual","parameters":[{"name":"deviceManualId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceManualResponse"}}}}}},"delete":{"tags":["Tenant - Manuals"],"summary":"Delete device manual","operationId":"deleteManual","parameters":[{"name":"deviceManualId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Manuals"],"summary":"Update device manual","operationId":"updateManual","parameters":[{"name":"deviceManualId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceManualRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceManualResponse"}}}}}}},"/tenant/hubs/{hubUuid}":{"get":{"tags":["Tenant - Hubs"],"summary":"Get hub detail","description":"Get hub detail with READ permission check","operationId":"getHub","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseHubDetailResponse"}}}}}},"patch":{"tags":["Tenant - Hubs"],"summary":"Update hub label","description":"Tenant 측에서 hub_identifier 같은 운영 라벨을 수정. PATCH 의미 — null 필드는 그대로 둠.","operationId":"updateHub","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubUpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseHubDetailResponse"}}}}}}},"/tenant/hubs/{hubUuid}/adapters/{address}":{"patch":{"tags":["Tenant - Hub Adapters"],"summary":"adapter role / supplier 할당 변경","operationId":"update_3","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"address","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAdapterView"}}}}}}},"/tenant/devices/{deviceInstanceId}":{"get":{"tags":["Tenant - Devices"],"summary":"Get device instance detail","operationId":"getDevice","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceInstanceResponse"}}}}}},"delete":{"tags":["Tenant - Devices"],"summary":"Delete device instance","operationId":"deleteDevice","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Devices"],"summary":"Update device instance","operationId":"updateDevice","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceInstanceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceInstanceResponse"}}}}}}},"/tenant/device-versions/{deviceVersionUuid}":{"get":{"tags":["Tenant - Device Versions"],"summary":"Get device version detail","operationId":"getVersion","parameters":[{"name":"deviceVersionUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceVersionResponse"}}}}}},"delete":{"tags":["Tenant - Device Versions"],"summary":"Delete device version entry","operationId":"deleteVersion","parameters":[{"name":"deviceVersionUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Device Versions"],"summary":"Update device version entry","operationId":"updateVersion","parameters":[{"name":"deviceVersionUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceVersionRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceVersionResponse"}}}}}}},"/tenant/device-ui-schemas/{deviceUiId}":{"get":{"tags":["Tenant - Device UI"],"summary":"Get device UI schema detail","operationId":"getUiSchema","parameters":[{"name":"deviceUiId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceUiResponse"}}}}}},"delete":{"tags":["Tenant - Device UI"],"summary":"Delete device UI schema","operationId":"deleteUiSchema","parameters":[{"name":"deviceUiId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Device UI"],"summary":"Update device UI schema","operationId":"updateUiSchema","parameters":[{"name":"deviceUiId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceUiRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceUiResponse"}}}}}}},"/tenant/device-protocols/{deviceProtocolId}":{"get":{"tags":["Tenant - Device Protocols"],"summary":"Get device protocol detail","operationId":"getProtocol","parameters":[{"name":"deviceProtocolId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceProtocolResponse"}}}}}},"delete":{"tags":["Tenant - Device Protocols"],"summary":"Delete device protocol entry","operationId":"deleteProtocol","parameters":[{"name":"deviceProtocolId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Device Protocols"],"summary":"Update device protocol entry","operationId":"updateProtocol","parameters":[{"name":"deviceProtocolId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceProtocolRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceProtocolResponse"}}}}}}},"/tenant/device-catalog/{deviceUuid}":{"get":{"tags":["Tenant - Device Catalog"],"summary":"Get device catalog entry detail","operationId":"getDevice_1","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceCatalogResponse"}}}}}},"delete":{"tags":["Tenant - Device Catalog"],"summary":"Delete device catalog entry (hard delete)","operationId":"deleteDevice_1","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Device Catalog"],"summary":"Update device catalog entry","operationId":"updateDevice_1","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceCatalogResponse"}}}}}}},"/tenant/device-catalog/{deviceUuid}/identifiers/{id}":{"delete":{"tags":["Tenant - Device Match Identifiers"],"summary":"Remove an identifier","operationId":"delete_4","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}},"patch":{"tags":["Tenant - Device Match Identifiers"],"summary":"Update label/notes on an identifier","operationId":"update_4","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceMatchIdentifierRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceMatchIdentifierResponse"}}}}}}},"/tenant/action-definitions/{actionId}":{"get":{"tags":["Tenant - Action Definitions"],"summary":"Get action definition","description":"Get a single action definition by ID","operationId":"get_3","parameters":[{"name":"actionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseActionDefinitionResponse"}}}}}},"delete":{"tags":["Tenant - Action Definitions"],"summary":"Delete action definition","description":"Delete an action definition","operationId":"delete_5","parameters":[{"name":"actionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}},"patch":{"tags":["Tenant - Action Definitions"],"summary":"Update action definition","description":"Update an existing action definition","operationId":"update_5","parameters":[{"name":"actionId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionDefinitionUpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseActionDefinitionResponse"}}}}}}},"/platform/agent-releases/{releaseUuid}":{"patch":{"tags":["Platform - Agent Releases"],"summary":"Update agent release","description":"Update an existing agent release","operationId":"updateRelease","parameters":[{"name":"releaseUuid","in":"path","description":"Release UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentReleaseRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentReleaseResponse"}}}}}}},"/v1/test":{"get":{"tags":["Hub API"],"summary":"Hub test endpoint","description":"Test endpoint that requires hub token authentication","operationId":"testHubAccess","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}},"security":[{"bearerAuth":[]}]}},"/v1/hubs/{hubUuid}/desired-state":{"get":{"tags":["Hub - DesiredState"],"summary":"Get current DesiredState for this hub (poll)","operationId":"get_4","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/v1/hubs/scan-config":{"get":{"tags":["Hub - Scan Config"],"summary":"현재 hub의 tenant 소속 device + identifier + protocol + HUB-layer route 묶음","operationId":"get_5","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseScanConfigResponse"}}}}}}},"/v1/hubs/ca-bundle":{"get":{"tags":["Hub - mTLS"],"summary":"Root CA PEM","description":"Agent 가 trust store 에 박을 LinkOStar root CA 인증서.","operationId":"getCaBundle","responses":{"200":{"description":"OK","content":{"application/x-pem-file":{"schema":{"type":"string"}}}}}}},"/v1/apps/{appReleaseUuid}/manifest":{"get":{"tags":["hub-app-controller"],"operationId":"getManifest","parameters":[{"name":"appReleaseUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonNode"}}}}}}},"/v1/agent/releases/latest":{"get":{"tags":["Hub - Agent"],"summary":"Get latest agent release","description":"Bearer token 의 hub identity 로 자동 매칭. hubUuid query param 은 admin override 용 optional.","operationId":"getLatestRelease","parameters":[{"name":"hubUuid","in":"query","description":"Hub UUID — 생략 시 Bearer token 에서 자동 추출","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"channel","in":"query","description":"Agent channel (e.g., stable, beta)","required":false,"schema":{"type":"string","default":"stable"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentReleaseLatestResponse"}}}}}}},"/tenant/units/{tenantUuid}/test":{"get":{"tags":["Tenant"],"summary":"Test unit boundary enforcement","description":"Test endpoint that verifies persona belongs to specified unit","operationId":"testUnitAccess","parameters":[{"name":"tenantUuid","in":"path","description":"Unit UUID to access","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}},"security":[{"bearerAuth":[]}]}},"/tenant/transfer-requests/outgoing":{"get":{"tags":["Tenant Transfer"],"summary":"보낸 PENDING 이전 요청 (현재 persona의 unit에서 발신)","operationId":"outgoing","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListTenantTransferRequestResponse"}}}}}}},"/tenant/transfer-requests/incoming":{"get":{"tags":["Tenant Transfer"],"summary":"받은 PENDING 이전 요청 (현재 persona의 unit으로 향한)","operationId":"incoming","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListTenantTransferRequestResponse"}}}}}}},"/tenant/test":{"get":{"tags":["Tenant"],"summary":"Tenant test endpoint","description":"Test endpoint that requires JWT authentication","operationId":"testTenantAccess","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}},"security":[{"bearerAuth":[]}]}},"/tenant/stream/hubs/{hubUuid}/logs":{"get":{"tags":["SSE Stream"],"summary":"Stream hub logs","description":"Subscribe to real-time hub logs via Server-Sent Events (SSE).\n\n**SSE Protocol:**\n- Content-Type: text/event-stream\n- Event name: `hub_log`\n- Heartbeat: Every 20 seconds (comment: ping)\n- Connection timeout: 5 minutes\n\n**Last-Event-ID Support:**\n- Client can send `Last-Event-ID` header with ISO-8601 timestamp\n- Server will stream logs after that timestamp\n- Event IDs are ISO-8601 timestamps (receivedAt)\n\n**Permission:**\n- Requires unit scope (persona's unit must match hub's unit)\n- Requires READ permission (permissionCode & 1 == 1)\n\n**Testing with curl:**\n```bash\ncurl -N -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     http://localhost:8080/tenant/stream/hubs/{hubUuid}/logs\n```\n","operationId":"streamHubLogs","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"}},{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"Last-Event-ID","in":"header","description":"Last event timestamp (ISO-8601)","required":false,"schema":{"type":"string"},"example":"2026-02-27T10:00:00Z"}],"responses":{"200":{"description":"SSE stream established","content":{"text/event-stream":{"schema":{"type":"string"},"example":"event: hub_log\nid: 2026-02-27T10:30:00Z\ndata: {\"receivedAt\":\"2026-02-27T10:30:00Z\",\"level\":\"INFO\",\"message\":\"System started\"}\n\n: ping\n\nevent: hub_log\nid: 2026-02-27T10:30:05Z\ndata: {\"receivedAt\":\"2026-02-27T10:30:05Z\",\"level\":\"WARN\",\"message\":\"Low memory\"}\n"}}},"404":{"description":"Hub not found or persona doesn't have access","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/SseEmitter"}}}},"403":{"description":"Insufficient permissions","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/SseEmitter"}}}}}}},"/tenant/stream/hubs/{hubUuid}/jobs":{"get":{"tags":["SSE Stream"],"summary":"Stream hub job events","description":"Subscribe to real-time hub job events via Server-Sent Events (SSE).\n\n**SSE Protocol:**\n- Content-Type: text/event-stream\n- Event name: `hub_job_event`\n- Heartbeat: Every 20 seconds (comment: ping)\n- Connection timeout: 5 minutes\n\n**Last-Event-ID Support:**\n- Client can send `Last-Event-ID` header with ISO-8601 timestamp\n- Server will stream events after that timestamp\n- Event IDs are ISO-8601 timestamps (receivedAt)\n\n**Permission:**\n- Requires unit scope (persona's unit must match hub's unit)\n- Requires READ permission (permissionCode & 1 == 1)\n\n**Testing with curl:**\n```bash\ncurl -N -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     http://localhost:8080/tenant/stream/hubs/{hubUuid}/jobs\n```\n\n**Testing with EventSource (JavaScript):**\n```javascript\nconst eventSource = new EventSource('/tenant/stream/hubs/{hubUuid}/jobs', {\n    headers: { Authorization: 'Bearer YOUR_TOKEN' }\n});\n\neventSource.addEventListener('hub_job_event', (event) => {\n    const data = JSON.parse(event.data);\n    console.log('Job event:', data);\n});\n```\n","operationId":"streamHubJobEvents","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"}},{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"},"example":"550e8400-e29b-41d4-a716-446655440001"},{"name":"Last-Event-ID","in":"header","description":"Last event timestamp (ISO-8601)","required":false,"schema":{"type":"string"},"example":"2026-02-27T10:00:00Z"}],"responses":{"200":{"description":"SSE stream established","content":{"text/event-stream":{"schema":{"type":"string"},"example":"event: hub_job_event\nid: 2026-02-27T10:30:00Z\ndata: {\"jobUuid\":\"550e8400-e29b-41d4-a716-446655440001\",\"state\":\"RUNNING\",\"progress\":50,\"message\":\"Processing...\",\"at\":\"2026-02-27T10:30:00Z\"}\n\n: ping\n\nevent: hub_job_event\nid: 2026-02-27T10:30:15Z\ndata: {\"jobUuid\":\"550e8400-e29b-41d4-a716-446655440001\",\"state\":\"COMPLETED\",\"progress\":100,\"message\":\"Done\",\"at\":\"2026-02-27T10:30:15Z\"}\n"}}},"404":{"description":"Hub not found or persona doesn't have access","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/SseEmitter"}}}},"403":{"description":"Insufficient permissions","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/SseEmitter"}}}}}}},"/tenant/stream/ble/events":{"get":{"tags":["SSE Stream"],"summary":"Stream BLE events","description":"Subscribe to real-time BLE events via Server-Sent Events (SSE).\n\n**SSE Protocol:**\n- Content-Type: text/event-stream\n- Event name: `ble_event`\n- Heartbeat: Every 20 seconds (comment: ping)\n- Connection timeout: 5 minutes\n\n**Last-Event-ID Support:**\n- Client can send `Last-Event-ID` header with ISO-8601 timestamp\n- Server will stream events after that timestamp\n- Event IDs are ISO-8601 timestamps (receivedAt)\n\n**Permission:**\n- Requires unit scope (events filtered by persona's unit)\n- Requires READ permission (permissionCode & 1 == 1)\n\n**Testing with curl:**\n```bash\ncurl -N -H \"Authorization: Bearer YOUR_TOKEN\" \\\n     http://localhost:8080/tenant/stream/ble/events\n```\n\n**Testing with EventSource (JavaScript):**\n```javascript\nconst eventSource = new EventSource('/tenant/stream/ble/events', {\n    headers: { Authorization: 'Bearer YOUR_TOKEN' }\n});\n\neventSource.addEventListener('ble_event', (event) => {\n    const data = JSON.parse(event.data);\n    console.log('BLE event:', data);\n});\n\neventSource.onerror = (error) => {\n    console.error('SSE error:', error);\n};\n```\n","operationId":"streamBleEvents","parameters":[{"name":"Authorization","in":"header","required":true,"schema":{"type":"string"}},{"name":"Last-Event-ID","in":"header","description":"Last event timestamp (ISO-8601)","required":false,"schema":{"type":"string"},"example":"2026-02-27T10:00:00Z"}],"responses":{"200":{"description":"SSE stream established","content":{"text/event-stream":{"schema":{"type":"string"},"example":"event: ble_event\nid: 2026-02-27T10:30:00Z\ndata: {\"bleEventId\":12345,\"hubUuid\":\"550e8400-e29b-41d4-a716-446655440001\",\"receivedAt\":\"2026-02-27T10:30:00Z\",\"processingStatus\":\"PENDING\",\"deliveryStatus\":\"PENDING\"}\n\n: ping\n\nevent: ble_event\nid: 2026-02-27T10:30:02Z\ndata: {\"bleEventId\":12346,\"hubUuid\":\"550e8400-e29b-41d4-a716-446655440001\",\"receivedAt\":\"2026-02-27T10:30:02Z\",\"processingStatus\":\"COMPLETED\",\"deliveryStatus\":\"SENT\"}\n"}}},"403":{"description":"Insufficient permissions","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/SseEmitter"}}}}}}},"/tenant/simulator/presets":{"get":{"tags":["tenant-simulator-controller"],"operationId":"getPresets","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListSimulationPreset"}}}}}}},"/tenant/personas":{"get":{"tags":["Tenant - Personas"],"summary":"List active members + pending / historical invitations","operationId":"list_5","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseTenantPersonasResponse"}}}}}}},"/tenant/hubs":{"get":{"tags":["Tenant - Hubs"],"summary":"List hubs","description":"List all hubs for current unit with READ permission check","operationId":"listHubs","parameters":[{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListHubSummaryResponse"}}}}}}},"/tenant/hubs/{hubUuid}/telemetry":{"get":{"tags":["Tenant - Hubs"],"summary":"Get hub telemetry","description":"Get hub telemetry with time range filter","operationId":"getHubTelemetry","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListHubTelemetryResponse"}}}}}}},"/tenant/hubs/{hubUuid}/logs":{"get":{"tags":["Tenant - Hubs"],"summary":"Get hub logs","description":"Get hub logs with time range filter","operationId":"getHubLogs","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListHubLogResponse"}}}}}}},"/tenant/hubs/{hubUuid}/jobs":{"get":{"tags":["Tenant - Hubs"],"summary":"Get hub jobs","description":"Get hub jobs with READ permission check","operationId":"getHubJobs","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListHubJobResponse"}}}}}}},"/tenant/hubs/{hubUuid}/installed-apps":{"get":{"tags":["Tenant - Hub Installed Apps"],"summary":"List apps scheduled / installed on this hub","operationId":"list_6","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListInstalledAppView"}}}}}}},"/tenant/hubs/{hubUuid}/apps":{"get":{"tags":["tenant-app-controller"],"operationId":"getInstalledApps","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListHubInstalledAppResponse"}}}}}}},"/tenant/hubs/{hubUuid}/adapters":{"get":{"tags":["Tenant - Hub Adapters"],"summary":"이 hub가 가진 BlueZ adapter 전부","operationId":"list_7","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAdapterView"}}}}}}},"/tenant/hub-monitoring/{hubUuid}/telemetry":{"get":{"tags":["Hub Monitoring"],"summary":"Get hub telemetry","description":"Retrieve telemetry data filtered by time range (latest first)","operationId":"getHubTelemetry_1","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T00:00:00Z"},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T23:59:59Z"},{"name":"pageable","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Pageable"}}],"responses":{"200":{"description":"Telemetry data retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"content":[{"hubTelemetryUuid":"750e8400-e29b-41d4-a716-446655440000","hubUuid":"550e8400-e29b-41d4-a716-446655440000","payloadJson":{"cpu":45.2,"memory":512},"receivedAt":"2026-02-26T10:00:00Z"}],"totalElements":100}}}}},"404":{"description":"Hub not found or access denied","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageHubTelemetryResponse"}}}}}}},"/tenant/hub-monitoring/{hubUuid}/logs":{"get":{"tags":["Hub Monitoring"],"summary":"Get hub logs","description":"Retrieve log entries filtered by time range (latest first)","operationId":"getHubLogs_1","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T00:00:00Z"},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T23:59:59Z"},{"name":"pageable","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Pageable"}}],"responses":{"200":{"description":"Logs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"content":[{"hubLogUuid":"850e8400-e29b-41d4-a716-446655440000","hubUuid":"550e8400-e29b-41d4-a716-446655440000","level":"INFO","message":"Hub started successfully","payloadJson":{"version":"1.2.3"},"loggedAt":"2026-02-26T10:00:00Z"}],"totalElements":200}}}}},"404":{"description":"Hub not found or access denied","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageHubLogResponse"}}}}}}},"/tenant/hub-monitoring/{hubUuid}/jobs":{"get":{"tags":["Hub Monitoring"],"summary":"Get hub jobs","description":"Retrieve paginated list of jobs for a specific hub. Requires READ permission on the hub's unit.","operationId":"getHubJobs_1","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"pageable","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Pageable"}}],"responses":{"200":{"description":"Hub jobs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"content":[{"hubJobUuid":"550e8400-e29b-41d4-a716-446655440000","jobType":"SELF_UPDATE","jobState":"RUNNING","progress":50,"message":"downloading","createdAt":"2026-02-26T10:00:00Z","updatedAt":"2026-02-26T10:30:00Z"}],"pageable":{"pageNumber":0,"pageSize":20},"totalElements":10,"totalPages":1}}}}},"404":{"description":"Hub not found or access denied","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageHubJobResponse"}}}},"403":{"description":"Insufficient permissions","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageHubJobResponse"}}}}}}},"/tenant/hub-monitoring/{hubUuid}/jobs/{jobUuid}":{"get":{"tags":["Hub Monitoring"],"summary":"Get hub job details","description":"Retrieve detailed information about a specific job including desired and result JSON payloads","operationId":"getHubJobDetail","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"jobUuid","in":"path","description":"Job UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Job details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"hubJobUuid":"550e8400-e29b-41d4-a716-446655440000","jobType":"SELF_UPDATE","jobState":"RUNNING","progress":50,"message":"downloading","desiredJson":{"version":"1.2.3"},"resultJson":null,"createdAt":"2026-02-26T10:00:00Z","updatedAt":"2026-02-26T10:30:00Z"}}}}},"404":{"description":"Hub or job not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseHubJobDetailResponse"}}}}}}},"/tenant/hub-monitoring/{hubUuid}/jobs/{jobUuid}/events":{"get":{"tags":["Hub Monitoring"],"summary":"Get hub job events","description":"Retrieve time-ordered events for a specific job","operationId":"getHubJobEvents","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"jobUuid","in":"path","description":"Job UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"pageable","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Pageable"}}],"responses":{"200":{"description":"Job events retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"content":[{"hubJobEventUuid":"650e8400-e29b-41d4-a716-446655440000","hubJobUuid":"550e8400-e29b-41d4-a716-446655440000","eventType":"STATE_CHANGE","message":"Job started","createdAt":"2026-02-26T10:00:00Z"}],"totalElements":5}}}}},"404":{"description":"Hub or job not found","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageHubJobEventResponse"}}}}}}},"/tenant/downloads/manifest":{"get":{"tags":["Tenant - Downloads"],"summary":"Latest release + filtered assets for installer / hub-os / hub-agent","operationId":"manifest","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDownloadManifest"}}}}}}},"/tenant/downloads/asset-url":{"get":{"tags":["Tenant - Downloads"],"summary":"Resolve a GH presigned S3 URL for a single asset (5-min TTL)","operationId":"assetUrl","parameters":[{"name":"category","in":"query","required":true,"schema":{"type":"string"}},{"name":"assetId","in":"query","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAssetUrl"}}}}}}},"/tenant/devices/{deviceInstanceId}/sensor-data":{"get":{"tags":["Tenant - Devices"],"summary":"Query sensor timeseries (TODO: backed by ble_event for now — empty stub)","operationId":"getSensorData","parameters":[{"name":"deviceInstanceId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":100}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListMapStringObject"}}}}}}},"/tenant/device-protocols/devices/{deviceUuid}":{"get":{"tags":["Tenant - Device Protocols"],"summary":"Get device catalog header (Device entity)","operationId":"getDevice_2","parameters":[{"name":"deviceUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceCatalogResponse"}}}}}}},"/tenant/data-pipelines/{pipelineUuid}/dlq":{"get":{"tags":["tenant-data-pipeline-controller"],"operationId":"getDlqMessages","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDlqMessageResponse"}}}}}}},"/tenant/data-pipelines/{pipelineUuid}/deliveries":{"get":{"tags":["tenant-data-pipeline-controller"],"operationId":"getDeliveries","parameters":[{"name":"pipelineUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":50}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListMapStringObject"}}}}}}},"/tenant/dashboard/summary":{"get":{"tags":["Tenant - Dashboard"],"summary":"Dashboard summary — hub/device/pipeline/DLQ counts + BLE throughput & webhook success","description":"windowMinutes (default 60, clamped 1–1440) sizes the events / delivery / BLE-in-range window. Hub online is derived from telemetry within a fixed 10-minute window.","operationId":"summary","parameters":[{"name":"windowMinutes","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":60}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDashboardSummary"}}}}}}},"/tenant/consent-records":{"get":{"tags":["Tenant - Consent"],"summary":"List consent records","description":"List all consent records for the current tenant (or pinned supplier)","operationId":"listConsentRecords","parameters":[{"name":"supplierUuid","in":"query","description":"Supplier UUID (defaults to current tenant)","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListConsentRecordResponse"}}}}}}},"/tenant/ble/events":{"get":{"tags":["tenant-ble-controller"],"operationId":"queryBleEvents","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"hubUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"deviceInstanceId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"processingStatus","in":"query","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListBleEventResponse"}}}}}}},"/tenant/ble/events/{bleEventId}":{"get":{"tags":["tenant-ble-controller"],"operationId":"getBleEvent","parameters":[{"name":"bleEventId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBleEventResponse"}}}}}}},"/tenant/ble/events/{bleEventId}/runs":{"get":{"tags":["tenant-ble-controller"],"operationId":"getBleProcessingRuns","parameters":[{"name":"bleEventId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListBleProcessingRunResponse"}}}}}}},"/tenant/ble-query/events":{"get":{"tags":["BLE Query (Legacy)"],"summary":"Get BLE events","description":"Retrieve paginated list of BLE events filtered by unit scope and optional criteria. Raw base64 data is excluded from list view.","operationId":"getBleEvents","parameters":[{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T00:00:00Z"},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T23:59:59Z"},{"name":"hubUuid","in":"query","description":"Filter by hub UUID","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"deviceInstanceId","in":"query","description":"Filter by device instance ID","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"processingStatus","in":"query","description":"Filter by processing status","required":false,"schema":{"type":"string"}},{"name":"deliveryStatus","in":"query","description":"Filter by delivery status","required":false,"schema":{"type":"string"}},{"name":"pageable","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Pageable"}}],"responses":{"200":{"description":"BLE events retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"content":[{"bleEventId":123,"receivedAt":"2026-02-26T10:00:00Z","hubUuid":"550e8400-e29b-41d4-a716-446655440000","deviceInstanceId":456,"rssi":-65,"processingStatus":"PROCESSED","deliveryStatus":"DELIVERED","payloadJson":{"temperature":22.5}}],"totalElements":100}}}}},"403":{"description":"Insufficient permissions","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageBleEventResponse"}}}}}}},"/tenant/ble-query/events/{bleEventId}":{"get":{"tags":["BLE Query (Legacy)"],"summary":"Get BLE event detail","description":"Retrieve detailed information about a specific BLE event. Raw base64 data can be included with includeRaw=true parameter.","operationId":"getBleEventDetail","parameters":[{"name":"bleEventId","in":"path","description":"BLE event ID","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"includeRaw","in":"query","description":"Include raw base64 data","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"BLE event detail retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"bleEventId":123,"receivedAt":"2026-02-26T10:00:00Z","hubUuid":"550e8400-e29b-41d4-a716-446655440000","deviceInstanceId":456,"rssi":-65,"processingStatus":"PROCESSED","deliveryStatus":"DELIVERED","payloadJson":{"temperature":22.5},"rawBase64":"base64encodeddata..."}}}}},"404":{"description":"Event not found or access denied","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBleEventDetailResponse"}}}}}}},"/tenant/ble-query/events/{bleEventId}/runs":{"get":{"tags":["BLE Query (Legacy)"],"summary":"Get BLE event processing runs","description":"Retrieve all processing runs and their actions for a specific BLE event","operationId":"getBleEventRuns","parameters":[{"name":"bleEventId","in":"path","description":"BLE event ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Processing runs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":[{"bleProcessingRunId":456,"bleEventId":123,"bleRouteId":789,"processingStatus":"COMPLETED","startedAt":"2026-02-26T10:00:01Z","completedAt":"2026-02-26T10:00:05Z","actions":[{"bleProcessingActionId":111,"actionOrder":1,"actionType":"PARSE","status":"SUCCESS","executedAt":"2026-02-26T10:00:02Z"}]}]}}}},"404":{"description":"Event not found or access denied","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListBleProcessingRunResponse"}}}}}}},"/tenant/ble-query/deliveries":{"get":{"tags":["BLE Query (Legacy)"],"summary":"Get BLE deliveries","description":"Retrieve paginated list of BLE deliveries filtered by unit scope and optional criteria","operationId":"getBleDeliveries","parameters":[{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T00:00:00Z"},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string","format":"date-time"},"example":"2026-02-26T23:59:59Z"},{"name":"status","in":"query","description":"Filter by delivery status","required":false,"schema":{"type":"string"}},{"name":"pageable","in":"query","required":true,"schema":{"$ref":"#/components/schemas/Pageable"}}],"responses":{"200":{"description":"BLE deliveries retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiResponse"},"example":{"data":{"content":[{"bleDeliveryId":123,"bleEventId":456,"hubUuid":"550e8400-e29b-41d4-a716-446655440000","targetUrl":"https://api.example.com/webhook","deliveryStatus":"DELIVERED","httpStatusCode":200,"attemptCount":1,"lastAttemptAt":"2026-02-26T10:00:00Z"}],"totalElements":50}}}}}}}},"/tenant/billing/transactions":{"get":{"tags":["Tenant - Billing/Entitlement"],"summary":"Get billing transactions","description":"sdx-web pass-through. Cursor pagination by createdAt desc.","operationId":"getTransactions","parameters":[{"name":"cursor","in":"query","description":"ISO-8601 datetime; 생략 시 최신부터","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"1-100, default 50","required":false,"schema":{"type":"integer","format":"int32","default":50}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/tenant/billing/entitlement":{"get":{"tags":["Tenant - Billing/Entitlement"],"summary":"Get current entitlement","description":"sdx-web 구독 기반 entitlement (tier, limits, validUntil)","operationId":"getEntitlement","parameters":[{"name":"tenantUuid","in":"query","description":"Unit UUID (생략 시 현재 컨텍스트 사용)","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseEntitlementResponse"}}}}}}},"/tenant/billing/balance":{"get":{"tags":["Tenant - Billing/Entitlement"],"summary":"Get billing balance","description":"sdx-web pass-through. Returns currentCreditCents, activeSubscription, lastInvoice.","operationId":"getBalance","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/tenant/audit-logs":{"get":{"tags":["Tenant Audit Logs"],"summary":"Get tenant audit logs","description":"Retrieve tenant-level audit logs with pagination","operationId":"getTenantAuditLogs","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageAuditLogResponse"}}}}}}},"/tenant/apps/{appUuid}":{"get":{"tags":["tenant-app-controller"],"operationId":"getApp","parameters":[{"name":"appUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAppResponse"}}}}}}},"/tenant/agent-update-policies/{policyUuid}":{"get":{"tags":["Tenant - Agent Update Policies"],"operationId":"get_6","parameters":[{"name":"policyUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentUpdatePolicyResponse"}}}}}},"delete":{"tags":["Tenant - Agent Update Policies"],"operationId":"delete_6","parameters":[{"name":"policyUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"}}}},"/tenant/agent-releases":{"get":{"tags":["Tenant - Agent Releases"],"summary":"List agent releases (optionally filter by channel + active)","operationId":"list_8","parameters":[{"name":"channel","in":"query","required":false,"schema":{"type":"string"}},{"name":"activeOnly","in":"query","required":false,"schema":{"type":"boolean","default":false}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":50}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAgentReleaseResponse"}}}}}}},"/tenant/agent-releases/{releaseUuid}":{"get":{"tags":["Tenant - Agent Releases"],"operationId":"get_7","parameters":[{"name":"releaseUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentReleaseResponse"}}}}}}},"/public/invitations/{token}":{"get":{"tags":["Invitations"],"summary":"Preview an invitation without authentication (safe subset)","operationId":"preview","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseInvitationPreview"}}}}}}},"/platform/test":{"get":{"tags":["Platform Admin"],"summary":"Platform admin test endpoint","description":"Test endpoint that requires PLATFORM_ADMIN role","operationId":"testPlatformAccess","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}},"security":[{"bearerAuth":[]}]}},"/platform/supplier-oauth-configs/{supplierUuid}":{"get":{"tags":["Platform - Supplier OAuth Config"],"summary":"Get supplier OAuth config (secret 미노출)","operationId":"get_8","parameters":[{"name":"supplierUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}},"delete":{"tags":["Platform - Supplier OAuth Config"],"summary":"Delete supplier OAuth config","operationId":"delete_7","parameters":[{"name":"supplierUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}}},"/platform/registration-events":{"get":{"tags":["Platform - Registration Events (Outbox)"],"summary":"outbox 이벤트 조회","description":"status / supplierUuid 필터(선택). occurredAt desc, 페이지네이션.","operationId":"list_9","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["PENDING","SENT","FAILED","DEAD"]}},{"name":"supplierUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":50}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageSupplierRegistrationEvent"}}}}}}},"/platform/permission-cache":{"get":{"tags":["Platform - Permission Cache"],"summary":"권한 캐시 조회","description":"userUuid / supplierUuid 필터(선택). fetchedAt desc, 페이지네이션.","operationId":"list_10","parameters":[{"name":"userUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"supplierUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":50}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageSupplierPermissionCache"}}}}}},"delete":{"tags":["Platform - Permission Cache"],"summary":"user×supplier 권한 캐시 무효화 (강제 refetch 유도)","description":"다음 권한 검사 시 cache miss → supplier.permission_query_url 재호출.","operationId":"invalidate","parameters":[{"name":"userUuid","in":"query","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"supplierUuid","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/platform/hubs/{hub_uuid}/status":{"get":{"tags":["Platform Hub Management"],"summary":"Check if hub is blocked","description":"Check if a hub is currently blocked","operationId":"getHubStatus","parameters":[{"name":"hub_uuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object","additionalProperties":{}}}}}}}},"/platform/audit-logs":{"get":{"tags":["Platform Audit Logs"],"summary":"Get platform audit logs","description":"Retrieve platform-level audit logs with pagination","operationId":"getPlatformAuditLogs","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageAuditLogResponse"}}}}}}},"/platform/agent-update-policies/{policyUuid}":{"get":{"tags":["Platform - Agent Update Policies"],"summary":"Get agent update policy","description":"Get a specific agent update policy by UUID","operationId":"getPolicy","parameters":[{"name":"policyUuid","in":"path","description":"Policy UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAgentUpdatePolicyResponse"}}}}}},"delete":{"tags":["Platform - Agent Update Policies"],"summary":"Delete agent update policy","description":"Delete a specific agent update policy","operationId":"deletePolicy","parameters":[{"name":"policyUuid","in":"path","description":"Policy UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"No Content"}}}},"/platform/activation-events":{"get":{"tags":["Platform - Activation Events"],"summary":"활성 이벤트 조회","description":"sync_status 필터(선택). occurredAt desc 정렬, 페이지네이션.","operationId":"list_11","parameters":[{"name":"syncStatus","in":"query","description":"PENDING | SYNCED | FAILED | REJECTED_BALANCE | BACKFILL_SKIPPED","required":false,"schema":{"type":"string","enum":["PENDING","SYNCED","FAILED","REJECTED_BALANCE","BACKFILL_SKIPPED"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":50}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponsePageDeviceActivationEvent"}}}}}}},"/openapi.json":{"get":{"tags":["open-api-controller"],"operationId":"getOpenApiSpec","responses":{"200":{"description":"OK"}}}},"/me/notifications":{"get":{"tags":["Me - Notifications"],"summary":"Recent notifications for the signed-in persona","operationId":"list_12","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseNotificationsResponse"}}}}}}},"/installer/{filename}":{"get":{"tags":["Public - Installer Auto-Update"],"summary":"Stream a release asset by filename — latest.yml or installer binary","description":"electron-updater polls latest.yml then GETs the .exe/.dmg/.AppImage referenced inside. Both go through this endpoint.","operationId":"download","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}}}}},"/health":{"get":{"tags":["Health"],"summary":"Health check","description":"Returns the health status of the application","operationId":"health","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseHealthStatus"}}}}}}},"/auth/supplier-link/callback":{"get":{"tags":["Auth - Supplier Link Callback"],"summary":"OAuth Authorization Code callback","operationId":"callback","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string"}},{"name":"error","in":"query","required":false,"schema":{"type":"string"}},{"name":"error_description","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/app/supplier-oauth-configs/{supplierUuid}":{"get":{"tags":["App - Supplier Link"],"summary":"Get consent preview (no secret)","description":"supplier가 required로 등록되어 있으면 consent_text/scope/userinfo_url 반환","operationId":"consentPreview","parameters":[{"name":"supplierUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/app/supplier-links":{"get":{"tags":["App - Supplier Link"],"summary":"List my active supplier links","description":"supplier_uuid 쿼리 시 그 supplier의 active link만 (n:1로 여러 개 가능)","operationId":"list_13","parameters":[{"name":"supplierUuid","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListSupplierLinkResponse"}}}}}}},"/app/supplier-links/{id}/access-token":{"get":{"tags":["App - Supplier Link"],"summary":"Get fresh access token","description":"만료 5분 이내면 자동 refresh 후 반환. step.configJson.external_submit_url 호출 직전에 사용.","operationId":"getAccessToken","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/app/notifications":{"get":{"tags":["App - Notifications"],"summary":"List notifications","description":"List notifications for current user (paginated)","operationId":"listNotifications","parameters":[{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int32","default":1}},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListNotificationResponse"}}}}}}},"/app/hubs":{"get":{"tags":["App - Hubs"],"summary":"List hubs","description":"List all hubs owned by current user","operationId":"listHubs_1","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListAppHubSummaryResponse"}}}}}}},"/app/hubs/{hubUuid}":{"get":{"tags":["App - Hubs"],"summary":"Get hub detail","description":"Get hub detail by UUID","operationId":"getHub_1","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAppHubDetailResponse"}}}}}}},"/app/devices":{"get":{"tags":["App - Devices"],"summary":"List user's devices","description":"List all devices from units where user has a persona","operationId":"listDevices_3","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListDeviceSummaryResponse"}}}}}}},"/app/devices/{deviceInstanceId}":{"get":{"tags":["App - Devices"],"summary":"Get device detail","description":"Get device detail by instance ID","operationId":"getDevice_3","parameters":[{"name":"deviceInstanceId","in":"path","description":"Device instance ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseDeviceDetailResponse"}}}}}}},"/app/devices/{deviceInstanceId}/sensor-data":{"get":{"tags":["App - Devices"],"summary":"Get sensor data","description":"Get sensor data for a device with optional time range","operationId":"getSensorData_1","parameters":[{"name":"deviceInstanceId","in":"path","description":"Device instance ID","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"from","in":"query","description":"Start time (ISO 8601)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"End time (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseObject"}}}}}}},"/app/device-ui/setup/{hubUuid}":{"get":{"tags":["App - Device UI Invoke (M4)"],"summary":"허브-device 의 device_ui setup 스키마 조회","description":"device_ui 미저작 시 404 → 앱은 legacy step-runner 로 fallback.","operationId":"getSetupUi","parameters":[{"name":"hubUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringObject"}}}}}}},"/app/bundle-catalog":{"get":{"tags":["App - Bundle Catalog"],"summary":"List PUBLISHED bundles","description":"현재 사용자 기준 link 상태 함께 반환","operationId":"list_14","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListBundleCatalogResponse"}}}}}}},"/app/bundle-catalog/{bundleUuid}":{"get":{"tags":["App - Bundle Catalog"],"summary":"Get bundle catalog detail","operationId":"get_9","parameters":[{"name":"bundleUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseBundleCatalogResponse"}}}}}}},"/app/action-definitions":{"get":{"tags":["App - Action Definitions"],"summary":"List action definitions for a supplier","description":"Returns all action definitions for the specified supplier","operationId":"list_15","parameters":[{"name":"supplierUuid","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseListActionDefinitionResponse"}}}}}}},"/app/action-definitions/{actionId}":{"get":{"tags":["App - Action Definitions"],"summary":"Get action definition","description":"Get a single action definition by ID","operationId":"get_10","parameters":[{"name":"actionId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseActionDefinitionResponse"}}}}}}},"/api-docs/customer":{"get":{"tags":["open-api-controller"],"operationId":"getCustomerApiSpec","responses":{"200":{"description":"OK"}}}},"/tenant/tenants/{tenantUuid}/members/{targetPersonaUuid}":{"delete":{"tags":["Tenants"],"summary":"Revoke access (ADMIN+; last OWNER protected)","operationId":"revokeMember","parameters":[{"name":"tenantUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"targetPersonaUuid","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}}},"/tenant/personas/invitations/{invitationId}":{"delete":{"tags":["Tenant - Personas"],"summary":"Mark an invitation REVOKED (unlike a member revoke, this is idempotent)","operationId":"revokeInvitation","parameters":[{"name":"invitationId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}}},"/tenant/hubs/{hubUuid}/setup-delegations/{id}":{"delete":{"tags":["Tenant - Setup Delegation"],"summary":"Revoke setup delegation","description":"Revoke a setup delegation","operationId":"revokeDelegation","parameters":[{"name":"hubUuid","in":"path","description":"Hub UUID","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"id","in":"path","description":"Delegation ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}},"/tenant/hubs/claim-codes/{claimCode}":{"delete":{"tags":["Tenant - Hubs"],"summary":"Hard-delete (unused) or soft-revoke (used) a claim code","operationId":"revokeClaimCode","parameters":[{"name":"claimCode","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No Content"}}}},"/app/supplier-links/{id}":{"delete":{"tags":["App - Supplier Link"],"summary":"Revoke supplier link","description":"supplier revoke_url 호출 + 로컬 soft-revoke","operationId":"revoke_1","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseMapStringString"}}}}}}},"/app/consent/{consentId}":{"delete":{"tags":["App - Consent"],"summary":"Withdraw consent","description":"Withdraw a previously granted consent","operationId":"withdrawConsent","parameters":[{"name":"consentId","in":"path","description":"Consent record ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}}}}},"components":{"schemas":{"SupplierOauthConfigRequest":{"type":"object","description":"Supplier OAuth client config registration","properties":{"supplierUuid":{"type":"string","format":"uuid","description":"Supplier UUID. Platform endpoint에서는 필수, Tenant endpoint에서는 무시되고 X-Tenant-UUID 헤더가 사용됨.","example":"11111111-1111-1111-1111-111111111111"},"authorizeUrl":{"type":"string","maxLength":500,"minLength":0},"tokenUrl":{"type":"string","maxLength":500,"minLength":0},"clientId":{"type":"string","minLength":1},"clientSecret":{"type":"string","description":"OAuth client secret in plaintext — server encrypts before storing.","minLength":1},"scopes":{"type":"string","description":"JSON array. 예: [\"openid\",\"provisioning:write\"]","example":["openid","provisioning:write"],"minLength":1},"consentText":{"type":"string","minLength":1},"consentTextLocaleMap":{"type":"string","description":"{\"ko\":\"...\",\"en\":\"...\"} (optional)"},"userinfoUrl":{"type":"string","description":"n:1 모델에서 sub로 supplier-account 식별 — 필수","maxLength":500,"minLength":0},"revokeUrl":{"type":"string","maxLength":500,"minLength":0},"permissionQueryUrl":{"type":"string","description":"supplier 권한 SSOT일 때 호출되는 endpoint. 응답: [{resource_type, resource_uuid, permissions[]}]. null이면 LinkOStar SSOT.","maxLength":500,"minLength":0},"permissionWebhookUrl":{"type":"string","description":"(참고용) supplier가 자기 webhook 흐름 식별/검증에 쓸 수도 있는 URL — LinkOStar는 직접 호출하지 않는다.","maxLength":500,"minLength":0},"hubRegistrationUrl":{"type":"string","description":"LinkOStar가 새 hub_instance 만들 때 push할 endpoint (outbox + HMAC 서명)","maxLength":500,"minLength":0},"deviceRegistrationUrl":{"type":"string","description":"LinkOStar가 새 device_instance 만들 때 push할 endpoint (outbox + HMAC 서명)","maxLength":500,"minLength":0},"registrationSharedSecret":{"type":"string","description":"HMAC-SHA256 양방향 webhook 서명 공유 비밀 (plaintext, 서버가 즉시 AES-GCM 암호화)."}},"required":["authorizeUrl","clientId","clientSecret","consentText","scopes","tokenUrl","userinfoUrl"]},"ApiResponseMapStringObject":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageInfo":{"type":"object","properties":{"page":{"type":"integer","format":"int32"},"size":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"}}},"ApiResponseListUUID":{"type":"object","properties":{"data":{"type":"array","items":{"type":"string","format":"uuid"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BundleDeviceRefRequest":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"autoProvision":{"type":"boolean"},"defaultVersionUuid":{"type":"string","format":"uuid"},"note":{"type":"string","maxLength":500,"minLength":0}},"required":["deviceUuid"]},"ApiResponseListObject":{"type":"object","properties":{"data":{"type":"array","items":{}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BundleAppRefRequest":{"type":"object","properties":{"managedAppUuid":{"type":"string","format":"uuid"},"installOrder":{"type":"integer","format":"int32"},"pinnedVersion":{"type":"string","maxLength":64,"minLength":0},"envOverridesJson":{"type":"string"}},"required":["managedAppUuid"]},"UpsertNotificationSettingRequest":{"type":"object","properties":{"notificationType":{"type":"string","maxLength":32,"minLength":0},"channel":{"type":"string","minLength":1,"pattern":"EMAIL|PUSH|SMS|WEBHOOK"},"enabled":{"type":"boolean"}},"required":["channel","enabled","notificationType"]},"ApiResponseNotificationSettingResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/NotificationSettingResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"NotificationSettingResponse":{"type":"object","properties":{"settingId":{"type":"integer","format":"int64"},"userUuid":{"type":"string","format":"uuid"},"notificationType":{"type":"string"},"channel":{"type":"string"},"enabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ExternalEndpointRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":120,"minLength":0},"baseUrl":{"type":"string","maxLength":500,"minLength":0,"pattern":"^https://.+"},"verifyMethod":{"type":"string","pattern":"DNS_TXT|WELL_KNOWN"},"authType":{"type":"string","pattern":"NONE|API_KEY|BEARER|HMAC"},"authConfig":{"type":"string","maxLength":1900,"minLength":0},"description":{"type":"string","maxLength":2000,"minLength":0}},"required":["baseUrl","name"]},"JsonNode":{"type":"object","properties":{"valueNode":{"type":"boolean"},"container":{"type":"boolean"},"missingNode":{"type":"boolean"},"object":{"type":"boolean"},"nodeType":{"type":"string","enum":["ARRAY","BINARY","BOOLEAN","MISSING","NULL","NUMBER","OBJECT","POJO","STRING"]},"string":{"type":"boolean"},"integralNumber":{"type":"boolean"},"pojo":{"type":"boolean"},"floatingPointNumber":{"type":"boolean"},"short":{"type":"boolean"},"int":{"type":"boolean"},"long":{"type":"boolean"},"double":{"type":"boolean"},"bigDecimal":{"type":"boolean"},"bigInteger":{"type":"boolean"},"textual":{"type":"boolean","deprecated":true},"boolean":{"type":"boolean"},"binary":{"type":"boolean"},"array":{"type":"boolean"},"empty":{"type":"boolean"},"null":{"type":"boolean"},"float":{"type":"boolean"},"number":{"type":"boolean"},"embeddedValue":{"type":"boolean"}}},"UpdatePipelineRequest":{"type":"object","description":"Update pipeline (V16 모델 — endpointsJson + forward op). null field = leave existing value alone.","properties":{"pipelineName":{"type":"string","description":"Pipeline display name","maxLength":255,"minLength":0},"sourceType":{"type":"string","description":"Source scope (HUB / DEVICE_INSTANCE / DEVICE_GROUP / UNIT)","maxLength":32,"minLength":0},"sourceUuid":{"type":"string","format":"uuid","description":"Source UUID — HUB/DEVICE_GROUP 매칭 시"},"sourceId":{"type":"integer","format":"int64","description":"Source numeric id — DEVICE_INSTANCE 매칭 시"},"mode":{"type":"string","description":"Aggregation/forwarding mode","maxLength":32,"minLength":0},"windowConfigJson":{"$ref":"#/components/schemas/JsonNode","description":"Window aggregation config"},"pipelineRulesJson":{"$ref":"#/components/schemas/JsonNode","description":"Rules — PipelineOp array"},"endpointsJson":{"$ref":"#/components/schemas/JsonNode","description":"Endpoint catalog. rules 의 forward op 가 key 로 라우팅."},"signingSecret":{"type":"string","description":"Webhook signing secret (HMAC). endpointsJson 내 signing_secret_b64 권장."},"enabled":{"type":"boolean","description":"Enabled flag"},"healthCheckIntervalSec":{"type":"integer","format":"int32","description":"Per-pipeline rate cap (optional)"},"healthCheckFailureThreshold":{"type":"integer","format":"int32","description":"Per-pipeline failure threshold (optional)"},"destinationType":{"type":"string","deprecated":true,"description":"[DEPRECATED v0.2.7] use endpointsJson","maxLength":16,"minLength":0},"destinationUrl":{"type":"string","deprecated":true,"description":"[DEPRECATED v0.2.7] use endpointsJson","maxLength":1024,"minLength":0},"destinationAuthJson":{"$ref":"#/components/schemas/JsonNode","deprecated":true,"description":"[DEPRECATED v0.2.7] use endpointsJson"},"pipelineLayer":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] use endpointsJson","maxLength":16,"minLength":0},"directDeliveryUrl":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] use endpointsJson","maxLength":512,"minLength":0},"directDeliveryApiKey":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] use endpointsJson","maxLength":256,"minLength":0},"fallbackDeliveryUrl":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] use endpointsJson","maxLength":512,"minLength":0}}},"ApiResponsePipelineConfigResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PipelineConfigResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PipelineConfigResponse":{"type":"object","properties":{"pipelineUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"supplierUuid":{"type":"string","format":"uuid"},"pipelineName":{"type":"string"},"sourceType":{"type":"string"},"sourceUuid":{"type":"string","format":"uuid"},"sourceId":{"type":"integer","format":"int64"},"mode":{"type":"string"},"windowConfigJson":{"$ref":"#/components/schemas/JsonNode"},"pipelineRulesJson":{"$ref":"#/components/schemas/JsonNode"},"endpointsJson":{"$ref":"#/components/schemas/JsonNode"},"enabled":{"type":"boolean"},"destinationType":{"type":"string","deprecated":true},"destinationUrl":{"type":"string","deprecated":true},"destinationAuthJson":{"$ref":"#/components/schemas/JsonNode","deprecated":true},"pipelineLayer":{"type":"string","deprecated":true},"directDeliveryUrl":{"type":"string","deprecated":true},"directDeliveryApiKey":{"type":"string","deprecated":true},"fallbackDeliveryUrl":{"type":"string","deprecated":true},"healthCheckIntervalSec":{"type":"integer","format":"int32"},"healthCheckFailureThreshold":{"type":"integer","format":"int32"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"BleRouteConfigRequest":{"type":"object","properties":{"mode":{"type":"string","maxLength":16,"minLength":0},"endpointUrl":{"type":"string","maxLength":1024,"minLength":0},"authJson":{"$ref":"#/components/schemas/JsonNode"},"signingSecret":{"type":"string"},"processingEnabled":{"type":"boolean"},"parserType":{"type":"string","maxLength":32,"minLength":0},"parserConfigJson":{"$ref":"#/components/schemas/JsonNode"},"pipelineConfigJson":{"$ref":"#/components/schemas/JsonNode"},"enabled":{"type":"boolean"}},"required":["enabled","mode","processingEnabled"]},"ApiResponseBleRouteConfigResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BleRouteConfigResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BleRouteConfigResponse":{"type":"object","properties":{"tenantUuid":{"type":"string","format":"uuid"},"mode":{"type":"string"},"endpointUrl":{"type":"string"},"authJson":{"$ref":"#/components/schemas/JsonNode"},"processingEnabled":{"type":"boolean"},"parserType":{"type":"string"},"parserConfigJson":{"$ref":"#/components/schemas/JsonNode"},"pipelineConfigJson":{"$ref":"#/components/schemas/JsonNode"},"enabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiResponseMapStringString":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"type":"string"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiKeyUpdateRequest":{"type":"object","properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"rateLimit":{"type":"integer","format":"int32"}}},"ApiKeyListResponse":{"type":"object","properties":{"apiKeyId":{"type":"integer","format":"int64"},"keyPrefix":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"rateLimit":{"type":"integer","format":"int32"},"expiresAt":{"type":"string"},"lastUsedAt":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string"}}},"ApiResponseApiKeyListResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApiKeyListResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"CreateAgentUpdatePolicyRequest":{"type":"object","properties":{"scopeType":{"type":"string","minLength":1},"tenantUuid":{"type":"string","format":"uuid"},"hubUuid":{"type":"string","format":"uuid"},"channel":{"type":"string","minLength":1},"autoApply":{"type":"boolean"},"rolloutPercentage":{"type":"integer","format":"int32","maximum":100,"minimum":0},"allowlistJson":{},"denylistJson":{},"maintenanceJson":{},"paused":{"type":"boolean"}},"required":["channel","scopeType"]},"AgentUpdatePolicyResponse":{"type":"object","properties":{"policyUuid":{"type":"string","format":"uuid"},"scopeType":{"type":"string"},"tenantUuid":{"type":"string","format":"uuid"},"hubUuid":{"type":"string","format":"uuid"},"channel":{"type":"string"},"autoApply":{"type":"boolean"},"rolloutPercentage":{"type":"integer","format":"int32"},"allowlistJson":{"$ref":"#/components/schemas/JsonNode"},"denylistJson":{"$ref":"#/components/schemas/JsonNode"},"maintenanceJson":{"$ref":"#/components/schemas/JsonNode"},"paused":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiResponseAgentUpdatePolicyResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AgentUpdatePolicyResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"UserProfileUpdateRequest":{"type":"object","properties":{"userNick":{"type":"string"}}},"ApiResponseUserProfileResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/UserProfileResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"UserProfileResponse":{"type":"object","properties":{"userUuid":{"type":"string","format":"uuid"},"email":{"type":"string"},"userNick":{"type":"string"},"userStatus":{"type":"string"},"joinedAt":{"type":"string","format":"date-time"}}},"ApiResponseVoid":{"type":"object","properties":{"data":{},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"RetentionUpdateRequest":{"type":"object","properties":{"retentionPeriodDays":{"type":"integer","format":"int32"}},"required":["retentionPeriodDays"]},"ApiResponseRetentionSettingResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RetentionSettingResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"RetentionSettingResponse":{"type":"object","properties":{"consentId":{"type":"integer","format":"int64"},"retentionPeriodDays":{"type":"integer","format":"int32"}}},"HubJobEventRequest":{"type":"object","properties":{"jobState":{"type":"string","minLength":1},"progress":{"type":"integer","format":"int32","maximum":100,"minimum":0},"message":{"type":"string"},"resultJson":{"$ref":"#/components/schemas/JsonNode"}},"required":["jobState"]},"Advertisement":{"type":"object","properties":{"serviceUuids":{"type":"array","items":{"type":"string"}},"manufacturerData":{"$ref":"#/components/schemas/ManufacturerData"},"ibeaconUuid":{"type":"string"},"eddystoneUid":{"type":"string"}}},"DeviceQueryRequest":{"type":"object","properties":{"macAddress":{"type":"string","maxLength":32,"minLength":0},"advertisement":{"$ref":"#/components/schemas/Advertisement"}}},"ManufacturerData":{"type":"object","properties":{"companyId":{"type":"string"},"dataHex":{"type":"string"}}},"ApiResponseDeviceQueryResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceQueryResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceQueryResponse":{"type":"object","properties":{"deviceInstanceId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionUuid":{"type":"string","format":"uuid"},"registrationMode":{"type":"string"},"activationStatus":{"type":"string"},"activatedAt":{"type":"string","format":"date-time"},"matchedIdentifier":{"$ref":"#/components/schemas/MatchedIdentifier"}}},"MatchedIdentifier":{"type":"object","properties":{"kind":{"type":"string"},"value":{"type":"string"}}},"CertificateIssueRequest":{"type":"object","properties":{"csrPem":{"type":"string","minLength":1}},"required":["csrPem"]},"ApiResponseCertificateIssueResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CertificateIssueResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"CertificateIssueResponse":{"type":"object","properties":{"serial":{"type":"string"},"certPem":{"type":"string"},"caBundlePem":{"type":"string"},"notBefore":{"type":"string","format":"date-time"},"notAfter":{"type":"string","format":"date-time"}}},"HubRefreshRequest":{"type":"object","description":"Request to refresh hub access token","properties":{"refreshToken":{"type":"string","description":"Refresh token obtained from claim or previous refresh","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","minLength":1}},"required":["refreshToken"]},"ApiResponse":{"type":"object","properties":{"data":{},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubClaimRequest":{"type":"object","description":"Request to claim/register a hub instance","properties":{"deviceInstanceId":{"type":"integer","format":"int64","description":"Unique device instance ID from hardware","example":123},"claimCode":{"type":"string","description":"Claim code generated by tenant (format: XXXX-XXXX-XXXX-XXXX)","example":"ABCD-1234-EFGH-5678","minLength":1},"hubIdentifier":{"type":"string","description":"Human-readable hub identifier (optional)","example":"living-room-hub"},"hubType":{"type":"string","description":"Hub type (OPEN or CLOSED, defaults to CLOSED)","example":"CLOSED"},"csrPem":{"type":"string","description":"Optional PKCS#10 CSR (PEM). Backend signs + returns cert in same response (Phase 1c).","example":"-----BEGIN CERTIFICATE REQUEST-----\\n…\\n-----END CERTIFICATE REQUEST-----\\n"},"supplierUuid":{"type":"string","format":"uuid","description":"Supplier UUID (from claim code context or request)"},"ownerUserUuid":{"type":"string","format":"uuid","description":"Owner user UUID (APP_USER who claimed this hub)"},"macAddress":{"type":"string","description":"Optional MAC address for stronger supplier identification","example":"AA:BB:CC:DD:EE:FF"}},"required":["claimCode","deviceInstanceId"]},"AdapterReport":{"type":"object","properties":{"address":{"type":"string","maxLength":17,"minLength":0},"adapterId":{"type":"string","maxLength":8,"minLength":0},"name":{"type":"string","maxLength":64,"minLength":0},"powered":{"type":"boolean"},"discoverable":{"type":"boolean"},"pairable":{"type":"boolean"},"active":{"type":"boolean"}},"required":["address"]},"Payload":{"type":"object","properties":{"adapters":{"type":"array","items":{"$ref":"#/components/schemas/AdapterReport"}}}},"ApiResponseResult":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Result"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"Result":{"type":"object","properties":{"reported":{"type":"integer","format":"int32"},"markedUnpowered":{"type":"integer","format":"int32"}}},"BleEventUploadRequest":{"type":"object","properties":{"payloadJson":{"$ref":"#/components/schemas/JsonNode"},"rssi":{"type":"integer","format":"int32"},"rawBase64":{"type":"string"},"deviceInstanceId":{"type":"integer","format":"int64"}},"required":["payloadJson"]},"ApiResponseBleEventUploadResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BleEventUploadResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BleEventUploadResponse":{"type":"object","properties":{"bleEventId":{"type":"integer","format":"int64"},"status":{"type":"string"}}},"WindowedBleEventRequest":{"type":"object","properties":{"payloadJson":{"$ref":"#/components/schemas/JsonNode"},"deviceInstanceId":{"type":"integer","format":"int64"},"windowStart":{"type":"string","format":"date-time"},"windowEnd":{"type":"string","format":"date-time"},"eventCount":{"type":"integer","format":"int32"}},"required":["payloadJson"]},"ApiResponseWindowedBleEventResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WindowedBleEventResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"WindowedBleEventResponse":{"type":"object","properties":{"status":{"type":"string"},"pipelinesTriggered":{"type":"integer","format":"int32"},"processedResult":{"$ref":"#/components/schemas/JsonNode"}}},"ApiResponseTenantTransferRequestResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TenantTransferRequestResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"TenantTransferRequestResponse":{"type":"object","properties":{"requestUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"fromUnitUuid":{"type":"string","format":"uuid"},"toUnitUuid":{"type":"string","format":"uuid"},"requestedByPersonaUuid":{"type":"string","format":"uuid"},"status":{"type":"string"},"note":{"type":"string"},"requestedAt":{"type":"string","format":"date-time"},"respondedAt":{"type":"string","format":"date-time"},"respondedByPersonaUuid":{"type":"string","format":"uuid"}}},"CreateTenantRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":100,"minLength":0}},"required":["name"]},"ApiResponseTenantResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TenantResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"TenantResponse":{"type":"object","properties":{"tenantUuid":{"type":"string","format":"uuid"},"name":{"type":"string"},"ownerUnitUuid":{"type":"string","format":"uuid"},"status":{"type":"string"},"myRole":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"InitiateTransferRequest":{"type":"object","properties":{"toUnitUuid":{"type":"string","format":"uuid"},"note":{"type":"string","maxLength":500,"minLength":0}},"required":["toUnitUuid"]},"GrantAccessRequest":{"type":"object","properties":{"personaUuid":{"type":"string","format":"uuid"},"role":{"type":"string","minLength":1}},"required":["personaUuid","role"]},"ApiResponseTenantMemberResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TenantMemberResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"TenantMemberResponse":{"type":"object","properties":{"personaUuid":{"type":"string","format":"uuid"},"email":{"type":"string"},"displayName":{"type":"string"},"role":{"type":"string"},"grantedAt":{"type":"string","format":"date-time"},"grantedByPersonaUuid":{"type":"string","format":"uuid"},"lastActiveAt":{"type":"string","format":"date-time"}}},"CreateBundleRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":0},"versionLabel":{"type":"string","maxLength":64,"minLength":0},"description":{"type":"string","maxLength":1000,"minLength":0},"thumb":{"type":"string","maxLength":500,"minLength":0},"agentChannel":{"type":"string","maxLength":64,"minLength":0},"metadata":{"type":"string"}},"required":["name"]},"ApiResponseBundleResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BundleResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BundleResponse":{"type":"object","properties":{"bundleUuid":{"type":"string","format":"uuid"},"supplierUuid":{"type":"string","format":"uuid"},"name":{"type":"string"},"versionLabel":{"type":"string"},"description":{"type":"string"},"thumb":{"type":"string"},"agentChannel":{"type":"string"},"status":{"type":"string"},"metadata":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"publishedAt":{"type":"string","format":"date-time"},"archivedAt":{"type":"string","format":"date-time"},"hubDeviceUuid":{"type":"string","format":"uuid"}}},"StreamSimulationRequest":{"type":"object","properties":{"pipelineUuid":{"type":"string","format":"uuid"},"preset":{"type":"string"},"count":{"type":"integer","format":"int32","maximum":100,"minimum":1},"intervalSec":{"type":"integer","format":"int32","minimum":1},"mode":{"type":"string","enum":["LIVE","DRY_RUN"]}},"required":["mode","pipelineUuid"]},"ApiResponseListSimulationResult":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SimulationResult"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"SimulationResult":{"type":"object","properties":{"inputData":{"type":"object","additionalProperties":{}},"pipelineOutput":{"type":"object","additionalProperties":{}},"webhookDelivery":{"$ref":"#/components/schemas/WebhookDeliveryResult"},"simulatedAt":{"type":"string","format":"date-time"}}},"WebhookDeliveryResult":{"type":"object","properties":{"statusCode":{"type":"integer","format":"int32"},"responseBody":{"type":"string"},"durationMs":{"type":"integer","format":"int64"},"success":{"type":"boolean"}}},"SimulationRequest":{"type":"object","properties":{"pipelineUuid":{"type":"string","format":"uuid"},"preset":{"type":"string"},"customData":{"type":"object","additionalProperties":{}},"mode":{"type":"string","enum":["LIVE","DRY_RUN"]}},"required":["mode","pipelineUuid"]},"ApiResponseSimulationResult":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SimulationResult"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PersonaInviteRequest":{"type":"object","properties":{"email":{"type":"string","maxLength":255,"minLength":0},"personaUuid":{"type":"string","format":"uuid"},"displayName":{"type":"string","maxLength":100,"minLength":0},"role":{"type":"string","minLength":1,"pattern":"OWNER|ADMIN|MEMBER"}},"required":["role"]},"ApiResponseInviteResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InviteResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"InviteResponse":{"type":"object","properties":{"member":{"$ref":"#/components/schemas/TenantMemberResponse"},"invitation":{"$ref":"#/components/schemas/TenantInvitationResponse"}}},"TenantInvitationResponse":{"type":"object","properties":{"invitationId":{"type":"integer","format":"int64"},"email":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"invitedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"acceptedAt":{"type":"string","format":"date-time"},"acceptedPersonaUuid":{"type":"string","format":"uuid"},"invitedByPersonaUuid":{"type":"string","format":"uuid"},"emailSentAt":{"type":"string","format":"date-time"},"emailError":{"type":"string"}}},"ApiResponseTenantInvitationResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TenantInvitationResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListNotificationSettingResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/NotificationSettingResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"CreateDeviceManualRequest":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceManualName":{"type":"string","maxLength":255,"minLength":0},"deviceManualVersion":{"type":"string","maxLength":255,"minLength":0},"deviceManualLink":{"type":"string","maxLength":255,"minLength":0},"deviceManualLog":{"type":"string","maxLength":255,"minLength":0}},"required":["deviceUuid"]},"ApiResponseDeviceManualResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceManualResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceManualResponse":{"type":"object","properties":{"deviceManualId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"deviceManualName":{"type":"string"},"deviceManualVersion":{"type":"string"},"deviceManualLink":{"type":"string"},"deviceManualLog":{"type":"string"}}},"SetupDelegationRequest":{"type":"object","description":"Create a setup delegation for a hub","properties":{"delegatedToUserUuid":{"type":"string","format":"uuid","description":"UUID of the user to delegate setup to","example":"550e8400-e29b-41d4-a716-446655440000"},"expiresInHours":{"type":"integer","format":"int32","description":"Hours until the delegation expires (null for no expiry)","example":24}},"required":["delegatedToUserUuid"]},"ApiResponseSetupDelegationResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SetupDelegationResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"SetupDelegationResponse":{"type":"object","description":"Setup delegation details","properties":{"id":{"type":"integer","format":"int64","description":"Delegation ID"},"hubUuid":{"type":"string","format":"uuid","description":"Hub UUID"},"delegatedToUserUuid":{"type":"string","format":"uuid","description":"User UUID the setup is delegated to"},"delegatedByUuid":{"type":"string","format":"uuid","description":"User UUID who created the delegation"},"expiresAt":{"type":"string","format":"date-time","description":"When the delegation expires"},"usedAt":{"type":"string","format":"date-time","description":"When the delegation was used"},"createdAt":{"type":"string","format":"date-time","description":"When the delegation was created"}}},"ApiResponseUUID":{"type":"object","properties":{"data":{"type":"string","format":"uuid"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AppInstallRequest":{"type":"object","properties":{"appReleaseUuid":{"type":"string","format":"uuid"}},"required":["appReleaseUuid"]},"ClaimCodeGenerateRequest":{"type":"object","description":"Request to generate a hub claim code","properties":{"maxUses":{"type":"integer","format":"int32","default":1,"description":"Maximum number of times this code can be used","example":1,"maximum":100,"minimum":1},"expiresInSeconds":{"type":"integer","format":"int64","default":86400,"description":"Expiration time in seconds from now","example":86400,"maximum":2592000,"minimum":300},"aliasHint":{"type":"string","description":"Optional human-readable alias hint. Copied to hub_instance on claim.","example":"거실 허브","maxLength":100,"minLength":0},"description":{"type":"string","description":"Optional description of the hub. Copied to hub_instance on claim.","example":"1층 거실, 조명/스피커 연결","maxLength":500,"minLength":0},"isOpen":{"type":"boolean","default":false,"description":"Pre-claim Open/Closed flag. true=OPEN hub, false=CLOSED. Defaults to false.","example":false},"macHint":{"type":"string","description":"Optional MAC hint for stronger supplier identification at claim time.","example":"AA:BB:CC:DD:EE:FF","maxLength":32,"minLength":0},"supplierUuid":{"type":"string","format":"uuid","description":"Supplier UUID owning this claim code","example":"11111111-..."},"bundleUuid":{"type":"string","format":"uuid","description":"Supplier bundle to apply on claim (PUBLISHED only)","example":"22222222-..."},"metadata":{"type":"string","description":"supplier-opaque metadata as JSON string. LinkOStar passes through to hub_instance unchanged.","example":{"eds":{"v":1,"owner_id":"...","space_id":"..."}}}}},"ApiResponseClaimCodeResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ClaimCodeResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ClaimCodeResponse":{"type":"object","description":"Generated hub claim code","properties":{"claimCode":{"type":"string","description":"The claim code to be used by the hub","example":"ABCD-1234-EFGH-5678"},"expiresAt":{"type":"string","format":"date-time","description":"When this code expires","example":"2026-02-27T10:00:00Z"},"maxUses":{"type":"integer","format":"int32","description":"Maximum number of times this code can be used","example":1},"createdAt":{"type":"string","format":"date-time","description":"When this code was created","example":"2026-02-26T10:00:00Z"},"aliasHint":{"type":"string","description":"Pre-claim hub alias hint, copied to hub_instance on claim","example":"거실 허브"},"description":{"type":"string","description":"Pre-claim hub description, copied to hub_instance on claim"},"isOpen":{"type":"boolean","description":"Pre-claim Open/Closed flag (true=OPEN, false=CLOSED)","example":false},"macHint":{"type":"string","description":"Pre-claim MAC hint","example":"AA:BB:CC:DD:EE:FF"},"supplierUuid":{"type":"string","format":"uuid","description":"Supplier UUID stamped on the resulting hub_instance"},"bundleUuid":{"type":"string","format":"uuid","description":"Supplier bundle to apply on claim (PUBLISHED only)"},"metadata":{"type":"string","description":"supplier-opaque metadata as JSON string (V9). Copied verbatim to hub_instance on claim."}}},"CreateDeviceInstanceRequest":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionUuid":{"type":"string","format":"uuid"},"deviceVersionCode":{"type":"string","maxLength":255,"minLength":0},"deviceCustomName":{"type":"string","maxLength":255,"minLength":0},"isActivated":{"type":"boolean"},"thumb":{"type":"string","maxLength":50,"minLength":0},"macAddress":{"type":"string","maxLength":32,"minLength":0},"hubUuid":{"type":"string","format":"uuid"}},"required":["deviceUuid","deviceVersionUuid"]},"ApiResponseDeviceInstanceResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceInstanceResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceInstanceResponse":{"type":"object","properties":{"deviceInstanceId":{"type":"integer","format":"int64"},"tenantUuid":{"type":"string","format":"uuid"},"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionUuid":{"type":"string","format":"uuid"},"deviceVersionCode":{"type":"string"},"deviceCustomName":{"type":"string"},"isActivated":{"type":"boolean"},"paymentDueDate":{"type":"string","format":"date-time"},"thumb":{"type":"string"},"macAddress":{"type":"string"},"activationStatus":{"type":"string"},"activatedAt":{"type":"string","format":"date-time"},"firstSeenHubUuid":{"type":"string","format":"uuid"}}},"CreateDeviceVersionRequest":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionCode":{"type":"string","maxLength":255,"minLength":0},"deviceVersionName":{"type":"string","maxLength":255,"minLength":0},"publishDatetime":{"type":"string","format":"date-time"}},"required":["deviceUuid","deviceVersionCode"]},"ApiResponseDeviceVersionResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceVersionResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceVersionResponse":{"type":"object","properties":{"deviceVersionUuid":{"type":"string","format":"uuid"},"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionCode":{"type":"string"},"deviceVersionName":{"type":"string"},"publishDatetime":{"type":"string","format":"date-time"}}},"CreateDeviceUiRequest":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceUiName":{"type":"string","maxLength":255,"minLength":0},"deviceUiVersion":{"type":"string","maxLength":255,"minLength":0},"deviceUiContent":{"type":"string"},"deviceUiLog":{"type":"string"}},"required":["deviceUuid"]},"ApiResponseDeviceUiResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceUiResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceUiResponse":{"type":"object","properties":{"deviceUiId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"deviceUiName":{"type":"string"},"deviceUiVersion":{"type":"string"},"deviceUiContent":{"type":"string"},"deviceUiLog":{"type":"string"}}},"CreateDeviceProtocolRequest":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceProtocolName":{"type":"string","maxLength":255,"minLength":0},"deviceProtocolVersion":{"type":"string","maxLength":255,"minLength":0},"deviceProtocolContent":{"type":"string"},"deviceProtocolLog":{"type":"string"}},"required":["deviceUuid"]},"ApiResponseDeviceProtocolResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceProtocolResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceProtocolResponse":{"type":"object","properties":{"deviceProtocolId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"deviceProtocolName":{"type":"string"},"deviceProtocolVersion":{"type":"string"},"deviceProtocolContent":{"type":"string"},"deviceProtocolLog":{"type":"string"}}},"CreateDeviceRequest":{"type":"object","properties":{"deviceName":{"type":"string","maxLength":255,"minLength":0},"deviceModel":{"type":"string","maxLength":255,"minLength":0},"isPublic":{"type":"boolean"},"publishDatetime":{"type":"string","format":"date-time"},"deviceGroupUuid":{"type":"string","format":"uuid"},"registrationMode":{"type":"string","pattern":"PRE_REGISTERED|AUTO_ON_MATCH"},"activationCredit":{"type":"integer","format":"int32","minimum":0},"isHub":{"type":"boolean"},"bundleUuid":{"type":"string","format":"uuid"}},"required":["deviceName"]},"ApiResponseDeviceCatalogResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceCatalogResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceCatalogResponse":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceModel":{"type":"string"},"deviceName":{"type":"string"},"isPublic":{"type":"boolean"},"publishDatetime":{"type":"string","format":"date-time"},"deviceGroupUuid":{"type":"string","format":"uuid"},"registrationMode":{"type":"string"},"activationCredit":{"type":"integer","format":"int32"},"isHub":{"type":"boolean"},"bundleUuid":{"type":"string","format":"uuid"}}},"CreateDeviceMatchIdentifierRequest":{"type":"object","properties":{"kind":{"type":"string","minLength":1,"pattern":"IBEACON_UUID|SERVICE_UUID|MANUFACTURER_DATA_PREFIX|EDDYSTONE_UID|BLE_MAC_PREFIX"},"value":{"type":"string","maxLength":255,"minLength":0},"label":{"type":"string","maxLength":100,"minLength":0},"notes":{"type":"string","maxLength":500,"minLength":0}},"required":["kind","value"]},"ApiResponseDeviceMatchIdentifierResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceMatchIdentifierResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceMatchIdentifierResponse":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"kind":{"type":"string"},"value":{"type":"string"},"label":{"type":"string"},"notes":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"CreatePipelineRequest":{"type":"object","description":"Create pipeline (V16 모델 — endpointsJson + forward op 사용)","properties":{"pipelineName":{"type":"string","description":"Pipeline display name","example":"Stone temperature → EDS","maxLength":255,"minLength":0},"sourceType":{"type":"string","description":"Source scope — HUB / DEVICE_INSTANCE / DEVICE_GROUP / UNIT (tenant-level)","enum":["HUB","DEVICE_INSTANCE","DEVICE_GROUP","UNIT"],"example":"UNIT","maxLength":32,"minLength":0},"sourceUuid":{"type":"string","format":"uuid","description":"Source UUID — HUB/DEVICE_GROUP 매칭 시 사용. UNIT 매칭이면 null."},"sourceId":{"type":"integer","format":"int64","description":"Source numeric id — DEVICE_INSTANCE 매칭 시 사용."},"mode":{"type":"string","description":"Aggregation/forwarding mode","enum":["FORWARD_RAW","FORWARD_PROCESSED","WINDOW_FORWARD","STORE","STORE_AND_FORWARD","WINDOW_STORE"],"example":"FORWARD_RAW","maxLength":32,"minLength":0},"windowConfigJson":{"$ref":"#/components/schemas/JsonNode","description":"Window aggregation config (optional)"},"pipelineRulesJson":{"$ref":"#/components/schemas/JsonNode","description":"Rules — PipelineOp array. Use forward op to dispatch to an endpoint key.","example":[{"op":"filter","field":"deviceName","eq":"Jinada Stone"},{"op":"forward","endpoint":"eds_main"}]},"endpointsJson":{"$ref":"#/components/schemas/JsonNode","description":"Endpoint catalog (V16 새 모델). rules 의 forward op 가 key 로 라우팅. reserved key 'linkostar' = backend windowed endpoint.","example":{"eds_main":{"url":"https://eds.example.com/webhook","headers":{"X-Webhook-Secret":"secret"}}}},"signingSecret":{"type":"string","description":"Webhook signing secret (HMAC). endpointsJson 내 signing_secret_b64 권장."},"enabled":{"type":"boolean","description":"Enabled flag — false 면 agent 가 안 받음","example":true},"healthCheckIntervalSec":{"type":"integer","format":"int32","description":"Per-pipeline rate cap (optional, 향후)"},"healthCheckFailureThreshold":{"type":"integer","format":"int32","description":"Per-pipeline failure threshold (optional)"},"destinationType":{"type":"string","deprecated":true,"description":"[DEPRECATED v0.2.7] Destination type. endpointsJson 사용으로 대체. 옛 SERVER-layer 흐름 호환만.","enum":["INTERNAL","WEBHOOK"],"maxLength":16,"minLength":0},"destinationUrl":{"type":"string","deprecated":true,"description":"[DEPRECATED v0.2.7] Server-layer webhook URL. endpointsJson 의 endpoint url 로 대체.","maxLength":1024,"minLength":0},"destinationAuthJson":{"$ref":"#/components/schemas/JsonNode","deprecated":true,"description":"[DEPRECATED v0.2.7] Server-layer webhook auth headers. endpointsJson 의 endpoint headers 로 대체."},"pipelineLayer":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] pipeline_layer (HUB/SERVER). 새 모델은 endpoint 별로 agent 가 알아서 결정.","maxLength":16,"minLength":0},"directDeliveryUrl":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] HUB-layer direct delivery URL. endpointsJson 사용.","maxLength":512,"minLength":0},"directDeliveryApiKey":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] HUB-layer X-Hub-API-Key 헤더 값. endpointsJson 의 endpoint headers 사용.","maxLength":256,"minLength":0},"fallbackDeliveryUrl":{"type":"string","deprecated":true,"description":"[DEPRECATED V16] HUB-layer fallback URL.","maxLength":512,"minLength":0}},"required":["mode","pipelineName","sourceType"]},"PipelineTestRequest":{"type":"object","properties":{"testData":{"$ref":"#/components/schemas/JsonNode"}},"required":["testData"]},"ApiResponsePipelineTestResult":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PipelineTestResult"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PipelineTestResult":{"type":"object","properties":{"success":{"type":"boolean"},"input":{"$ref":"#/components/schemas/JsonNode"},"output":{"$ref":"#/components/schemas/JsonNode"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/StepResult"}},"errorMessage":{"type":"string"}}},"StepResult":{"type":"object","properties":{"stepIndex":{"type":"integer","format":"int32"},"operator":{"type":"string"},"outputSnapshot":{"$ref":"#/components/schemas/JsonNode"},"durationMs":{"type":"integer","format":"int64"}}},"ApiResponseObject":{"type":"object","properties":{"data":{},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ConsentSettingRequest":{"type":"object","description":"Request to create or update consent settings","properties":{"supplierUuid":{"type":"string","format":"uuid","description":"Supplier UUID"},"consentText":{"type":"string","description":"Consent description shown to users","minLength":1},"dataItemsJson":{"type":"string","description":"JSON array of data items","example":["temperature","location","battery"],"minLength":1},"purpose":{"type":"string","description":"Purpose of data collection"}},"required":["consentText","dataItemsJson","supplierUuid"]},"ApiResponseConsentSettingResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConsentSettingResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ConsentSettingResponse":{"type":"object","properties":{"settingId":{"type":"integer","format":"int64"},"supplierUuid":{"type":"string","format":"uuid"},"consentType":{"type":"string"},"consentText":{"type":"string"},"dataItemsJson":{"type":"string"},"purpose":{"type":"string"},"isActive":{"type":"boolean"},"version":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"AppCreateRequest":{"type":"object","properties":{"appUuid":{"type":"string","format":"uuid"},"appName":{"type":"string","minLength":1},"appType":{"type":"string","minLength":1},"description":{"type":"string"}},"required":["appName","appType","appUuid"]},"ApiResponseAppResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AppResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AppResponse":{"type":"object","properties":{"appUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"appName":{"type":"string"},"appType":{"type":"string"},"description":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"AppReleaseCreateRequest":{"type":"object","properties":{"appReleaseUuid":{"type":"string","format":"uuid"},"version":{"type":"string","minLength":1},"manifestJson":{"$ref":"#/components/schemas/JsonNode"},"signatureJson":{"$ref":"#/components/schemas/JsonNode"}},"required":["appReleaseUuid","manifestJson","version"]},"ApiResponseAppReleaseResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AppReleaseResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AppReleaseResponse":{"type":"object","properties":{"appReleaseUuid":{"type":"string","format":"uuid"},"appUuid":{"type":"string","format":"uuid"},"version":{"type":"string"},"manifestJson":{"$ref":"#/components/schemas/JsonNode"},"signatureJson":{"$ref":"#/components/schemas/JsonNode"},"createdAt":{"type":"string","format":"date-time"}}},"ApiKeyCreateRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1},"supplierUuid":{"type":"string","format":"uuid"},"scopes":{"type":"array","items":{"type":"string"}},"expiresInDays":{"type":"integer","format":"int32"},"rateLimit":{"type":"integer","format":"int32"}},"required":["name"]},"ApiKeyCreateResponse":{"type":"object","properties":{"apiKeyId":{"type":"integer","format":"int64"},"key":{"type":"string"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":"string"},"rateLimit":{"type":"integer","format":"int32"}}},"ApiResponseApiKeyCreateResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApiKeyCreateResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ActionDefinitionCreateRequest":{"type":"object","properties":{"actionId":{"type":"string","minLength":1},"supplierUuid":{"type":"string","format":"uuid"},"actionType":{"type":"string","minLength":1},"actionName":{"type":"string"},"configJson":{"type":"string","minLength":1},"resultSchemaJson":{"type":"string"}},"required":["actionId","actionType","configJson"]},"ActionDefinitionResponse":{"type":"object","properties":{"actionId":{"type":"string"},"supplierUuid":{"type":"string","format":"uuid"},"actionType":{"type":"string"},"actionName":{"type":"string"},"configJson":{"type":"string"},"resultSchemaJson":{"type":"string"},"createdAt":{"type":"string"}}},"ApiResponseActionDefinitionResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ActionDefinitionResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"CreateForcedUpdateJobRequest":{"type":"object","properties":{"targetVersion":{"type":"string"},"message":{"type":"string"}}},"ApiResponseHubJobResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HubJobResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubJobResponse":{"type":"object","properties":{"hubJobUuid":{"type":"string","format":"uuid"},"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"jobType":{"type":"string"},"jobState":{"type":"string"},"progress":{"type":"integer","format":"int32"},"message":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"CreateAgentReleaseRequest":{"type":"object","properties":{"version":{"type":"string","minLength":1,"pattern":"^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z.-]+)?(\\+[0-9A-Za-z.-]+)?$"},"channel":{"type":"string","minLength":1},"bundleUrl":{"type":"string","minLength":1},"sha256":{"type":"string","minLength":1,"pattern":"^[a-fA-F0-9]{64}$"},"sigUrl":{"type":"string"},"minVersion":{"type":"string"},"isActive":{"type":"boolean"}},"required":["bundleUrl","channel","sha256","version"]},"AgentReleaseResponse":{"type":"object","properties":{"agentReleaseUuid":{"type":"string","format":"uuid"},"version":{"type":"string"},"channel":{"type":"string"},"bundleUrl":{"type":"string"},"sha256":{"type":"string"},"sigUrl":{"type":"string"},"minVersion":{"type":"string"},"isActive":{"type":"boolean"},"createdByUserUuid":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"ApiResponseAgentReleaseResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AgentReleaseResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AcceptRequest":{"type":"object","properties":{"token":{"type":"string"}}},"AcceptResult":{"type":"object","properties":{"tenantUuid":{"type":"string","format":"uuid"},"personaUuid":{"type":"string","format":"uuid"},"role":{"type":"string"}}},"ApiResponseAcceptResult":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AcceptResult"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AuthorizeRequest":{"type":"object","properties":{"supplierUuid":{"type":"string","format":"uuid"}}},"DeviceCommandRequest":{"type":"object","properties":{"command":{"type":"string"},"payloadJson":{"type":"string"}},"required":["command"]},"ApiResponseDeviceCommandResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceCommandResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceCommandResponse":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}}},"DeviceUiInvokeRequest":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"endpointRef":{"type":"string","minLength":1},"method":{"type":"string","pattern":"GET|POST"},"path":{"type":"string","minLength":1},"body":{"type":"object","additionalProperties":{}},"query":{"type":"object","additionalProperties":{}}},"required":["endpointRef","hubUuid","path"]},"ConsentGrantRequest":{"type":"object","properties":{"supplierUuid":{"type":"string","format":"uuid"},"consentType":{"type":"string"}},"required":["consentType","supplierUuid"]},"ApiResponseConsentRecordResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConsentRecordResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ConsentRecordResponse":{"type":"object","properties":{"consentId":{"type":"integer","format":"int64"},"userUuid":{"type":"string","format":"uuid"},"supplierUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"consentType":{"type":"string"},"status":{"type":"string"},"grantedAt":{"type":"string","format":"date-time"},"withdrawnAt":{"type":"string","format":"date-time"},"retentionPeriodDays":{"type":"integer","format":"int32"},"consentTextVersion":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"UpdateBundleRequest":{"type":"object","properties":{"name":{"type":"string","maxLength":255,"minLength":0},"versionLabel":{"type":"string","maxLength":64,"minLength":0},"description":{"type":"string","maxLength":1000,"minLength":0},"thumb":{"type":"string","maxLength":500,"minLength":0},"agentChannel":{"type":"string","maxLength":64,"minLength":0},"metadata":{"type":"string"}}},"UpdatePersonaRoleRequest":{"type":"object","properties":{"role":{"type":"string","minLength":1,"pattern":"OWNER|ADMIN|MEMBER"}},"required":["role"]},"UpdateDeviceManualRequest":{"type":"object","properties":{"deviceManualName":{"type":"string","maxLength":255,"minLength":0},"deviceManualVersion":{"type":"string","maxLength":255,"minLength":0},"deviceManualLink":{"type":"string","maxLength":255,"minLength":0},"deviceManualLog":{"type":"string","maxLength":255,"minLength":0}}},"HubUpdateRequest":{"type":"object","description":"Tenant 측에서 hub 메타데이터를 수정 (현재는 hubIdentifier 만)","properties":{"hubIdentifier":{"type":"string","description":"사람이 읽는 식별자/별칭 (예: \"거실 허브\"). null 이면 변경 안 함, 빈 문자열이면 기존 값 삭제(null로 set).","example":"거실 허브","maxLength":128,"minLength":0}}},"ApiResponseHubDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HubDetailResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubDetailResponse":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"hubIdentifier":{"type":"string"},"hubType":{"type":"string"},"macAddress":{"type":"string"},"supplierUuid":{"type":"string","format":"uuid"},"bundleUuid":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"UpdateRequest":{"type":"object","properties":{"role":{"type":"string","enum":["PROVISIONING","SCANNING","DUAL","DISABLED"]},"supplierUuid":{"type":"string"}}},"AdapterView":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"adapterAddress":{"type":"string"},"adapterId":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["PROVISIONING","SCANNING","DUAL","DISABLED"]},"supplierUuid":{"type":"string","format":"uuid"},"powered":{"type":"boolean"},"discoverable":{"type":"boolean"},"pairable":{"type":"boolean"},"active":{"type":"boolean"},"lastSeenAt":{"type":"string","format":"date-time"}}},"ApiResponseAdapterView":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AdapterView"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"UpdateDeviceInstanceRequest":{"type":"object","properties":{"deviceCustomName":{"type":"string","maxLength":255,"minLength":0},"isActivated":{"type":"boolean"},"thumb":{"type":"string","maxLength":50,"minLength":0}}},"UpdateDeviceVersionRequest":{"type":"object","properties":{"deviceVersionCode":{"type":"string","maxLength":255,"minLength":0},"deviceVersionName":{"type":"string","maxLength":255,"minLength":0},"publishDatetime":{"type":"string","format":"date-time"}}},"UpdateDeviceUiRequest":{"type":"object","properties":{"deviceUiName":{"type":"string","maxLength":255,"minLength":0},"deviceUiVersion":{"type":"string","maxLength":255,"minLength":0},"deviceUiContent":{"type":"string"},"deviceUiLog":{"type":"string"}}},"UpdateDeviceProtocolRequest":{"type":"object","properties":{"deviceProtocolName":{"type":"string","maxLength":255,"minLength":0},"deviceProtocolVersion":{"type":"string","maxLength":255,"minLength":0},"deviceProtocolContent":{"type":"string"},"deviceProtocolLog":{"type":"string"}}},"UpdateDeviceRequest":{"type":"object","properties":{"deviceName":{"type":"string","maxLength":255,"minLength":0},"deviceModel":{"type":"string","maxLength":255,"minLength":0},"isPublic":{"type":"boolean"},"publishDatetime":{"type":"string","format":"date-time"},"deviceGroupUuid":{"type":"string","format":"uuid"},"registrationMode":{"type":"string","pattern":"PRE_REGISTERED|AUTO_ON_MATCH"},"activationCredit":{"type":"integer","format":"int32","minimum":0},"isHub":{"type":"boolean"},"bundleUuid":{"type":"string","format":"uuid"}}},"UpdateDeviceMatchIdentifierRequest":{"type":"object","properties":{"label":{"type":"string","maxLength":100,"minLength":0},"notes":{"type":"string","maxLength":500,"minLength":0}}},"ActionDefinitionUpdateRequest":{"type":"object","properties":{"actionType":{"type":"string"},"actionName":{"type":"string"},"configJson":{"type":"string"},"resultSchemaJson":{"type":"string"}}},"UpdateAgentReleaseRequest":{"type":"object","properties":{"isActive":{"type":"boolean"},"sigUrl":{"type":"string"},"minVersion":{"type":"string"}}},"ApiResponseScanConfigResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ScanConfigResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubDataRoute":{"type":"object","properties":{"pipelineUuid":{"type":"string","format":"uuid"},"directDeliveryUrl":{"type":"string","deprecated":true},"directDeliveryApiKey":{"type":"string","deprecated":true},"destinationAuthJson":{"type":"string"},"pipelineRulesJson":{"type":"string"},"signingSecretBase64":{"type":"string"},"fallbackDeliveryUrl":{"type":"string","deprecated":true},"mode":{"type":"string"}}},"IdentifierView":{"type":"object","properties":{"kind":{"type":"string"},"value":{"type":"string"},"label":{"type":"string"}}},"ProtocolView":{"type":"object","properties":{"protocolId":{"type":"integer","format":"int64"},"name":{"type":"string"},"version":{"type":"string"},"content":{"type":"string"}}},"ScanConfigResponse":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"devices":{"type":"array","items":{"$ref":"#/components/schemas/ScanTarget"}},"pipelines":{"type":"array","items":{"$ref":"#/components/schemas/TenantPipeline"}},"hubDataRoutes":{"type":"array","deprecated":true,"items":{"$ref":"#/components/schemas/HubDataRoute"}}}},"ScanTarget":{"type":"object","properties":{"deviceUuid":{"type":"string","format":"uuid"},"deviceModel":{"type":"string"},"deviceName":{"type":"string"},"registrationMode":{"type":"string"},"supplierUuid":{"type":"string","format":"uuid"},"identifiers":{"type":"array","items":{"$ref":"#/components/schemas/IdentifierView"}},"protocols":{"type":"array","items":{"$ref":"#/components/schemas/ProtocolView"}}}},"TenantPipeline":{"type":"object","properties":{"pipelineUuid":{"type":"string","format":"uuid"},"pipelineName":{"type":"string"},"mode":{"type":"string"},"rules":{"$ref":"#/components/schemas/JsonNode"},"endpoints":{"$ref":"#/components/schemas/JsonNode"},"pipelineSigningSecretBase64":{"type":"string"}}},"AgentReleaseLatestResponse":{"type":"object","properties":{"agentReleaseUuid":{"type":"string","format":"uuid"},"version":{"type":"string"},"channel":{"type":"string"},"bundleUrl":{"type":"string"},"sha256":{"type":"string"},"sigUrl":{"type":"string"},"minVersion":{"type":"string"}}},"ApiResponseAgentReleaseLatestResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AgentReleaseLatestResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListTenantTransferRequestResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TenantTransferRequestResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListTenantResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TenantResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListTenantMemberResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TenantMemberResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListBundleResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BundleResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"SseEmitter":{"type":"object","properties":{"timeout":{"type":"integer","format":"int64"}}},"ApiResponseListSimulationPreset":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SimulationPreset"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"SimulationPreset":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"sampleData":{"type":"object","additionalProperties":{}}}},"ApiResponseTenantPersonasResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TenantPersonasResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"TenantPersonasResponse":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/TenantMemberResponse"}},"invitations":{"type":"array","items":{"$ref":"#/components/schemas/TenantInvitationResponse"}}}},"ApiResponseListDeviceManualResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceManualResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListHubSummaryResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HubSummaryResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubSummaryResponse":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"hubIdentifier":{"type":"string"},"hubType":{"type":"string"},"macAddress":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiResponseListHubTelemetryResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HubTelemetryResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubTelemetryResponse":{"type":"object","properties":{"hubTelemetryId":{"type":"integer","format":"int64"},"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"receivedAt":{"type":"string","format":"date-time"},"payloadJson":{"$ref":"#/components/schemas/JsonNode"}}},"ApiResponseListSetupDelegationResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SetupDelegationResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListHubLogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HubLogResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubLogResponse":{"type":"object","properties":{"hubLogId":{"type":"integer","format":"int64"},"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"receivedAt":{"type":"string","format":"date-time"},"level":{"type":"string"},"message":{"type":"string"},"payloadJson":{"$ref":"#/components/schemas/JsonNode"}}},"ApiResponseListHubJobResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HubJobResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListInstalledAppView":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InstalledAppView"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"InstalledAppView":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"appUuid":{"type":"string","format":"uuid"},"installedVersion":{"type":"string"},"status":{"type":"string"},"lastReportedJson":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiResponseListHubInstalledAppResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HubInstalledAppResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubInstalledAppResponse":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"appUuid":{"type":"string","format":"uuid"},"appReleaseUuid":{"type":"string","format":"uuid"},"installedVersion":{"type":"string"},"installedAt":{"type":"string","format":"date-time"}}},"ApiResponseListAdapterView":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AdapterView"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListClaimCodeListItem":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClaimCodeListItem"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ClaimCodeListItem":{"type":"object","description":"Single claim code row in the tenant listing","properties":{"status":{"type":"string","description":"Status — PENDING / USED / EXPIRED / REVOKED"},"claimCode":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"claimedAt":{"type":"string","format":"date-time"},"revokedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"maxUses":{"type":"integer","format":"int32"},"usedCount":{"type":"integer","format":"int32"},"aliasHint":{"type":"string"},"description":{"type":"string"},"isOpen":{"type":"boolean"},"macHint":{"type":"string"},"claimedByHubUuid":{"type":"string","format":"uuid"},"supplierUuid":{"type":"string","format":"uuid"},"bundleUuid":{"type":"string","format":"uuid"}}},"Pageable":{"type":"object","properties":{"page":{"type":"integer","format":"int32","minimum":0},"size":{"type":"integer","format":"int32","minimum":1},"sort":{"type":"array","items":{"type":"string"}}}},"ApiResponsePageHubTelemetryResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageHubTelemetryResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageHubTelemetryResponse":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/HubTelemetryResponse"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"PageableObject":{"type":"object","properties":{"offset":{"type":"integer","format":"int64"},"sort":{"$ref":"#/components/schemas/SortObject"},"paged":{"type":"boolean"},"pageNumber":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"unpaged":{"type":"boolean"}}},"SortObject":{"type":"object","properties":{"empty":{"type":"boolean"},"sorted":{"type":"boolean"},"unsorted":{"type":"boolean"}}},"ApiResponsePageHubLogResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageHubLogResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageHubLogResponse":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/HubLogResponse"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"ApiResponsePageHubJobResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageHubJobResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageHubJobResponse":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/HubJobResponse"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"ApiResponseHubJobDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HubJobDetailResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubJobDetailResponse":{"type":"object","description":"Detailed hub job information including JSON payloads","properties":{"hubJobUuid":{"type":"string","format":"uuid","description":"Hub job UUID","example":"550e8400-e29b-41d4-a716-446655440000"},"jobType":{"type":"string","description":"Job type","example":"SELF_UPDATE"},"jobState":{"type":"string","description":"Job state","example":"RUNNING"},"progress":{"type":"integer","format":"int32","description":"Progress percentage (0-100)","example":50},"message":{"type":"string","description":"Status message","example":"downloading"},"desiredJson":{"$ref":"#/components/schemas/JsonNode","description":"Desired state JSON payload"},"resultJson":{"$ref":"#/components/schemas/JsonNode","description":"Result JSON payload"},"createdAt":{"type":"string","format":"date-time","description":"Created timestamp (ISO 8601)","example":"2026-02-26T10:00:00Z"},"updatedAt":{"type":"string","format":"date-time","description":"Last updated timestamp (ISO 8601)","example":"2026-02-26T10:30:00Z"}}},"ApiResponsePageHubJobEventResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageHubJobEventResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HubJobEventResponse":{"type":"object","description":"Hub job event information","properties":{"hubJobEventId":{"type":"integer","format":"int64","description":"Hub job event ID","example":123},"hubJobUuid":{"type":"string","format":"uuid","description":"Hub job UUID","example":"550e8400-e29b-41d4-a716-446655440001"},"jobState":{"type":"string","description":"Job state at event time","example":"RUNNING"},"progress":{"type":"integer","format":"int32","description":"Progress percentage (0-100)","example":50},"message":{"type":"string","description":"Event message","example":"Downloading update"},"at":{"type":"string","format":"date-time","description":"Event timestamp (ISO 8601)","example":"2026-02-26T10:00:00Z"}}},"PageHubJobEventResponse":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/HubJobEventResponse"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"ApiResponseListMapStringObject":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":{}}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseDownloadManifest":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DownloadManifest"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AssetRow":{"type":"object","properties":{"assetId":{"type":"integer","format":"int64"},"name":{"type":"string"},"size":{"type":"integer","format":"int64"},"os":{"type":"string"}}},"CategoryRelease":{"type":"object","properties":{"repo":{"type":"string"},"tag":{"type":"string"},"publishedAt":{"type":"string"},"assets":{"type":"array","items":{"$ref":"#/components/schemas/AssetRow"}}}},"DownloadManifest":{"type":"object","properties":{"installer":{"$ref":"#/components/schemas/CategoryRelease"},"hubOs":{"$ref":"#/components/schemas/CategoryRelease"},"hubAgent":{"$ref":"#/components/schemas/CategoryRelease"},"warning":{"type":"string"}}},"ApiResponseAssetUrl":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AssetUrl"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AssetUrl":{"type":"object","properties":{"url":{"type":"string"}}},"ApiResponseListDeviceInstanceResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceInstanceResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListDeviceVersionResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceVersionResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListDeviceUiResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceUiResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListDeviceProtocolResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceProtocolResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListDeviceCatalogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceCatalogResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListDeviceMatchIdentifierResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceMatchIdentifierResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListPipelineConfigResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PipelineConfigResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListDlqMessageResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DlqMessageResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DlqMessageResponse":{"type":"object","properties":{"dlqId":{"type":"integer","format":"int64"},"pipelineUuid":{"type":"string","format":"uuid"},"originalPayload":{"$ref":"#/components/schemas/JsonNode"},"errorMessage":{"type":"string"},"retryCount":{"type":"integer","format":"int32"},"firstFailureAt":{"type":"string","format":"date-time"},"lastRetryAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"status":{"type":"string"}}},"ApiResponseDashboardSummary":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DashboardSummary"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DashboardSummary":{"type":"object","properties":{"hubs":{"$ref":"#/components/schemas/HubsSummary"},"devices":{"$ref":"#/components/schemas/DevicesSummary"},"pipelines":{"$ref":"#/components/schemas/PipelinesSummary"},"dlq":{"$ref":"#/components/schemas/DlqSummary"},"events":{"$ref":"#/components/schemas/EventsSummary"},"delivery":{"$ref":"#/components/schemas/DeliverySummary"},"bleInRange":{"type":"integer","format":"int64"}}},"DeliverySummary":{"type":"object","properties":{"windowMinutes":{"type":"integer","format":"int32"},"success":{"type":"integer","format":"int64"},"failed":{"type":"integer","format":"int64"},"pending":{"type":"integer","format":"int64"},"attempted":{"type":"integer","format":"int64"},"successRate":{"type":"number","format":"double"}}},"DevicesSummary":{"type":"object","properties":{"total":{"type":"integer","format":"int64"},"active":{"type":"integer","format":"int64"}}},"DlqSummary":{"type":"object","properties":{"total":{"type":"integer","format":"int64"}}},"EventsSummary":{"type":"object","properties":{"windowMinutes":{"type":"integer","format":"int32"},"count":{"type":"integer","format":"int64"},"perMinute":{"type":"number","format":"double"}}},"HubsSummary":{"type":"object","properties":{"total":{"type":"integer","format":"int64"},"online":{"type":"integer","format":"int64"},"offline":{"type":"integer","format":"int64"}}},"PipelinesSummary":{"type":"object","properties":{"total":{"type":"integer","format":"int64"}}},"ApiResponseListConsentRecordResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ConsentRecordResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListBleEventResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BleEventResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BleEventResponse":{"type":"object","properties":{"bleEventId":{"type":"integer","format":"int64"},"tenantUuid":{"type":"string","format":"uuid"},"hubUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"receivedAt":{"type":"string","format":"date-time"},"rssi":{"type":"integer","format":"int32"},"rawBase64":{"type":"string"},"payloadJson":{"$ref":"#/components/schemas/JsonNode"},"parsedJson":{"$ref":"#/components/schemas/JsonNode"},"normalizedJson":{"$ref":"#/components/schemas/JsonNode"},"processedAt":{"type":"string","format":"date-time"},"processingStatus":{"type":"string"},"deliveryStatus":{"type":"string"}}},"ApiResponseBleEventResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BleEventResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListBleProcessingRunResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BleProcessingRunResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BleProcessingRunResponse":{"type":"object","properties":{"runId":{"type":"integer","format":"int64"},"bleEventId":{"type":"integer","format":"int64"},"tenantUuid":{"type":"string","format":"uuid"},"hubUuid":{"type":"string","format":"uuid"},"startedAt":{"type":"string","format":"date-time"},"finishedAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"errorMessage":{"type":"string"},"debugJson":{"$ref":"#/components/schemas/JsonNode"}}},"ApiResponsePageBleEventResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageBleEventResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageBleEventResponse":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/BleEventResponse"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"ApiResponseBleEventDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BleEventDetailResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BleEventDetailResponse":{"type":"object","description":"Detailed BLE event information","properties":{"bleEventId":{"type":"integer","format":"int64","description":"BLE event ID","example":123},"receivedAt":{"type":"string","format":"date-time","description":"Received timestamp (ISO 8601)","example":"2026-02-26T10:00:00Z"},"hubUuid":{"type":"string","format":"uuid","description":"Hub UUID","example":"550e8400-e29b-41d4-a716-446655440000"},"deviceInstanceId":{"type":"integer","format":"int64","description":"Device instance ID","example":123},"rssi":{"type":"integer","format":"int32","description":"RSSI value","example":-65},"processingStatus":{"type":"string","description":"Processing status","example":"PROCESSED"},"deliveryStatus":{"type":"string","description":"Delivery status","example":"DELIVERED"},"payloadJson":{"$ref":"#/components/schemas/JsonNode","description":"Payload JSON"},"rawBase64":{"type":"string","description":"Raw base64 data (only included if requested)"}}},"ApiResponseEntitlementResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EntitlementResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"EntitlementResponse":{"type":"object","properties":{"tier":{"type":"string"},"limits":{"type":"object","additionalProperties":{}},"validUntil":{"type":"string"},"active":{"type":"boolean"}}},"AuditLogResponse":{"type":"object","properties":{"auditId":{"type":"integer","format":"int64"},"tenantUuid":{"type":"string","format":"uuid"},"scope":{"type":"string"},"actorUserUuid":{"type":"string","format":"uuid"},"actorPersonaUuid":{"type":"string","format":"uuid"},"actorHubUuid":{"type":"string","format":"uuid"},"action":{"type":"string"},"objectType":{"type":"string"},"objectUuid":{"type":"string","format":"uuid"},"objectId":{"type":"integer","format":"int64"},"occurredAt":{"type":"string","format":"date-time"},"ip":{"type":"string"},"userAgent":{"type":"string"},"traceId":{"type":"string"},"requestJson":{"$ref":"#/components/schemas/JsonNode"},"diffJson":{"$ref":"#/components/schemas/JsonNode"},"resultJson":{"$ref":"#/components/schemas/JsonNode"}}},"PageAuditLogResponse":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogResponse"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"ApiResponseListAppResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AppResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListAppReleaseResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AppReleaseResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListApiKeyListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyListResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListAgentUpdatePolicyResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AgentUpdatePolicyResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListAgentReleaseResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AgentReleaseResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseListActionDefinitionResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ActionDefinitionResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"ApiResponseInvitationPreview":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvitationPreview"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"InvitationPreview":{"type":"object","properties":{"maskedEmail":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"tenantName":{"type":"string"},"inviterDisplay":{"type":"string"}}},"ApiResponsePageSupplierRegistrationEvent":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageSupplierRegistrationEvent"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageSupplierRegistrationEvent":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/SupplierRegistrationEvent"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"SupplierRegistrationEvent":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"eventType":{"type":"string","enum":["HUB_REGISTERED","DEVICE_REGISTERED"]},"supplierUuid":{"type":"string","format":"uuid"},"resourceUuid":{"type":"string","format":"uuid"},"payload":{"type":"string"},"status":{"type":"string","enum":["PENDING","SENT","FAILED","DEAD"]},"attemptCount":{"type":"integer","format":"int32"},"lastAttemptAt":{"type":"string","format":"date-time"},"nextAttemptAt":{"type":"string","format":"date-time"},"lastError":{"type":"string"},"sentAt":{"type":"string","format":"date-time"},"occurredAt":{"type":"string","format":"date-time"},"idempotencyKey":{"type":"string"}}},"ApiResponsePageSupplierPermissionCache":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageSupplierPermissionCache"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"PageSupplierPermissionCache":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/SupplierPermissionCache"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"SupplierPermissionCache":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"userUuid":{"type":"string","format":"uuid"},"supplierUuid":{"type":"string","format":"uuid"},"resourceType":{"type":"string","enum":["HUB","DEVICE"]},"resourceUuid":{"type":"string","format":"uuid"},"permissions":{"type":"string"},"fetchedAt":{"type":"string","format":"date-time"}}},"ApiResponsePageDeviceActivationEvent":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PageDeviceActivationEvent"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceActivationEvent":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"tenantUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"hubUuid":{"type":"string","format":"uuid"},"activationCredit":{"type":"integer","format":"int32"},"occurredAt":{"type":"string","format":"date-time"},"syncStatus":{"type":"string","enum":["PENDING","SYNCED","FAILED","REJECTED_BALANCE","BACKFILL_SKIPPED"]},"syncedAt":{"type":"string","format":"date-time"},"syncError":{"type":"string"},"lastAttemptAt":{"type":"string","format":"date-time"},"attemptCount":{"type":"integer","format":"int32"}}},"PageDeviceActivationEvent":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/DeviceActivationEvent"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"empty":{"type":"boolean"}}},"AcceptedTenantInvitation":{"type":"object","properties":{"tenantUuid":{"type":"string","format":"uuid"},"tenantName":{"type":"string"},"role":{"type":"string"},"acceptedAt":{"type":"string","format":"date-time"}}},"ApiResponseNotificationsResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/NotificationsResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"NotificationsResponse":{"type":"object","properties":{"acceptedInvitations":{"type":"array","items":{"$ref":"#/components/schemas/AcceptedTenantInvitation"}}}},"ApiResponseHealthStatus":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HealthStatus"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"HealthStatus":{"type":"object","properties":{"status":{"type":"string"},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"ApiResponseListSupplierLinkResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SupplierLinkResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"SupplierLinkResponse":{"type":"object","description":"Supplier OAuth link summary for the app","properties":{"id":{"type":"integer","format":"int64"},"supplierUuid":{"type":"string","format":"uuid"},"supplierUserId":{"type":"string"},"supplierUserLabel":{"type":"string"},"linkedAt":{"type":"string","format":"date-time"},"accessTokenExpiresAt":{"type":"string","format":"date-time"},"scopes":{"type":"string"}}},"ApiResponseListNotificationResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/NotificationResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"NotificationResponse":{"type":"object","properties":{"notificationId":{"type":"integer","format":"int64"},"userUuid":{"type":"string","format":"uuid"},"notificationType":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"dataJson":{"type":"string"},"isRead":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"ApiResponseListAppHubSummaryResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AppHubSummaryResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AppHubSummaryResponse":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"hubIdentifier":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiResponseAppHubDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AppHubDetailResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"AppHubDetailResponse":{"type":"object","properties":{"hubUuid":{"type":"string","format":"uuid"},"tenantUuid":{"type":"string","format":"uuid"},"deviceInstanceId":{"type":"integer","format":"int64"},"hubIdentifier":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ApiResponseListDeviceSummaryResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeviceSummaryResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceSummaryResponse":{"type":"object","properties":{"deviceInstanceId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionUuid":{"type":"string","format":"uuid"},"deviceCustomName":{"type":"string"},"deviceVersionCode":{"type":"string"},"isActivated":{"type":"boolean"},"tenantUuid":{"type":"string","format":"uuid"},"thumb":{"type":"string"}}},"ApiResponseDeviceDetailResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeviceDetailResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"DeviceDetailResponse":{"type":"object","properties":{"deviceInstanceId":{"type":"integer","format":"int64"},"deviceUuid":{"type":"string","format":"uuid"},"deviceVersionUuid":{"type":"string","format":"uuid"},"deviceCustomName":{"type":"string"},"deviceVersionCode":{"type":"string"},"isActivated":{"type":"boolean"},"tenantUuid":{"type":"string","format":"uuid"},"thumb":{"type":"string"},"paymentDueDate":{"type":"string","format":"date-time"}}},"ApiResponseListBundleCatalogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BundleCatalogResponse"}},"pagination":{"$ref":"#/components/schemas/PageInfo"}}},"BundleCatalogResponse":{"type":"object","description":"Bundle catalog entry — supplier 제품 설명 + 계정 연동 진입점","properties":{"bundleUuid":{"type":"string","format":"uuid"},"supplierUuid":{"type":"string","format":"uuid"},"name":{"type":"string"},"versionLabel":{"type":"string"},"description":{"type":"string"},"thumb":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"},"requiresSupplierLink":{"type":"boolean","description":"supplier가 OAuth 동의를 요구하는지 (supplier_oauth_config 등록 여부)"},"currentUserLinked":{"type":"boolean","description":"현재 사용자가 이 supplier에 active link를 가지는지"},"consentPreview":{"type":"string","description":"동의 미리보기 — link 안 한 사용자에게 보여줄 텍스트"},"supplierAuthorizeHint":{"type":"string","description":"지금 link 흐름을 시작할 URL. POST /app/supplier-link/authorize 와 동일 효과"}}},"ApiResponseBundleCatalogResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BundleCatalogResponse"},"pagination":{"$ref":"#/components/schemas/PageInfo"}}}},"responses":{"BadRequest":{"description":"Bad Request - Invalid input parameters","content":{"application/json":{"schema":{"properties":{"message":{"example":"Invalid request parameters"},"timestamp":{"format":"date-time"}}}}}},"Unauthorized":{"description":"Unauthorized - Authentication required","content":{"application/json":{"schema":{"properties":{"message":{"example":"Authentication required"},"timestamp":{"format":"date-time"}}}}}},"Forbidden":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"schema":{"properties":{"message":{"example":"Insufficient permissions"},"timestamp":{"format":"date-time"}}}}}},"NotFound":{"description":"Not Found - Resource not found","content":{"application/json":{"schema":{"properties":{"message":{"example":"Resource not found"},"timestamp":{"format":"date-time"}}}}}},"TooManyRequests":{"description":"Too Many Requests - Rate limit exceeded","content":{"application/json":{"schema":{"properties":{"message":{"example":"Rate limit exceeded for telemetry uploads"},"timestamp":{"format":"date-time"}}}}}},"InternalServerError":{"description":"Internal Server Error","content":{"application/json":{"schema":{"properties":{"message":{"example":"An internal error occurred"},"timestamp":{"format":"date-time"}}}}}}},"securitySchemes":{"Bearer-JWT":{"type":"http","description":"User JWT token for platform/tenant endpoints","scheme":"bearer","bearerFormat":"JWT"},"Bearer-Hub":{"type":"http","description":"Hub authentication token for /v1/** endpoints","scheme":"bearer","bearerFormat":"opaque"},"ApiKeyAuth":{"type":"apiKey","description":"API Key (starts with ls_). Issued from the web portal.","name":"X-API-Key","in":"header"}}}}