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:
- url: http://{host}:8843 variables: host: { default: board.local } security:
- bearerAuth: [] paths: /board/info: get: summary: Discovery probe (unauthenticated) security: [] responses: "200": { description: OK, content: { application/json: { schema: { $ref: "#/components/schemas/BoardInfo" } } } }
/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]