board connect.yaml

Synced copy of vendor/harrishill/packages/services/BoardDeveloperBridgeService/assets/web/openapi.yaml — do not edit here; update the source spec and re-sync.

openapi: 3.1.0 info: title: Board Connect device API version: "1" description: > HTTP API hosted on a Board device (port 8843) for developer tooling — discovery, pairing, and managing installed apps (APKs) and web-app bundles. Consumed by the Board Connect web UI and board-connect-cli. Served unauthenticated at GET /openapi.yaml for discovery. See board-eng-docs/design/sdk-platform/board-connect-webapp-workflow.md. servers:

/openapi.yaml: get: summary: This spec (unauthenticated) security: [] responses: { "200": { description: OK } } /v1/pair: post: summary: Pair with a code shown on the device (manual / human flow) security: [] requestBody: required: true content: { application/json: { schema: { $ref: "#/components/schemas/PairRequest" } } } responses: "200": { description: Paired, content: { application/json: { schema: { $ref: "#/components/schemas/PairResponse" } } } } "401": { $ref: "#/components/responses/Error" } "409": { $ref: "#/components/responses/Error" } "429": { $ref: "#/components/responses/Error" } /v1/pair/request: post: summary: Tap-to-approve pairing (agent flow) — long-polls until the user taps Approve on the device security: [] requestBody: required: true content: { application/json: { schema: { $ref: "#/components/schemas/PairRequestStart" } } } responses: "200": { description: Approved, content: { application/json: { schema: { $ref: "#/components/schemas/PairResponse" } } } } "403": { $ref: "#/components/responses/Error", description: "pairing_disabled (the device setting is off)" } "408": { $ref: "#/components/responses/Error", description: "timed out awaiting approval; retry" } "429": { $ref: "#/components/responses/Error" } /v1/board/status: get: { summary: Readiness, responses: { "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/Status" } } } } } } /v1/board/capabilities: get: { summary: Protocol version + capability tags, responses: { "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/Capabilities" } } } } } } /v1/board/version: get: { summary: OS version, responses: { "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/Version" } } } } } } /v1/apps: get: summary: List dev-installed apps (APKs + web apps) responses: { "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/AppsResponse" } } } } } post: summary: Install an app (multipart). The bundle type (APK vs packed web app) is detected by content; the response reports packageName for an APK or appId for a web app. requestBody: required: true content: { multipart/form-data: { schema: { type: object, properties: { file: { type: string, format: binary } } } } } responses: "200": { description: Installed, content: { application/json: { schema: { $ref: "#/components/schemas/InstallResult" } } } } "400": { $ref: "#/components/responses/Error", description: "invalid_bundle / incomplete_transfer" } "422": { $ref: "#/components/responses/Error", description: "validation_failed / invalid_apk / ambiguous_bundle / unrecognized_bundle / missing_config / invalid_app_id / missing_entry / no_sdk" } "503": { $ref: "#/components/responses/Error", description: browser_unavailable } /v1/apps/cleanup: post: { summary: Uninstall all dev-managed apps, responses: { "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/CleanupResponse" } } } } } } /v1/apps/{id}/launch: post: summary: Launch an app by id (APK package name or web-app appId) parameters: [{ name: id, in: path, required: true, schema: { type: string } }] responses: { "204": { description: Launched }, "404": { $ref: "#/components/responses/Error" } } /v1/apps/{id}/stop: post: summary: Force-stop an APK by package. Web apps cannot be stopped individually (422 stop_unsupported). parameters: [{ name: id, in: path, required: true, schema: { type: string } }] responses: { "204": { description: Stopped }, "404": { $ref: "#/components/responses/Error" }, "422": { $ref: "#/components/responses/Error", description: stop_unsupported } } /v1/apps/{id}: delete: summary: Uninstall an app by id (APK package name or web-app appId) parameters: [{ name: id, in: path, required: true, schema: { type: string } }] responses: { "204": { description: Removed }, "404": { $ref: "#/components/responses/Error" } } /v1/apps/{id}/logs: get: summary: Dump recent logs for an app by id (APK package or web-app appId) parameters: - { name: id, in: path, required: true, schema: { type: string } } - { name: tag, in: query, required: false, schema: { type: string } } - { name: level, in: query, required: false, schema: { type: string, enum: [V, D, I, W, E, F] } } responses: { "200": { description: Log lines, content: { text/plain: { schema: { type: string } } } }, "404": { $ref: "#/components/responses/Error" } }

Deprecated split aliases — prefer the unified /v1/apps surface above. Kept for back-compat.

/v1/webapps: post: deprecated: true summary: "[deprecated: use POST /v1/apps] Install or update a web-app bundle (multipart zip)" requestBody: required: true content: { multipart/form-data: { schema: { type: object, properties: { file: { type: string, format: binary } } } } } responses: "200": { description: Installed, content: { application/json: { schema: { $ref: "#/components/schemas/InstallResult" } } } } "400": { $ref: "#/components/responses/Error", description: "invalid_bundle / incomplete_transfer" } "422": { $ref: "#/components/responses/Error", description: "missing_config / invalid_app_id / missing_entry / no_sdk" } "503": { $ref: "#/components/responses/Error", description: browser_unavailable } /v1/webapps/{appId}/launch: post: deprecated: true summary: "[deprecated: use POST /v1/apps/{id}/launch] Launch a web app by appId" parameters: [{ name: appId, in: path, required: true, schema: { type: string, format: uuid } }] responses: { "204": { description: Launched }, "404": { $ref: "#/components/responses/Error", description: webapp_not_found } } /v1/webapps/{appId}: delete: deprecated: true summary: "[deprecated: use DELETE /v1/apps/{id}] Remove a web app by appId" parameters: [{ name: appId, in: path, required: true, schema: { type: string, format: uuid } }] responses: { "204": { description: Removed }, "404": { $ref: "#/components/responses/Error", description: webapp_not_found } } /v1/webapps/{appId}/logs: get: deprecated: true summary: "[deprecated: use GET /v1/apps/{id}/logs] Dump recent logs for a web app (tag BoardWebApp:)" parameters: - { name: appId, in: path, required: true, schema: { type: string, format: uuid } } - { name: level, in: query, required: false, schema: { type: string, enum: [V, D, I, W, E, F] } } responses: { "200": { description: Log lines, content: { text/plain: { schema: { type: string } } } }, "404": { $ref: "#/components/responses/Error", description: webapp_not_found } } /v1/screenshot: get: summary: Capture a PNG screenshot (rate-limited 1/sec) responses: { "200": { description: PNG, content: { image/png: { schema: { type: string, format: binary } } } }, "429": { $ref: "#/components/responses/Error" } } /v1/media: post: summary: Push a media file to BoardMediaPlayer (multipart) requestBody: required: true content: { multipart/form-data: { schema: { type: object, properties: { file: { type: string, format: binary } } } } } responses: { "200": { description: Pushed, content: { application/json: { schema: { $ref: "#/components/schemas/PushMediaResult" } } } } } /v1/media/launch: post: { summary: Open BoardMediaPlayer, responses: { "204": { description: Launched } } } /v1/logs/dump: get: summary: Dump recent logs for a bdb-installed package parameters: - { name: package, in: query, required: true, schema: { type: string } } - { name: tag, in: query, required: false, schema: { type: string } } - { name: level, in: query, required: false, schema: { type: string, enum: [V, D, I, W, E, F] } } responses: { "200": { description: Log lines, content: { text/plain: { schema: { type: string } } } } } /v1/logs: get: summary: Stream logs over WebSocket (token via ?token= query param) security: [] responses: { "101": { description: Switching Protocols (WebSocket) } } /v1/paired-clients: get: { summary: List paired clients, responses: { "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/PairedClients" } } } } } } /v1/paired-clients/{id}: delete: summary: Revoke a paired client parameters: [{ name: id, in: path, required: true, schema: { type: integer, format: int64 } }] responses: { "204": { description: Revoked }, "400": { $ref: "#/components/responses/Error" } } components: securitySchemes: bearerAuth: { type: http, scheme: bearer } responses: Error: description: Error content: { application/json: { schema: { $ref: "#/components/schemas/Error" } } } schemas: BoardInfo: type: object properties: name: { type: string } serial: { type: string } model: { type: string } os: { type: string } apiVersions: { type: array, items: { type: string } } capabilities: { type: array, items: { type: string } } Status: type: object properties: ready: { type: boolean } Capabilities: type: object properties: protocolVersion: { type: integer } osVersion: { type: string } capabilities: { type: array, items: { type: string } } Version: type: object properties: version: { type: string } App: type: object properties: packageName: { type: string } label: { type: string } versionName: { type: string } versionCode: { type: integer, format: int64 } kind: { type: string, enum: [apk, webapp] } appId: { type: string, format: uuid, nullable: true } required: [packageName, kind] AppsResponse: type: object properties: apps: { type: array, items: { $ref: "#/components/schemas/App" } } InstallResult: type: object properties: packageName: { type: string } appId: { type: string, format: uuid, nullable: true } CleanupResponse: type: object properties: removed: { type: integer } PushMediaResult: type: object properties: name: { type: string } sizeBytes: { type: integer, format: int64 } PairRequest: type: object required: [code, label] properties: code: { type: string } label: { type: string } PairRequestStart: type: object required: [clientName] properties: clientName: { type: string } PairResponse: type: object properties: token: { type: string } id: { type: integer, format: int64 } PairedClient: type: object properties: id: { type: integer, format: int64 } label: { type: string } pairedAt: { type: integer, format: int64 } lastSeenAt: { type: integer, format: int64 } sourceIp: { type: string, nullable: true } PairedClients: type: object properties: clients: { type: array, items: { $ref: "#/components/schemas/PairedClient" } } Error: type: object properties: error: type: string description: > Machine-readable code. Web-app install: invalid_bundle, missing_config, invalid_app_id, missing_entry, no_sdk, webapp_not_found, webapp_install_failed. Others: package_not_installed, package_not_managed, validation_failed, invalid_apk, incomplete_transfer, wrong_code, expired, not_pairing, pairing_disabled, rate_limited, locked_out. message: { type: string } required: [error, message]