openapi: 3.1.0 info: title: sub2api-cn-relay-manager API version: 0.1.0 servers: - url: / paths: /healthz: get: responses: '200': description: ok /api/hosts: get: security: - bearerAuth: [] responses: '200': description: list of registered hosts content: application/json: schema: $ref: '#/components/schemas/ListHostsResponse' '401': $ref: '#/components/responses/Unauthorized' post: security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateHostRequest' responses: '200': description: host created content: application/json: schema: $ref: '#/components/schemas/HostInfo' '401': $ref: '#/components/responses/Unauthorized' /api/hosts/{hostID}: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/HostID' responses: '200': description: host detail content: application/json: schema: $ref: '#/components/schemas/HostInfo' '401': $ref: '#/components/responses/Unauthorized' '404': description: host not found delete: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/HostID' responses: '204': description: host deleted '401': $ref: '#/components/responses/Unauthorized' '404': description: host not found /api/hosts/{hostID}/probe: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/HostID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProbeHostRequest' responses: '200': description: refreshed host capability snapshot content: application/json: schema: $ref: '#/components/schemas/HostInfo' '401': $ref: '#/components/responses/Unauthorized' /api/packs/install: post: security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/InstallPackRequest' responses: '200': description: pack installed /api/packs: get: security: - bearerAuth: [] responses: '200': description: installed pack list content: application/json: schema: $ref: '#/components/schemas/ListPacksResponse' '401': $ref: '#/components/responses/Unauthorized' /api/packs/{packID}: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/PackID' responses: '200': description: pack detail content: application/json: schema: $ref: '#/components/schemas/PackInfo' '401': $ref: '#/components/responses/Unauthorized' '404': description: pack not found /api/packs/{packID}/providers: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/PackID' responses: '200': description: provider list within pack content: application/json: schema: $ref: '#/components/schemas/ListPackProvidersResponse' '401': $ref: '#/components/responses/Unauthorized' '404': description: pack not found /api/batch-import/runs: post: security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateBatchImportRunRequest' responses: '200': description: batch import run created content: application/json: schema: $ref: '#/components/schemas/BatchImportRunCreateResponse' '401': $ref: '#/components/responses/Unauthorized' get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/BatchImportRunStateQuery' - $ref: '#/components/parameters/BatchImportAccessModeQuery' - $ref: '#/components/parameters/BatchImportQuery' - $ref: '#/components/parameters/CursorQuery' - $ref: '#/components/parameters/LimitQuery' responses: '200': description: list batch import runs content: application/json: schema: $ref: '#/components/schemas/ListBatchImportRunsResponse' '401': $ref: '#/components/responses/Unauthorized' /api/batch-import/runs/{run_id}: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/RunID' responses: '200': description: batch import run detail content: application/json: schema: $ref: '#/components/schemas/BatchImportRunDetail' '401': $ref: '#/components/responses/Unauthorized' '404': description: run not found /api/batch-import/runs/{run_id}/items: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/RunID' - $ref: '#/components/parameters/BatchImportCurrentStageQuery' - $ref: '#/components/parameters/BatchImportConfirmationStatusQuery' - $ref: '#/components/parameters/BatchImportAccessStatusQuery' - $ref: '#/components/parameters/BatchImportHasWarningQuery' - $ref: '#/components/parameters/BatchImportProviderIDQuery' - $ref: '#/components/parameters/BatchImportMatchedAccountStateQuery' - $ref: '#/components/parameters/BatchImportAccountResolutionQuery' - $ref: '#/components/parameters/BatchImportQuery' - $ref: '#/components/parameters/CursorQuery' - $ref: '#/components/parameters/LimitQuery' responses: '200': description: batch import run items content: application/json: schema: $ref: '#/components/schemas/ListBatchImportRunItemsResponse' '401': $ref: '#/components/responses/Unauthorized' '404': description: run not found /api/batch-import/runs/{run_id}/items/{item_id}: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/RunID' - $ref: '#/components/parameters/ItemID' responses: '200': description: batch import run item detail content: application/json: schema: $ref: '#/components/schemas/BatchImportRunItemDetail' '401': $ref: '#/components/responses/Unauthorized' '404': description: run or item not found /api/import-batches/{batchID}: get: deprecated: true security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/BatchID' responses: '200': description: v1 legacy batch detail '401': $ref: '#/components/responses/Unauthorized' /api/import-batches/{batchID}/rollback: post: deprecated: true security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/BatchID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RollbackBatchRequest' responses: '200': description: batch rollback summary content: application/json: schema: $ref: '#/components/schemas/RollbackSummaryResponse' '401': $ref: '#/components/responses/Unauthorized' /api/providers/{providerID}/status: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' - $ref: '#/components/parameters/PackIDQuery' - $ref: '#/components/parameters/HostIDQuery' responses: '200': description: provider runtime status '401': $ref: '#/components/responses/Unauthorized' /api/providers/{providerID}/resources: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' - $ref: '#/components/parameters/PackIDQuery' - $ref: '#/components/parameters/HostIDQuery' responses: '200': description: provider managed resources snapshot '401': $ref: '#/components/responses/Unauthorized' /api/providers/{providerID}/access/status: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' - $ref: '#/components/parameters/PackIDQuery' - $ref: '#/components/parameters/HostIDQuery' responses: '200': description: provider access closure status '401': $ref: '#/components/responses/Unauthorized' /api/providers/{providerID}/import-batches: get: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' - $ref: '#/components/parameters/PackIDQuery' - $ref: '#/components/parameters/HostIDQuery' responses: '200': description: provider import batch history content: application/json: schema: $ref: '#/components/schemas/ListImportBatchesResponse' '401': $ref: '#/components/responses/Unauthorized' /api/providers/{providerID}/preview-import: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PreviewProviderRequest' responses: '200': description: preview summary /api/providers/{providerID}/import: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ImportProviderRequest' responses: '200': description: import summary /api/providers/{providerID}/rollback: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RollbackProviderRequest' responses: '200': description: rollback summary /api/providers/{providerID}/reconcile: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ReconcileProviderRequest' responses: '200': description: reconcile summary /api/providers/{providerID}/access/preview: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AccessPreviewRequest' responses: '200': description: access preview result content: application/json: schema: $ref: '#/components/schemas/AccessPreviewResponse' /api/providers/{providerID}/access/assign-subscriptions: post: security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/ProviderID' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/AssignAccessSubscriptionsRequest' responses: '200': description: access subscription assignment summary content: application/json: schema: $ref: '#/components/schemas/AssignAccessSubscriptionsResponse' components: securitySchemes: bearerAuth: type: http scheme: bearer parameters: HostID: name: hostID in: path required: true schema: type: string PackID: name: packID in: path required: true schema: type: string BatchID: name: batchID in: path required: true schema: type: integer format: int64 RunID: name: run_id in: path required: true schema: type: string ItemID: name: item_id in: path required: true schema: type: string ProviderID: name: providerID in: path required: true schema: type: string PackIDQuery: name: pack_id in: query required: false schema: type: string BatchImportRunStateQuery: name: state in: query required: false schema: type: string enum: [running, completed, completed_with_warnings, failed, cancelled] BatchImportAccessModeQuery: name: access_mode in: query required: false schema: type: string enum: [subscription, self_service] BatchImportQuery: name: q in: query required: false schema: type: string CursorQuery: name: cursor in: query required: false schema: type: string LimitQuery: name: limit in: query required: false schema: type: integer minimum: 1 BatchImportCurrentStageQuery: name: current_stage in: query required: false schema: type: string enum: [probe, provision, confirm, validate, done] BatchImportConfirmationStatusQuery: name: confirmation_status in: query required: false schema: type: string enum: [pending, confirmed, advisory, failed] BatchImportAccessStatusQuery: name: access_status in: query required: false schema: type: string enum: [unknown, active, degraded, broken] BatchImportHasWarningQuery: name: has_warning in: query required: false schema: type: boolean BatchImportProviderIDQuery: name: provider_id in: query required: false schema: type: string BatchImportMatchedAccountStateQuery: name: matched_account_state in: query required: false schema: type: string enum: [none, active, disabled, deprecated, broken] BatchImportAccountResolutionQuery: name: account_resolution in: query required: false schema: type: string enum: [created, reused, reactivated, replaced] responses: Unauthorized: description: missing or invalid admin token content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' schemas: ErrorResponse: type: object properties: error: type: object properties: code: type: string message: type: string CreateHostAuth: type: object required: [token] properties: type: type: string enum: [apikey, api_key, bearer] token: type: string CreateHostRequest: type: object required: [base_url, auth] properties: name: type: string base_url: type: string auth: $ref: '#/components/schemas/CreateHostAuth' ProbeHostRequest: type: object required: [auth] properties: auth: $ref: '#/components/schemas/CreateHostAuth' HostCapabilities: type: object properties: groups: type: boolean channels: type: boolean plans: type: boolean accounts: type: boolean account_test: type: boolean account_models: type: boolean subscriptions: type: boolean HostInfo: type: object properties: host_id: type: string base_url: type: string host_version: type: string auth_type: type: string status: type: string capabilities: $ref: '#/components/schemas/HostCapabilities' ListHostsResponse: type: object properties: hosts: type: array items: $ref: '#/components/schemas/HostInfo' PackInfo: type: object properties: pack_id: type: string version: type: string vendor: type: string target_host: type: string min_host_version: type: string max_host_version: type: string ListPacksResponse: type: object properties: packs: type: array items: $ref: '#/components/schemas/PackInfo' PackProviderInfo: type: object properties: provider_id: type: string display_name: type: string platform: type: string ListPackProvidersResponse: type: object properties: providers: type: array items: $ref: '#/components/schemas/PackProviderInfo' BatchImportEntry: type: object required: [base_url, api_key] properties: base_url: type: string api_key: type: string requested_models: type: array items: type: string CreateBatchImportRunRequestBase: type: object required: [host_id, mode, access_mode, entries] properties: host_id: type: string mode: type: string enum: [strict, partial] access_mode: type: string enum: [subscription, self_service] confirm_wait_timeout_sec: type: integer subscription_users: type: array items: type: string subscription_days: type: integer probe_api_key: type: string entries: type: array items: $ref: '#/components/schemas/BatchImportEntry' CreateBatchImportRunSubscriptionRequest: allOf: - $ref: '#/components/schemas/CreateBatchImportRunRequestBase' - type: object required: [subscription_users, subscription_days] properties: access_mode: type: string enum: [subscription] CreateBatchImportRunSelfServiceRequest: allOf: - $ref: '#/components/schemas/CreateBatchImportRunRequestBase' - type: object required: [probe_api_key] properties: access_mode: type: string enum: [self_service] CreateBatchImportRunRequest: oneOf: - $ref: '#/components/schemas/CreateBatchImportRunSubscriptionRequest' - $ref: '#/components/schemas/CreateBatchImportRunSelfServiceRequest' BatchImportRunSummary: type: object properties: run_id: type: string state: type: string enum: [running, completed, completed_with_warnings, failed, cancelled] mode: type: string enum: [strict, partial] access_mode: type: string enum: [subscription, self_service] total_items: type: integer completed_items: type: integer active_items: type: integer degraded_items: type: integer broken_items: type: integer warning_items: type: integer started_at: type: string format: date-time finished_at: type: string format: date-time nullable: true BatchImportRunCreateResponse: type: object properties: run_id: type: string state: type: string result_page: type: string total_items: type: integer active_items: type: integer degraded_items: type: integer broken_items: type: integer warning_items: type: integer ListBatchImportRunsResponse: type: object properties: runs: type: array items: $ref: '#/components/schemas/BatchImportRunSummary' next_cursor: type: string nullable: true BatchImportCapabilityTransportProfile: type: object properties: supports_openai_models: type: boolean supports_openai_chat_completions: type: boolean supports_openai_responses: type: boolean supports_anthropic_messages: type: boolean auth_style: type: string model_id_style: type: string known_advisories: type: array items: type: string BatchImportCapabilityModelProfile: type: object properties: raw_model_id: type: string normalized_model_id: type: string canonical_model_family: type: string supports_stream: type: string supports_tools: type: string supports_reasoning_fields: type: string smoke_chat_ok: type: boolean BatchImportCapabilityProfile: type: object properties: transport_profile: $ref: '#/components/schemas/BatchImportCapabilityTransportProfile' model_profiles: type: array items: $ref: '#/components/schemas/BatchImportCapabilityModelProfile' BatchImportRunItemSummary: type: object properties: item_id: type: string base_url: type: string provider_id: type: string api_key_fingerprint: type: string requested_models: type: array items: type: string canonical_model_families: type: array items: type: string resolved_smoke_model: type: string nullable: true current_stage: type: string enum: [probe, provision, confirm, validate, done] confirmation_status: type: string enum: [pending, confirmed, advisory, failed] access_status: type: string enum: [unknown, active, degraded, broken] matched_account_state: type: string enum: [none, active, disabled, deprecated, broken] account_resolution: type: string enum: [created, reused, reactivated, replaced] provision_reused: type: boolean retry_count: type: integer last_retry_at: type: string format: date-time nullable: true advisory_messages: type: array items: type: string last_error_stage: type: string nullable: true last_error: type: string nullable: true BatchImportRunItemEvent: type: object properties: event_id: type: string event_type: type: string stage: type: string attempt: type: integer message: type: string payload_json: type: string created_at: type: string format: date-time BatchImportRunItemDetail: allOf: - $ref: '#/components/schemas/BatchImportRunItemSummary' - type: object properties: raw_models: type: array items: type: string normalized_models: type: array items: type: string canonical_model_families: type: array items: type: string recommended_models: type: array items: type: string reused_from_provider_id: type: string nullable: true reused_from_account_id: type: integer format: int64 nullable: true channel_id: type: integer format: int64 nullable: true account_id: type: integer format: int64 nullable: true capability_profile: $ref: '#/components/schemas/BatchImportCapabilityProfile' events: type: array items: $ref: '#/components/schemas/BatchImportRunItemEvent' BatchImportRunDetail: type: object properties: run: $ref: '#/components/schemas/BatchImportRunSummary' recent_warnings: type: array items: type: string ListBatchImportRunItemsResponse: type: object properties: items: type: array items: $ref: '#/components/schemas/BatchImportRunItemSummary' next_cursor: type: string nullable: true ImportBatchInfo: type: object properties: batch_id: type: integer format: int64 batch_status: type: string access_status: type: string ListImportBatchesResponse: type: object properties: batches: type: array items: $ref: '#/components/schemas/ImportBatchInfo' InstallPackRequest: type: object required: [host_base_url, pack_path] properties: host_base_url: type: string host_api_key: type: string host_bearer_token: type: string pack_path: type: string PreviewProviderRequest: type: object required: [host_id, pack_path, keys] properties: host_id: type: string host_base_url: type: string description: legacy fallback; prefer host_id host_api_key: type: string description: legacy fallback; prefer registered host auth host_bearer_token: type: string description: legacy fallback; prefer registered host auth pack_path: type: string provider_id: type: string keys: type: array items: type: string mode: type: string ImportProviderRequest: type: object required: [host_id, pack_path, keys, access_api_key] properties: host_id: type: string host_base_url: type: string description: legacy fallback; prefer host_id host_api_key: type: string description: legacy fallback; prefer registered host auth host_bearer_token: type: string description: legacy fallback; prefer registered host auth pack_path: type: string provider_id: type: string keys: type: array items: type: string mode: type: string access_mode: type: string access_api_key: type: string subscription_users: type: array items: type: string subscription_days: type: integer RollbackProviderRequest: type: object required: [host_id, pack_path] properties: host_id: type: string host_base_url: type: string description: legacy fallback; prefer host_id host_api_key: type: string description: legacy fallback; prefer registered host auth host_bearer_token: type: string description: legacy fallback; prefer registered host auth pack_path: type: string provider_id: type: string RollbackBatchRequest: type: object required: [auth] properties: auth: $ref: '#/components/schemas/CreateHostAuth' RollbackSummaryResponse: type: object properties: batch_id: type: integer format: int64 deleted_accounts: type: integer deleted_plans: type: integer deleted_channels: type: integer deleted_groups: type: integer ReconcileProviderRequest: type: object required: [host_id, pack_path] properties: host_id: type: string host_base_url: type: string description: legacy fallback; prefer host_id host_api_key: type: string description: legacy fallback; prefer registered host auth host_bearer_token: type: string description: legacy fallback; prefer registered host auth pack_path: type: string provider_id: type: string access_api_key: type: string AccessPreviewRequest: type: object properties: provider_id: type: string pack_id: type: string host_id: type: string mode: type: string AccessPreviewResponse: type: object properties: provider_id: type: string mode: type: string available: type: boolean message: type: string AssignAccessSubscriptionsRequest: type: object required: [host_id, pack_path, access_api_key] properties: host_id: type: string pack_path: type: string provider_id: type: string host_base_url: type: string description: legacy fallback; prefer host_id host_api_key: type: string description: legacy fallback; prefer registered host auth host_bearer_token: type: string description: legacy fallback; prefer registered host auth access_api_key: type: string subscription_users: type: array items: type: string subscription_days: type: integer AssignAccessSubscriptionsResponse: type: object properties: provider_id: type: string assigned: type: integer access_status: type: string