These endpoints list available AI models, manage your provider keys, launch AI-driven test runs, and report per-run usage. Authentication, error shapes and rate limits are covered in the REST API overview.
Get AI Config
Get the organization’s AI configuration (default provider and model).
GET /api/v1/ai/config
Auth: Bearer token required.
Response:
{
"default_provider": "vibeview",
"default_model": "claude-4-sonnet"
}
Update AI Config
PUT /api/v1/ai/config
Auth: Bearer token required. Developer role or above.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
default_provider | string | No | Provider: vibeview, anthropic, openai, google, openrouter |
default_model | string | No | Model identifier (e.g. claude-4-sonnet). Append :byok for own-key models |
List Models
List all available AI models, including built-in VibeView models and any models available via BYOK (Bring Your Own Key) API keys.
GET /api/v1/ai/models
Auth: Bearer token required.
Response:
[
{
"id": "claude-4-sonnet",
"name": "claude-4-sonnet (VibeView)",
"provider": "vibeview",
"builtin": true
},
{
"id": "gpt-4o:byok",
"name": "gpt-4o (own key)",
"provider": "openai",
"builtin": false
}
]
List OpenRouter Models
List vision-capable models available through OpenRouter. With an OpenRouter BYOK key configured, the list is fetched live from the OpenRouter API; without one, a curated recommended set is returned. All entries are own-key (:byok) models — runs are billed by OpenRouter directly, not by VibeView.
GET /api/v1/ai/models/openrouter
Auth: Bearer token required.
Response: Array of model objects, same shape as List Models (builtin is always false).
Add API Key (BYOK)
Store an API key for a provider to use your own models. Keys are encrypted at rest. If a key already exists for the provider, it is replaced.
POST /api/v1/ai/keys
Auth: Bearer token required. Developer role or above.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | anthropic, openai, google, or openrouter |
api_key | string | Yes | The API key |
Response:
{
"id": 1,
"provider": "openai",
"key_hint": "...abcd",
"created_at": "2025-01-15T10:30:00"
}
List API Keys
GET /api/v1/ai/keys
Auth: Bearer token required.
Response: Array of key objects (without the actual key values).
Delete API Key
DELETE /api/v1/ai/keys/{key_id}
Auth: Bearer token required. Developer role or above.
Get Usage
Get AI usage summary for the organization, broken down by total, BYOK, VibeView-hosted, and per-model.
GET /api/v1/ai/usage
Auth: Bearer token required.
Response:
{
"total": {
"input_tokens": 150000,
"output_tokens": 30000,
"cost_micro": 2500000,
"runs_count": 45
},
"byok": {
"input_tokens": 50000,
"output_tokens": 10000,
"cost_micro": 480000,
"runs_count": 15
},
"vibeview": {
"input_tokens": 100000,
"output_tokens": 20000,
"cost_micro": 2500000,
"runs_count": 30
},
"by_model": [
{
"model": "claude-4-sonnet",
"runs": 30,
"cost_micro": 2500000
}
]
}
Cost is reported in micro-credits (1,000,000 = $1.00). For the vibeview bucket it is the actual billed amount deducted from your usage credit. For the byok bucket it is an estimate computed from public list pricing — VibeView deducts nothing for BYOK runs, and your provider bills you directly, so the exact amount may differ. byok covers runs made with your own API key; vibeview covers VibeView-provided runs. The two are reported separately; the total bucket combines them, so treat its cost as “actual + estimate” rather than pure billed spend.
Generate Test from Recording
Analyze a recorded user session and generate natural-language test steps using AI.
POST /api/v1/ai/generate-test
Auth: Bearer token required.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
recording | array | Yes | Array of recorded action objects |
app_name | string | No | Name of the app being tested |
context | string | No | Additional context for the AI |
model | string | No | Model to use (defaults to org config) |
Response:
{
"name": "Login with valid credentials",
"steps": [
{
"text": "Tap on the email field and type 'user@example.com'",
"source_action_index": 0,
"screenshot": "data:image/png;base64,..."
}
],
"assertions": [
"Verify the dashboard screen is displayed"
]
}
Run AI Test
Launch an AI-powered test execution against a live device session. The test runs asynchronously; poll the test run endpoint for results.
POST /api/v1/ai/test/run
Auth: Bearer token required. Developer role or above.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
test_case_public_id | string | No* | Public ID of the test case to execute |
test_case_id | int | No* | Numeric ID of the test case (legacy alternative) |
session_id | string | Yes | Active session to run the test against |
model | string | No | Model to use (defaults to org config) |
provider | string | No | Provider override |
mode | string | No | hybrid (default), ai (pure AI), or replay (replay only) |
fuzzy_match | boolean | No | Per-run override of the case’s fuzzy-match default |
build_id | int | No | Specific AppBuild id to install before the run. Defaults to the test case app’s latest build. Returns 400 if the case has no app attached, 404 if the build doesn’t exist, 403 if it belongs to a different app or organization. |
*Provide either test_case_public_id or test_case_id.
Response:
{
"run_id": 1,
"run_public_id": "tr7abc123x",
"status": "started",
"message": "Hybrid test started with 5 steps",
"warnings": null
}
warnings is null or a list of human-readable strings (e.g. usage-threshold warnings) suitable for surfacing to the user.
Execution modes:
- hybrid (default) — Replays recorded actions first, falls back to AI for any steps that fail during replay.
- ai — Pure AI execution; the agent interprets each step and interacts with the device.
- replay — Replay recorded actions only; no AI fallback.
Run Suite
Execute all test cases in a suite sequentially against a live session.
POST /api/v1/ai/suite/run
Auth: Bearer token required.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
suite_public_id | string | No* | Public ID of the suite to execute |
suite_id | int | No* | Numeric suite ID (legacy alternative) |
session_id | string | Yes | Active session to run against |
model | string | No | Model to use |
provider | string | No | Provider override |
mode | string | No | hybrid, ai, or replay |
fuzzy_match | boolean | No | Per-run override of each case’s fuzzy-match default |
build_id | int | No | Specific AppBuild id to install before the first case. Defaults to the suite app’s latest build. Returns 400 if no app is attached to the suite, 404 if the build does not exist, 403 if the build belongs to a different app or organization. |
*Provide either suite_public_id or suite_id.
Response:
{
"suite_run_id": 1,
"suite_run_public_id": "sr9def456y",
"status": "pending"
}
Cancel Suite Run
Stop an in-flight suite run. The currently executing case is cancelled and no further cases are started.
POST /api/v1/ai/suite/run/{suite_run_id}/cancel
Auth: Bearer token required.
suite_run_id is the numeric suite_run_id returned by Run Suite.
Response:
{
"status": "cancellation_requested"
}
Errors:
400— Suite run is not active or already finished.