Skip to content
Black Friday30% off your first month. See prices →

Reference REST API AI

AI API

List available AI models, manage BYOK provider keys, launch AI-driven test runs, and read per-run token and credit usage over the REST API.

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",
  "max_iterations": 20,
  "default_max_iterations": 20,
  "max_iterations_overridden": false,
  "max_run_spend_micro": 5000000,
  "default_max_run_spend_micro": 5000000,
  "max_run_spend_overridden": false,
  "min_max_run_spend_micro": 500000,
  "max_max_run_spend_micro": 100000000
}

Amounts ending in _micro are in micro-dollars (1,000,000 = $1.00). max_iterations is the AI agent’s turns per step and max_run_spend_micro the AI spending limit per run, each your organization’s setting or, when you have not set one, the default.


Update AI Config

PUT /api/v1/ai/config

Auth: Bearer token required. Developer role or above.

Request body:

FieldTypeRequiredDescription
default_providerstringNoProvider: vibeview, anthropic, openai, google, openrouter
default_modelstringNoModel identifier (e.g. claude-4-sonnet). Append :byok for own-key models
max_iterationsinteger or nullNoAI agent turns per step, 1–30. null returns to the default
max_run_spend_microinteger or nullNoAI spending limit per run in micro-dollars, 500000–100000000 ($0.50–$100.00). null returns to the default ($5.00)

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. The list is fetched live from the OpenRouter API with your OpenRouter BYOK key; without one, the list is empty. 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:

FieldTypeRequiredDescription
providerstringYesanthropic, openai, google, or openrouter
api_keystringYesThe 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.


Draft Test Steps

Draft a test’s steps from a plain-language goal (the Describe tab of Create test).

POST /api/v1/ai/draft-steps

Auth: Bearer token required. Developer role or above. Limited to 10 requests a minute.

Request body:

FieldTypeRequiredDescription
app_idstringYesApp public ID; the app’s notes and the names of its test data are given to the model
goalstringYesWhat the test should check, 3-2000 characters
group_idsarrayNoSuite public IDs (of this app) whose notes are given to the model too
modelstringNoModel to use (defaults to org config)

Response:

{
  "name": "Save a destination",
  "steps": [
    { "text": "Search for Kyoto and open the first result" },
    { "text": "Tap Save" },
    { "text": "Verify 'Kyoto' is listed under Saved" }
  ],
  "model": "claude-4-sonnet",
  "who_pays": "usage_credit",
  "free_max_steps": null
}

who_pays is usage_credit, own_key or free (the Free plan’s free test paid for it). free_max_steps is the free test’s step limit (setups included) when the free test paid, otherwise null. Nothing is saved: create the test with POST /api/v1/tests/cases.

Errors:

  • 403 — drafting is refused; detail is { "message": "...", "remedy": "add_key" | "buy_credits" | "upgrade" | null }.
  • 404 — App or suite not found in your organization. 400 — a suite of another app.
  • 402 — usage credit ran out during the draft.
  • 429 — too many requests.
  • 502 — the AI model failed, or returned no usable steps (an unusable answer is still billed).

Who Pays for a Draft

GET /api/v1/ai/draft-steps/payer?app_id={app_id}

Auth: Bearer token required. Developer role or above.

Returns { "who_pays", "model", "model_name", "message", "remedy", "free_max_steps" }. who_pays is usage_credit, own_key, free or blocked; when blocked, message and remedy say why and how to fix it. free_max_steps is the free test’s step limit when the free test pays.


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. Developer role or above.

Request body:

FieldTypeRequiredDescription
recordingarrayYesArray of recorded action objects
app_namestringNoName of the app being tested
app_idstringNoApp public ID; the app’s notes are given to the model
contextstringNoAdditional context for the AI
modelstringNoModel 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,..."
    },
    {
      "text": "Verify 'Dashboard' is visible",
      "source_action_index": null,
      "screenshot": null
    }
  ],
  "assertions": []
}

Checks are written as inline Verify ... steps where they belong. A Verify step has no recorded actions, so its source_action_index is null. assertions is deprecated and always [].


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 and POST /api/v1/ai/suite/run keep working. For new integrations, use POST /api/v1/sessions/{session_id}/runs to run on a session you hold, or POST /api/v1/tests/runs to run on devices of their own.

POST /api/v1/ai/test/run

Auth: Bearer token required. Developer role or above.

Request body:

FieldTypeRequiredDescription
test_case_public_idstringNo*Public ID of the test case to execute
test_case_idintNo*Numeric ID of the test case (legacy alternative)
session_idstringYesActive session to run the test against
modelstringNoModel to use (defaults to org config)
providerstringNoProvider override
modestringNohybrid (Smart, default), ai (AI only), or replay (No AI)
fuzzy_matchbooleanNoDeprecated. Accepted and ignored. Replay matches elements by id or exact text only (see Element Matching)
build_idintNoThe AppBuild id to record the run against. The run does not install anything: it tests whatever is already on the session’s device, so start the session with the build you want to test. When omitted, the run is recorded against the build the session installed. 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.
group_public_idstringNoThe suite the run is started from. Its start state, notes (context) and screenshot thresholds apply; test data comes from the app. Omitted: the test’s suite when it is in exactly one; otherwise none. 404 for an unknown suite, 400 when the test is not in it. A test’s own start state (start_state) wins over the group’s; with no group and no setting a run starts from Clean app data.

*Provide either test_case_public_id or test_case_id.

Response:

{
  "run_id": 1,
  "run_public_id": "tr7abc123x",
  "status": "started",
  "message": "AI 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.

AI use (mode):

  • hybrid (Smart, default) — Replays recorded actions first, falls back to AI for any steps that fail during replay.
  • ai (AI only) — the AI agent runs every step; the agent interprets each step and interacts with the device.
  • replay (No AI) — Replay recorded actions only; no AI fallback. A test case with no recording is refused with 400 rather than run as AI.

Run Suite

Execute all test cases in a suite sequentially against a live session.

POST /api/v1/ai/suite/run

Auth: Bearer token required. Developer role or above.

Request body:

FieldTypeRequiredDescription
suite_public_idstringNo*Public ID of the suite to execute
suite_idintNo*Numeric suite ID (legacy alternative)
session_idstringYesActive session to run against
modelstringNoModel to use
providerstringNoProvider override; honored together with model
modestringNohybrid, ai, or replay
fuzzy_matchbooleanNoDeprecated. Accepted and ignored (see Element Matching)
build_idintNoThe AppBuild id to record each case’s run against. The suite tests what is already on the session’s device, so start the session with the build you want to test. The exception is a suite whose reset strategy is reinstall, which reinstalls this build before each case; on Roku, clear_data also deletes the channel and installs this build again before each case. On Roku, a suite started while the session’s channel is still installing waits for the install, and errors with the install’s reason if it fails. When omitted, runs are recorded against the build the session installed. Returns 400 if no app is attached to the suite, 404 if your organization has no such build, 403 if the build belongs to a different app. Both errors list the app’s newest builds.

*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. Developer role or above.

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.

Last updated 29 Oct 2026 Something wrong on this page? Tell us

Search the docs