# Create App Source: https://docs.docketqa.com/api-reference/endpoint/create-app POST /apps/create Register a new mobile app with its first build. The first build becomes the active build. Call [POST /apps/upload-url](/api-reference/endpoint/upload-build) first to obtain an `s3_key`. ## Request body Unique per platform. Max 255 chars. `"android"` or `"ios"`. Name for the first build (e.g. version or commit SHA). Max 255 chars. From [POST /apps/upload-url](/api-reference/endpoint/upload-build). Must belong to your company. Bytes uploaded. Used to preserve the file extension in the stored object name. ```json theme={null} { "name": "Acme Mobile", "platform": "android", "build_name": "v1.0.0", "s3_key": "files/2/4f8e1c2a-..._acme.apk", "file_size": 84213120, "original_filename": "acme.apk" } ``` ## Response Returns `{ message, app }` where `app` includes `id`, `name`, `platform`, `current_build` (with `id`, `name`, `arch`, `file`), `build_count`, `created_at`, `updated_at`. `arch` is auto-detected for Android builds (`"arm64"`, `"x86_64"`, `"universal"`) and is always `null` for iOS. ```json theme={null} { "message": "App created successfully", "app": { "id": 17, "name": "Acme Mobile", "platform": "android", "build_count": 1, "current_build": { "id": 42, "name": "v1.0.0", "arch": "arm64", "file": { "id": 312, "file_name": "Acme_Mobile_android_20260427_140312.apk", "file_size": 84213120 } } } } ``` ## Errors | Status | Cause | | ------ | --------------------------------------------------------------------- | | `400` | Missing/invalid field, bad extension, or 32-bit-only Android binary. | | `403` | No mobile concurrency on plan, or `s3_key` not owned by your company. | | `409` | An app with the same `name` already exists for this `platform`. | # Create Build Source: https://docs.docketqa.com/api-reference/endpoint/create-build POST /apps/{id}/builds Add a new build to an existing app. By default the new build is promoted to active; pass `set_as_current: false` to leave the active build unchanged. Call [POST /apps/upload-url](/api-reference/endpoint/upload-build) first to obtain an `s3_key`. ## Path parameters App ID. ## Request body The build name field is `name` on this endpoint. (When creating an app's *first* build via [POST /apps/create](/api-reference/endpoint/create-app) the equivalent field is `build_name`.) Unique within the app. Max 255 chars. From [POST /apps/upload-url](/api-reference/endpoint/upload-build). Must belong to your company. Bytes uploaded. Used to preserve the file extension. Default `true`. Set `false` to upload a build without affecting running tests; promote it later with [Set Active Build](/api-reference/endpoint/set-current-build). ```json theme={null} { "name": "v1.2.0", "s3_key": "files/2/9c2e7f5a-..._acme.apk", "file_size": 92012544, "original_filename": "acme.apk" } ``` ## Response Returns `{ message, build, app }`. `app.current_build` reflects the new active build when `set_as_current` is `true`. `build.arch` is `"arm64"` / `"x86_64"` / `"universal"` for Android (auto-detected from the binary) and `null` for iOS. ## Errors | Status | Cause | | ------ | --------------------------------------------------------------------- | | `400` | Missing/invalid field, bad extension, or 32-bit-only Android binary. | | `403` | No mobile concurrency on plan, or `s3_key` not owned by your company. | | `404` | App not found in your account. | | `409` | A build named `name` already exists for this app. | # Create Module Source: https://docs.docketqa.com/api-reference/endpoint/create-module POST /modules/create Create a reusable module that can be shared across multiple tests. A single module is reusable across every browser viewport, iOS device, and Android device. Modules support all step types including AI steps, assertions, API steps, recorded steps, and nested modules. ## Request body The name of the module. Must be between 1 and 128 characters and unique within your account. An ordered list of steps for the module. The position of this step in the sequence (starting from 1). Must be unique within the module. The step type. Available types: **AI steps:** * `"act"` — an AI-driven browser action (e.g. click, type, navigate). Action text must not be empty. * `"assert"` — an AI-driven assertion that verifies something on the page. **Module & orchestration:** * `"step_module"` — execute another module (nested). Requires `test_blueprint_module_id`. * `"trigger_run"` — trigger another test as a sub-run. Requires `trigger_run_config`. **API step:** * `"api"` — make an HTTP request. Requires `api_request`. **Recorded/low-level steps:** * `"key"` — press a keyboard key. * `"type"` — type text into the focused element. * `"mouse_move"` — move the mouse to coordinates. * `"left_click"` — left click at coordinates. * `"left_click_drag"` — click and drag from one point to another. * `"right_click"` — right click at coordinates. * `"double_click"` — double click at coordinates. * `"triple_click"` — triple click at coordinates. * `"scroll"` — scroll the page. * `"wait"` — wait for a duration. **Mobile-only:** * `"deeplink"` — open a deep link URL. Only executed when the module runs on an iOS or Android worker; ignored on browser workers. The legacy `"module"` type is not allowed. Use `"step_module"` for nested modules. A natural language instruction describing what the step should do. For recorded steps, this contains the coordinates or key data. For `api` steps, this can be left empty. Whether to enable vision (screenshot analysis) for this step. Defaults to `false`. The ID of the module to execute. **Required** when `type` is `"step_module"`. The HTTP request configuration. Required for steps with `type: "api"`. The full URL to send the request to. The HTTP method (e.g. `"GET"`, `"POST"`, `"PUT"`, `"DELETE"`). Key-value pairs for request headers. The request body (for POST, PUT, PATCH requests). Request timeout in seconds. Defaults to `60`. Number of retries on failure. Defaults to `1`. Delay between retries in seconds. Defaults to `2.5`. Whether to refresh the browser page after the API call. Defaults to `false`. Configuration for triggering another test. Required when `type` is `"trigger_run"`. The ID of the test blueprint to trigger as a sub-run. Number of screenshot images to capture for assertion steps. Defaults to `5`. Disable automatic self-healing for this step. Defaults to `false`. Number of clicks to perform for click-type steps. Defaults to `1`. Duration in seconds to hold before the action. Defaults to `0`. Duration in seconds to hold after the action. Defaults to `0`. The ID of the test suite this module belongs to. The folder path for organizing the module. Defaults to `"/"`. ### Example request body ```json theme={null} { "title": "Login Setup Module", "steps": [ { "step_number": 1, "type": "act", "action": "Navigate to the login page", "use_vision": false }, { "step_number": 2, "type": "api", "action": "", "api_request": { "url": "https://api.example.com/auth/token", "method": "POST", "headers": {}, "body": { "username": "testuser", "password": "testpass" }, "timeout": 60, "retries": 1, "backoff_seconds": 2.5, "should_refresh_page": false } }, { "step_number": 3, "type": "assert", "action": "Verify the auth token was returned", "use_vision": false } ] } ``` ## Response A confirmation message (e.g. `"Test blueprint created successfully"`). The created module object. The unique ID of the module. The module name. Always `"step_module"` for modules. The module status (e.g. `"active"`). Your company ID. The test suite ID, if set. The folder path of the module. The list of module steps with generated IDs. The unique step ID. Position of this step in the sequence. The step type (see [step types](/api-reference/introduction#step-types) for all values). The step instruction. Whether vision is enabled for this step. The referenced module ID (for `step_module` steps). The API request configuration (for `api` steps). The trigger run configuration (for `trigger_run` steps). Whether self-healing is disabled. Number of clicks for this step. Hold duration before the action. Hold duration after the action. Number of assertion images captured. IDs of files attached to this step. Number of tests using this module (always `0` for newly created modules). Tests referencing this module (empty for new modules). ISO 8601 timestamp of when the module was created. ISO 8601 timestamp of the last update. ### Example response ```json theme={null} { "message": "Test blueprint created successfully", "test_blueprint": { "id": 964, "title": "Login Setup Module", "type": "step_module", "status": "active", "company_id": 23, "test_blueprint_category_id": null, "folder_path": "/", "usage_count": 0, "test_blueprints_using_module": [], "steps": [ { "id": 23103, "step_number": 1, "type": "act", "action": "Navigate to the login page", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1 }, { "id": 23104, "step_number": 2, "type": "api", "action": "", "use_vision": false, "test_blueprint_module_id": null, "api_request": { "url": "https://api.example.com/auth/token", "method": "POST", "headers": {}, "body": { "username": "testuser", "password": "testpass" }, "timeout": 60, "retries": 1, "backoff_seconds": 2.5, "should_refresh_page": false }, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1 }, { "id": 23105, "step_number": 3, "type": "assert", "action": "Verify the auth token was returned", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1 } ], "created_at": "2025-12-13T18:58:45.895773+00:00", "updated_at": "2025-12-13T18:58:45.895781+00:00" } } ``` # Create Test Source: https://docs.docketqa.com/api-reference/endpoint/create-test POST /test_blueprint/create Create a new test blueprint with a title, starting URL, and a sequence of steps. ## Request body ### Required fields The name of the test. Must be between 1 and 128 characters and unique within your account. The blueprint type. Must be one of: * `"integration"` — a standard end-to-end test * `"module"` — an account/login module (requires `starting_url` and `credentials`) To create reusable modules, use the [Create Module](/api-reference/endpoint/create-module) endpoint instead. An ordered list of steps for the test to execute. Required for `integration` type. The position of this step in the sequence (starting from 1). Must be unique within the test. The step type. Available types: **AI steps:** * `"act"` — an AI-driven browser action (e.g. click, type, navigate). Action text must not be empty. * `"assert"` — an AI-driven assertion that verifies something on the page. **Module & orchestration:** * `"step_module"` — execute a reusable module. Requires `test_blueprint_module_id`. * `"trigger_run"` — trigger another test as a sub-run. Requires `trigger_run_config`. **API step:** * `"api"` — make an HTTP request. Requires `api_request`. **Recorded/low-level steps:** * `"key"` — press a keyboard key. * `"type"` — type text into the focused element. * `"mouse_move"` — move the mouse to coordinates. * `"left_click"` — left click at coordinates. * `"left_click_drag"` — click and drag from one point to another. * `"right_click"` — right click at coordinates. * `"double_click"` — double click at coordinates. * `"triple_click"` — triple click at coordinates. * `"scroll"` — scroll the page. * `"wait"` — wait for a duration. **Mobile-only:** * `"deeplink"` — open a deep link URL. Only supported when `device_type` is `"android"` or `"ios"`. A natural language instruction describing what the step should do. For recorded steps, this contains the coordinates or key data. For `api` steps, this can be left empty. Whether to enable vision (screenshot analysis) for this step. Defaults to `false`. The ID of the module to execute. **Required** when `type` is `"step_module"`. The HTTP request configuration. Required for steps with `type: "api"`. The full URL to send the request to. The HTTP method (e.g. `"GET"`, `"POST"`, `"PUT"`, `"DELETE"`). Key-value pairs for request headers. The request body (for POST, PUT, PATCH requests). Request timeout in seconds. Defaults to `60`. Number of retries on failure. Defaults to `1`. Delay between retries in seconds. Defaults to `2.5`. Whether to refresh the browser page after the API call. Defaults to `false`. Configuration for triggering another test. Required when `type` is `"trigger_run"`. The ID of the test blueprint to trigger as a sub-run. Array of file IDs to attach to this step. Files must be uploaded to the test blueprint first. Number of screenshot images to capture for assertion steps. Defaults to `5`. Disable automatic self-healing for this step. Defaults to `false`. Number of clicks to perform for click-type steps. Defaults to `1`. Duration in seconds to hold before the action. Defaults to `0`. Duration in seconds to hold after the action. Defaults to `0`. ### Optional fields The URL the browser navigates to before executing steps. Must be a valid URL starting with `http://` or `https://`. **Required** when `type` is `"module"`. A high-level description of what the test does. Used as additional context for the AI agent. The ID of the test suite this test belongs to. You can find this ID in the Docket dashboard URL when on the Test Suites tab. The folder path for organizing the test. Defaults to `"/"`. The device to run the test on. Must be one of: * `"browser"` — desktop browser (default) * `"android"` — Android device * `"ios"` — iOS device The specific device name to use for mobile testing (when `device_type` is `"android"` or `"ios"`). The ID of the mobile app to associate with this test. Used for Android and iOS testing. Browser zoom level. Must be between `0.75` and `2.0`. Defaults to `1.0`. Browser viewport width in pixels. Defaults to `1440`. Browser viewport height in pixels. Defaults to `900`. Number of automatic retries if the test fails. Must be between `0` and `3`. Defaults to `0`. Whether to reset the browser session on retry. Defaults to `true`. Typing speed in milliseconds per character. Must be between `1` and `1000`. Defaults to `null` (uses the default speed of 12ms). Whether to persist self-healed action caches so future runs use the healed selectors. Defaults to `true`. How to handle file downloads during the test. Must be one of: * `"save_only"` — save downloaded files without processing (default) * `"ingest_content"` — save and ingest file contents for the AI agent to use Variables that can be referenced in step actions using `{{variable_key}}` syntax. The variable name (used as the reference key in steps). The variable type: `"text"`, `"email"`, or `"random"`. The static value for `text` type variables. Configuration for `random` type variables. The ID of a module to run **before** the test steps begin. Useful for common setup tasks like authentication. The ID of a module to run **after** the test steps complete. Useful for cleanup tasks. The initial status of the test. Must be `"active"` or `"paused"`. Defaults to `"active"`. Login credentials for `module` (account) type blueprints. **Required** when `type` is `"module"`. The login username or email. The login password. Optional TOTP secret for two-factor authentication. ### Example: Basic integration test ```json theme={null} { "title": "Login Flow", "type": "integration", "test_blueprint_category_id": 12, "starting_url": "https://example.com/login", "steps": [ { "step_number": 1, "type": "act", "action": "Enter 'user@example.com' in the email field" }, { "step_number": 2, "type": "act", "action": "Enter 'password123' in the password field" }, { "step_number": 3, "type": "act", "action": "Click the 'Log In' button" }, { "step_number": 4, "type": "assert", "action": "Verify user is redirected to the dashboard page" } ] } ``` ### Example: Test with module, API step, and variables ```json theme={null} { "title": "Create Campaign with API Setup", "type": "integration", "starting_url": "https://app.example.com", "setup_module": 42, "num_retries": 1, "variables": [ { "key": "campaign_name", "type": "random", "randomConfig": { "prefix": "Test Campaign " } } ], "steps": [ { "step_number": 1, "type": "api", "action": "", "api_request": { "url": "https://api.example.com/campaigns", "method": "POST", "headers": { "Authorization": "Bearer {{token}}" }, "body": { "name": "{{campaign_name}}" }, "timeout": 30 } }, { "step_number": 2, "type": "act", "action": "Navigate to the campaigns list" }, { "step_number": 3, "type": "assert", "action": "Verify '{{campaign_name}}' appears in the campaign list" }, { "step_number": 4, "type": "step_module", "action": "Run cleanup module", "test_blueprint_module_id": 99 } ] } ``` ## Response A confirmation message (e.g. `"Test blueprint created successfully"`). The created test blueprint object. The unique ID of the test blueprint. Your company ID. The test title. The blueprint type (`"integration"` or `"module"`). The device type (`"browser"`, `"android"`, or `"ios"`). The starting URL for the test. The high-level description of the test. The test suite ID. The test status (`"active"` or `"paused"`). The browser zoom level. Browser viewport width. Browser viewport height. Number of automatic retries on failure. Whether self-healed caches are persisted. The file download handling mode. Variables defined for this test. The setup module ID, if set. The teardown module ID, if set. The folder path of the test. The list of test steps with their generated IDs. The ID of the user who created the test. ISO 8601 timestamp of when the test was created. ISO 8601 timestamp of when the test was last updated. ### Example response ```json theme={null} { "message": "Test blueprint created successfully", "test_blueprint": { "id": 181, "company_id": 2, "title": "Login Flow", "type": "integration", "device_type": "browser", "status": "active", "starting_url": "https://example.com/login", "starting_prompt": null, "test_blueprint_category_id": 12, "browser_zoom": 1.0, "viewport_width": 1440, "viewport_height": 900, "num_retries": 0, "persist_self_healed": true, "file_download_mode": "save_only", "variables": null, "setup_module": null, "teardown_module": null, "folder_path": "/", "created_by": 4, "created_at": "2025-07-03T01:45:55.486917+00:00", "updated_at": "2025-07-03T01:45:55.486923+00:00", "steps": [ { "id": 564, "step_number": 1, "test_blueprint_id": 181, "type": "act", "action": "Enter 'user@example.com' in the email field", "use_vision": false, "disable_self_healing": false, "click_count": 1 }, { "id": 565, "step_number": 2, "test_blueprint_id": 181, "type": "act", "action": "Enter 'password123' in the password field", "use_vision": false, "disable_self_healing": false, "click_count": 1 }, { "id": 566, "step_number": 3, "test_blueprint_id": 181, "type": "act", "action": "Click the 'Log In' button", "use_vision": false, "disable_self_healing": false, "click_count": 1 }, { "id": 567, "step_number": 4, "test_blueprint_id": 181, "type": "assert", "action": "Verify user is redirected to the dashboard page", "use_vision": false, "disable_self_healing": false, "click_count": 1 } ] } } ``` # Get Module Source: https://docs.docketqa.com/api-reference/endpoint/get-module GET /modules/{module_id} Retrieve a specific module by its ID, including all of its steps and usage information. The ID of the module to retrieve. ## Response The module object. The unique ID of the module. The module name. Always `"step_module"` for modules. The module status (e.g. `"active"`). Your company ID. The test suite ID, if set. The name of the test suite, if set. The folder path of the module. The list of steps in this module. The unique step ID. Position of this step in the sequence. The step type (see [step types](/api-reference/introduction#step-types) for all values). The step instruction. Whether vision is enabled for this step. The referenced module ID (for `step_module` steps). The API request configuration (for `api` steps). The trigger run configuration (for `trigger_run` steps). Whether self-healing is disabled. Number of clicks for this step. Hold duration before the action. Hold duration after the action. Number of assertion images captured. IDs of files attached to this step. List of test blueprints that reference this module. Number of tests using this module. ISO 8601 timestamp of when the module was created. ISO 8601 timestamp of the last update. ### Example response ```json theme={null} { "module": { "id": 962, "title": "Login Setup", "type": "step_module", "status": "active", "company_id": 23, "test_blueprint_category_id": null, "test_blueprint_category_name": null, "folder_path": "/", "usage_count": 0, "test_blueprints_using_module": [], "test_steps": [ { "id": 23101, "step_number": 1, "type": "act", "action": "Navigate to the login page", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1, "hold_start_duration": 0, "hold_end_duration": 0, "assert_images_count": 5, "attached_file_ids": null } ], "created_at": "2025-12-13T18:53:37.588258+00:00", "updated_at": "2025-12-13T18:53:37.588265+00:00" } } ``` # Get Test Run Source: https://docs.docketqa.com/api-reference/endpoint/get-test-run GET /test_run/{test_run_id} Retrieve the details and results of a specific test run. Use this to poll for results after [triggering a run](/api-reference/endpoint/run-test). The ID of the test run to retrieve (returned from the [Run Test](/api-reference/endpoint/run-test) endpoint). ## Response The test run object with full results. The unique ID of the test run. The current status: `"running"`, `"passed"`, or `"failed"`. The blueprint this run executed. The parent group run ID. A snapshot of the test blueprint at the time the run was triggered. Includes all blueprint fields (`title`, `type`, `device_type`, `starting_url`, `browser_zoom`, `viewport_width`, `viewport_height`, `variables`, etc.) and the full `steps` array with all step properties (see [step types](/api-reference/introduction#step-types)). Step-by-step results. `null` while the test is still running. The step number. The step instruction. Whether the step completed successfully. A description of what happened during this step. Time in seconds the step took to execute. Detailed browser actions taken during this step. A human-readable description of the action. The action type (e.g. `"click_element"`, `"input_text"`, `"extract_content"`, `"scroll_down"`, etc.). Pre-signed URL to a screenshot taken after this action. Pre-signed URL to a screenshot taken before this action (when available). The API response data (for `api` type steps). May include `api_response_url` with a pre-signed URL to the full response body. A pre-signed URL to stream the video recording of the test execution. A pre-signed URL to download the video recording as a `.webm` file. Results from retry attempts (when the test has `num_retries > 0` and the first attempt failed). Each attempt contains `results` and `test_video_url`. ISO 8601 timestamp of when the run started. ISO 8601 timestamp of the last status update. ### Example response ```json theme={null} { "test_run": { "id": 38, "status": "failed", "test_blueprint_id": 180, "test_group_run_id": 35, "blueprint_metadata": { "id": 180, "title": "Login Flow", "type": "integration", "device_type": "browser", "starting_url": "https://example.com/login", "browser_zoom": 1.0, "viewport_width": 1440, "viewport_height": 900, "variables": null, "steps": [ { "action": "Enter 'user@example.com' in the email field", "step_number": 1, "type": "act", "use_vision": false }, { "action": "Enter 'password123' in the password field", "step_number": 2, "type": "act", "use_vision": false } ] }, "results": [ { "step_number": 1, "task": "Enter 'user@example.com' in the email field", "is_successful": false, "result": "The agent could not complete the objective because no email field was present on the page.", "duration": 43, "actions": [ { "description": "Action: extract content with goal='Find any input fields'", "type": "extract_content", "screenshot_url": "https://..." } ] }, { "step_number": 2, "task": "Enter 'password123' in the password field", "is_successful": false, "result": "Step not completed", "duration": 0, "actions": [] } ], "test_video_url": "https://...", "test_video_download_url": "https://...", "additional_attempts": [], "created_at": "2025-07-03T01:38:03.032648+00:00", "updated_at": "2025-07-03T01:40:05.043914+00:00" } } ``` After triggering a run, use the `test_runs[].id` value to poll this endpoint until the status changes from `"running"` to `"passed"` or `"failed"`. # List Apps Source: https://docs.docketqa.com/api-reference/endpoint/list-apps GET /apps/list List every mobile app in your company, each with its current active build inlined. ## Query parameters `"android"` or `"ios"`. Omit for both. ## Response Returns `{ apps }`, ordered by `created_at` descending. Each app has `id`, `name`, `platform`, `build_count`, `current_build` (or `null`), `created_at`, `updated_at`. ```json theme={null} { "apps": [ { "id": 17, "name": "Acme Mobile", "platform": "android", "build_count": 3, "current_build": { "id": 51, "name": "v1.2.0", "arch": "arm64", "file": { "file_name": "Acme_Mobile_android_20260427_180501.apk", "file_size": 92012544 } } } ] } ``` *** ## Get a single app ```http theme={null} GET /apps/{id} ``` Same shape as a list entry plus an inline `builds` array containing **every** build for the app — useful when you need the full version history. ```bash theme={null} curl https://api.docketqa.com/apps/17 -H "X-API-KEY: your-api-key" ``` # List Modules Source: https://docs.docketqa.com/api-reference/endpoint/list-modules GET /modules/list Retrieve modules in your account, with optional filtering and step inclusion. ## Query parameters Comma-separated list of module IDs to fetch. Omit to retrieve all modules. Whether to include the full step details (flattened, with nested modules expanded) for each module. Defaults to `false`. When `with_steps=true`, scopes each step's internal cache to a specific execution config. Typically you don't construct this yourself — the runtime resolves it for you when a run is triggered. Filter by test suite ID. Pass `"none"` to get modules with no suite. Filter by folder path. Defaults to `"/"` (root folder). If `true`, return modules from all folders. Defaults to `false`. Search modules by title (case-insensitive partial match). Page number for pagination (1-indexed). Use with `per_page`. Number of results per page. Enables pagination when set. Offset for pagination. Use with `limit` as an alternative to `page`/`per_page`. Maximum number of results. Use with `offset`. ### Example requests Fetch all modules without steps: ```bash theme={null} GET /modules/list ``` Fetch specific modules with steps: ```bash theme={null} GET /modules/list?ids=962,964&with_steps=true ``` ## Response An array of module objects. The unique ID of the module. The module name. Always `"step_module"` for modules. The module status (e.g. `"active"`). Number of steps in the module. Your company ID. The test suite ID, if set. The name of the test suite, if set. The folder path of the module. The steps in the module. Only included when `with_steps=true`. When included, nested `step_module` steps are flattened into their individual steps. The unique step ID. Position of this step in the sequence. The step type (see [step types](/api-reference/introduction#step-types) for all values). The step instruction. Whether vision is enabled for this step. The referenced module ID (for `step_module` steps). The API request configuration (for `api` steps). The trigger run configuration (for `trigger_run` steps). Whether self-healing is disabled. Number of clicks for this step. Number of tests using this module. ISO 8601 timestamp of when the module was created. ISO 8601 timestamp of the last update. Pagination metadata. Only included when using `page`/`per_page` or `offset`/`limit` parameters. The current page number. Results per page. Total number of matching results. Total number of pages. List of subfolder paths within the current folder. Not included when using `search`. ### Example response ```json theme={null} { "modules": [ { "id": 962, "title": "Login Setup", "type": "step_module", "status": "active", "step_count": 1, "company_id": 23, "test_blueprint_category_id": null, "folder_path": "/", "usage_count": 0, "test_steps": [ { "id": 23101, "step_number": 1, "type": "act", "action": "Navigate to the login page", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1 } ], "created_at": "2025-12-13T18:53:37.588258+00:00", "updated_at": "2025-12-13T18:53:37.588265+00:00" }, { "id": 964, "title": "Auth Token Module", "type": "step_module", "status": "active", "step_count": 3, "company_id": 23, "test_blueprint_category_id": null, "folder_path": "/", "usage_count": 0, "test_steps": [ { "id": 23103, "step_number": 1, "type": "act", "action": "First AI step instructions", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "disable_self_healing": false, "click_count": 1 }, { "id": 23104, "step_number": 2, "type": "api", "action": "", "use_vision": false, "test_blueprint_module_id": null, "api_request": { "url": "https://api.example.com/auth", "method": "POST", "timeout": 60, "retries": 1 }, "disable_self_healing": false, "click_count": 1 }, { "id": 23105, "step_number": 3, "type": "assert", "action": "Verify auth succeeded", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "disable_self_healing": false, "click_count": 1 } ], "created_at": "2025-12-13T18:58:45.895773+00:00", "updated_at": "2025-12-13T18:58:45.895781+00:00" } ], "subfolders": ["/Auth Modules"] } ``` # List Tests Source: https://docs.docketqa.com/api-reference/endpoint/list-tests GET /test_blueprint/list Retrieve all test blueprints in your account with their last run information. ## Query parameters Filter by blueprint type. Must be one of: `"integration"`, `"module"`, `"step_module"`. Filter by test suite ID. Pass `"none"` to get tests with no suite. Filter by folder path. Defaults to `"/"` (root folder). If `true`, return tests from all folders. Defaults to `false`. Search tests by title (case-insensitive partial match). If `true`, include `used_by_integration_count` for module-type blueprints. Defaults to `false`. Page number for pagination (1-indexed). Use with `per_page`. Number of results per page. Enables pagination when set. Offset for pagination. Use with `limit` as an alternative to `page`/`per_page`. Maximum number of results. Use with `offset`. ## Response An array of test blueprint objects. The unique ID of the test blueprint. The test name. The blueprint type (`"integration"`, `"module"`, or `"step_module"`). The test status: `"active"` or `"paused"`. The device type (`"browser"`, `"android"`, or `"ios"`). The device name, if set. The starting URL for the test. The high-level description, if set. The number of steps in the test. The test suite this test belongs to. The name of the test suite. ISO 8601 timestamp of the most recent run, or `null`. The result of the most recent run (`"passed"`, `"failed"`, `"running"`), or `null`. Your company ID. The ID of the user who created the test. The browser zoom level. Browser viewport width in pixels. Browser viewport height in pixels. Number of automatic retries on failure. Whether the browser resets on retry. Typing speed in milliseconds per character, or `null` for default. Whether self-healed caches are persisted. The file download handling mode (`"save_only"` or `"ingest_content"`). Files attached to this test. Variables defined for this test. The setup module ID, if set. The teardown module ID, if set. The folder path of the test. ISO 8601 timestamp of when the test was created. ISO 8601 timestamp of the last update. Number of integration tests using this module. Only present when `include_usage_count=true` and `type` is `module`. Pagination metadata. Only included when using `page`/`per_page` or `offset`/`limit` parameters. The current page number. Results per page. Total number of matching results. Total number of pages. List of subfolder paths within the current folder. Not included when using `search` or `include_all_folders`. ### Example response ```json theme={null} { "test_blueprints": [ { "id": 446, "title": "Randomized Campaign Creation", "type": "integration", "status": "active", "device_type": "browser", "device_name": null, "starting_url": "https://app.example.com/", "starting_prompt": null, "step_count": 38, "test_blueprint_category_id": 26, "test_blueprint_category_name": "Campaigns", "last_run": "2025-10-10T21:05:19.847072+00:00", "last_status": "failed", "company_id": 3, "created_by": 5, "browser_zoom": 1.0, "viewport_width": 1440, "viewport_height": 900, "num_retries": 0, "reset_browser_on_retry": true, "typing_speed": null, "persist_self_healed": true, "file_download_mode": "save_only", "files": [], "variables": [], "setup_module": null, "teardown_module": null, "folder_path": "/", "created_at": "2025-10-07T00:53:44.522824+00:00", "updated_at": "2025-10-07T00:54:00.587872+00:00" } ], "subfolders": ["/E2E Tests", "/Smoke Tests"] } ``` # Run Test Source: https://docs.docketqa.com/api-reference/endpoint/run-test POST /test_group_run/trigger_run Trigger a test run for one or more test blueprints. Each test runs in its own remote screen session (browser or mobile device). An array of test blueprint IDs to run. You can trigger multiple tests in a single request. ### Example request body ```json theme={null} { "test_blueprint_ids": [181] } ``` A confirmation message (e.g. `"Test group run triggered successfully"`). The created test group run object. The unique ID of the test group run. Your company ID. Auto-generated name for the run (e.g. `"Manual Run 2025-07-03 01:38:03"`). The current status of the group run (e.g. `"running"`). Array of individual test run objects, one per blueprint ID. The unique ID of the individual test run. Use this with the [Get Test Run](/api-reference/endpoint/get-test-run) endpoint to poll for results. The current status of this test run (e.g. `"running"`, `"passed"`, `"failed"`). The blueprint ID this run is executing. The parent group run ID. A snapshot of the test blueprint at the time the run was triggered. Step-by-step results. `null` while the test is still running. ISO 8601 timestamp of when the run was triggered. ISO 8601 timestamp of the last status update. ### Example response ```json theme={null} { "message": "Test group run triggered successfully", "test_group_run": { "company_id": 2, "created_at": "2025-07-03T01:38:03.020496+00:00", "id": 35, "name": "Manual Run 2025-07-03 01:38:03", "status": "running", "test_runs": [ { "blueprint_metadata": { ... }, "created_at": "2025-07-03T01:38:03.032648+00:00", "id": 38, "is_login_test_run": false, "results": null, "status": "running", "test_blueprint_id": 180, "test_group_run_id": 35, "test_video_s3_key": null, "updated_at": "2025-07-03T01:38:03.032653+00:00" } ], "updated_at": "2025-07-03T01:38:03.020501+00:00" } } ``` After triggering a run, use the `test_runs[].id` value to poll the [Get Test Run](/api-reference/endpoint/get-test-run) endpoint until the status changes from `"running"` to `"passed"` or `"failed"`. # Set Active Build Source: https://docs.docketqa.com/api-reference/endpoint/set-current-build PUT /apps/{id}/builds/{build_id}/set-current Promote an existing build to be the app's active build. ## Path parameters App ID. The build to promote. Must belong to the app. No request body. ```bash theme={null} curl -X PUT https://api.docketqa.com/apps/17/builds/47/set-current \ -H "X-API-KEY: your-api-key" ``` Returns `{ message, app }` with `app.current_build` set to the promoted build. `404` if the app or build is not in your account. # Update Module Source: https://docs.docketqa.com/api-reference/endpoint/update-module PUT /modules/{module_id} Update an existing module's title, browser settings, and steps. When steps are provided, all existing steps are replaced with the new set. The ID of the module to update. ## Request body All fields are optional. Only provided fields will be updated. The updated module name. Must be between 1 and 128 characters and unique within your account. The new set of steps for the module. **Replaces all existing steps.** The position of this step in the sequence (starting from 1). Must be unique within the module. The step type. Available types: **AI steps:** * `"act"` — an AI-driven browser action (e.g. click, type, navigate). Action text must not be empty. * `"assert"` — an AI-driven assertion that verifies something on the page. **Module & orchestration:** * `"step_module"` — execute another module (nested). Requires `test_blueprint_module_id`. * `"trigger_run"` — trigger another test as a sub-run. Requires `trigger_run_config`. **API step:** * `"api"` — make an HTTP request. Requires `api_request`. **Recorded/low-level steps:** * `"key"` — press a keyboard key. * `"type"` — type text into the focused element. * `"mouse_move"` — move the mouse to coordinates. * `"left_click"` — left click at coordinates. * `"left_click_drag"` — click and drag from one point to another. * `"right_click"` — right click at coordinates. * `"double_click"` — double click at coordinates. * `"triple_click"` — triple click at coordinates. * `"scroll"` — scroll the page. * `"wait"` — wait for a duration. **Mobile-only:** * `"deeplink"` — open a deep link URL. Only executed when the module runs on an iOS or Android worker; ignored on browser workers. The legacy `"module"` type is not allowed. Use `"step_module"` for nested modules. A natural language instruction describing what the step should do. For recorded steps, this contains the coordinates or key data. For `api` steps, this can be left empty. Whether to enable vision (screenshot analysis) for this step. Defaults to `false`. The ID of the module to execute. **Required** when `type` is `"step_module"`. The HTTP request configuration. Required for steps with `type: "api"`. The full URL to send the request to. The HTTP method (e.g. `"GET"`, `"POST"`, `"PUT"`, `"DELETE"`). Key-value pairs for request headers. The request body (for POST, PUT, PATCH requests). Request timeout in seconds. Defaults to `60`. Number of retries on failure. Defaults to `1`. Delay between retries in seconds. Defaults to `2.5`. Whether to refresh the browser page after the API call. Defaults to `false`. Configuration for triggering another test. Required when `type` is `"trigger_run"`. The ID of the test blueprint to trigger as a sub-run. Number of screenshot images to capture for assertion steps. Defaults to `5`. Disable automatic self-healing for this step. Defaults to `false`. Number of clicks to perform for click-type steps. Defaults to `1`. Duration in seconds to hold before the action. Defaults to `0`. Duration in seconds to hold after the action. Defaults to `0`. The ID of the test suite this module belongs to. The folder path for organizing the module. ### Example request body ```json theme={null} { "title": "Updated Login Module", "steps": [ { "step_number": 1, "type": "act", "action": "Navigate to the updated login page", "use_vision": false }, { "step_number": 2, "type": "step_module", "action": "Run nested auth module", "test_blueprint_module_id": 50 } ] } ``` ## Response A confirmation message (e.g. `"Module updated successfully"`). The updated module object. The unique ID of the module. The updated module name. Always `"step_module"` for modules. The module status. Your company ID. The test suite ID, if set. The name of the test suite, if set. The folder path of the module. The updated list of steps. The unique step ID. Position of this step in the sequence. The step type (see [step types](/api-reference/introduction#step-types) for all values). The step instruction. Whether vision is enabled for this step. The referenced module ID (for `step_module` steps). The API request configuration (for `api` steps). The trigger run configuration (for `trigger_run` steps). Whether self-healing is disabled. Number of clicks for this step. Hold duration before the action. Hold duration after the action. Number of assertion images captured. IDs of files attached to this step. Tests referencing this module. Number of tests using this module. ISO 8601 timestamp of when the module was created. ISO 8601 timestamp of the last update. ### Example response ```json theme={null} { "message": "Module updated successfully", "module": { "id": 963, "title": "Updated Login Module", "type": "step_module", "status": "active", "company_id": 23, "test_blueprint_category_id": null, "folder_path": "/", "usage_count": 0, "test_blueprints_using_module": [], "test_steps": [ { "id": 23108, "step_number": 1, "type": "act", "action": "Navigate to the updated login page", "use_vision": false, "test_blueprint_module_id": null, "api_request": null, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1 }, { "id": 23109, "step_number": 2, "type": "step_module", "action": "Run nested auth module", "use_vision": false, "test_blueprint_module_id": 50, "api_request": null, "trigger_run_config": null, "disable_self_healing": false, "click_count": 1 } ], "created_at": "2025-12-13T18:56:48.692214+00:00", "updated_at": "2025-12-13T20:00:51.903151+00:00" } } ``` Updating a module replaces **all** existing steps with the steps provided in the request body. Make sure to include all steps you want to keep. # Upload a Build Source: https://docs.docketqa.com/api-reference/endpoint/upload-build POST /apps/upload-url Get a 15-minute presigned URL for uploading a build binary. `PUT` the binary to `s3_presigned_url`, then pass the returned `s3_key` to [Create App](/api-reference/endpoint/create-app) or [Create Build](/api-reference/endpoint/create-build). Files are capped at **1 GB**. ## Request body Original filename. Extension must match the platform. `"android"` or `"ios"`. Size in bytes. Must be `> 0` and `≤ 1073741824`. Defaults to `"application/octet-stream"`. Must match the `Content-Type` header you send on the S3 `PUT`. | Platform | Allowed extensions | | --------- | ------------------------------------------------------- | | `android` | `.apk`, `.xapk`, `.apks`, `.apkm` | | `ios` | `.zip` (zipped simulator `.app` bundle, **not** `.ipa`) | ## Response ```json theme={null} { "s3_presigned_url": "https://docket-blobs.s3.amazonaws.com/files/2/...&X-Amz-Signature=...", "s3_key": "files/2/4f8e1c2a-..._acme.apk", "content_type": "application/vnd.android.package-archive", "filename": "acme.apk" } ``` # API Reference Source: https://docs.docketqa.com/api-reference/introduction Programmatically create, run, and manage your Docket tests and modules The Docket API lets you integrate Docket into your workflows by creating tests, triggering runs, and managing reusable modules programmatically. **Base URL:** ``` https://api.docketqa.com ``` ## Authentication All API requests require an `X-API-KEY` header. You can find your API key in your [Docket account CI/CD tab](https://app.docketqa.com/). ```bash theme={null} curl -X GET https://api.docketqa.com/test_blueprint/list \ -H "X-API-KEY: your-api-key" ``` Keep your API key secret. Do not expose it in client-side code or public repositories. ## Key concepts ### Blueprint types Docket organizes tests using **blueprint types**: | Type | Value | Description | | -------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | **Integration** | `"integration"` | A standard end-to-end test with a sequence of steps. | | **Account (Module)** | `"module"` | A login/account module with stored credentials and a starting URL. | | **Module** | `"step_module"` | A reusable set of steps that can be embedded in other tests. Created via the [Modules API](/api-reference/endpoint/create-module). | ### Step types Steps define the actions your test performs. Each step has a `type` that determines its behavior: | Type | Description | | ------------------- | ------------------------------------------------------ | | `"act"` | AI-driven browser action (click, type, navigate, etc.) | | `"assert"` | AI-driven assertion that verifies page state | | `"step_module"` | Execute a reusable module inline | | `"api"` | Make an HTTP request (GET, POST, PUT, DELETE) | | `"trigger_run"` | Trigger another test blueprint as a sub-run | | `"key"` | Press a keyboard key (recorded step) | | `"type"` | Type text into the focused element (recorded step) | | `"mouse_move"` | Move mouse to coordinates (recorded step) | | `"left_click"` | Left click at coordinates (recorded step) | | `"right_click"` | Right click at coordinates (recorded step) | | `"double_click"` | Double click at coordinates (recorded step) | | `"triple_click"` | Triple click at coordinates (recorded step) | | `"left_click_drag"` | Click and drag (recorded step) | | `"scroll"` | Scroll the page (recorded step) | | `"wait"` | Wait for a duration (recorded step) | | `"deeplink"` | Open a deep link URL (mobile only) | ### Device types Tests can target different device types: | Device | Value | Description | | ------------------- | ----------- | ------------------------------------------- | | **Desktop browser** | `"browser"` | Default. Runs in a remote Chromium browser. | | **Android** | `"android"` | Runs on an Android device/emulator. | | **iOS** | `"ios"` | Runs on an iOS device/simulator. | Modules are device-agnostic — a single module can be referenced from a browser test at one viewport and from a mobile test on a phone. The runtime selects the right internal cache per execution config, so each combination of device / viewport / zoom stays sharp on its own. ## Endpoints Create a new test blueprint with steps Trigger a test run for one or more tests Retrieve results for a specific test run List all test blueprints in your account Create a reusable module Retrieve a specific module by ID List modules with optional filtering Update an existing module # Agent Rules Source: https://docs.docketqa.com/essentials/agent-context Context provided to the Docket AI agents about how to interact with your website ### Agent Rules Agent rules are instructions injected into Docket's system prompt when running your tests. They help the agent navigate application-specific behavior that isn't obvious from the UI alone. Agent rules are particularly useful when writing [AI Steps](/essentials/ai-steps), as they provide the AI agent with application-specific knowledge to make better decisions. **Examples:** * The "Create Project" button is only visible after hovering over the sidebar and clicking the plus icon * The onboarding modal must be dismissed before any part of the dashboard becomes interactive * To invite a teammate, go to "Workspace Settings" via the top-right dropdown, then open the "Members" tab * "Add to Cart" is labeled as "Reserve Now" on product detail pages for rental items * The "Submit for Approval" button only appears after all form fields are valid and the form auto-saves Each rule can be up to 1,024 characters, with a maximum of 10 rules per level. *** ### Company-Level Rules Company-level rules apply to **all tests** across your organization. Configure them from the Agent Rules tab on the Docket dashboard. Screenshot 2025-07-17 at 6.25.22 PM.png *** ### Suite-Level Rules You can also define agent rules at the **test suite** level. Suite-level rules are additive — they are combined with your company-level rules when running tests in that suite. This is useful when different parts of your application have different navigation patterns, terminology, or behavior. For example, your admin dashboard might have different conventions than your public-facing app. To add suite-level rules, open the create or edit modal for a test suite and scroll to the **Agent Rules** section. agent_rule_test_suite.png > **Note**: Suite-level rules supplement company rules — they don't replace them. The agent sees both sets of rules during test execution. # AI Steps Source: https://docs.docketqa.com/essentials/ai-steps How to write AI-driven test steps in Docket ### Overview AI steps are natural-language instructions that tell Docket's intelligent agent what to **do** or **verify** in your application.\ Unlike [recorded steps](/essentials/recorded-steps), which replay recorded coordinates, AI steps use Docket's **vision and reasoning models** to dynamically interpret your instructions and act accordingly. There are two main types of AI steps in Docket: 1. **AI Step** – perform an action 2. **Assert** – verify a condition You can mix and match AI steps and recorded steps to build powerful, adaptive, and self-healing tests. > **Getting Started**: New to Docket? Start with [Creating a Test](/essentials/test-creation) to learn the basics. *** ### AI Step An **AI Step** tells Docket to perform an action in your application. You can write these in two styles depending on how explicit or goal-oriented you want to be. #### Explicit (Step-by-Step) This style tells Docket exactly what to do, one action at a time. It’s ideal for debugging or when you need strict determinism. **Example:** * Click on the "Login" button. Click on the "Email" input field. Type "[nishant@docketqa.com](mailto:nishant@docketqa.com)". Click on the "Password" input field. Type "password123". Click on the "Sign In" button. **Pros:** * Predictable and repeatable **Cons:** * [Recorded steps](/essentials/recorded-steps) are faster and more accurate in this case * Can be verbose for longer flows * May need updating after UI redesigns #### Objective-Based This style focuses on *what* you want to achieve rather than *how* to achieve it.\ It’s useful for dynamic interfaces, forms, or multi-step workflows that may change layout. **Example:** * Login using "[nishant@docketqa.com](mailto:nishant@docketqa.com)" and "password123". **Pros:** * Short and human-readable * More resilient to UI changes * Uses full page context and reasoning **Cons:** * Less deterministic when multiple valid paths exist * Can be harder to debug exact click paths *** ### Special Capabilities Certain actions — such as [**sending or checking emails**](essentials/dedicated-mailboxes) and [**uploading files**](essentials/file-upload) — can only be performed using AI steps. These actions require contextual reasoning and browser-level access that recorded steps don’t support. **Examples:** * Upload the file "contract.pdf" to the upload input on the page. * Check the inbox for a verification code and enter it into the confirmation field. Docket’s agent will handle the entire sequence intelligently, linking file uploads and email variables (like `@registration_email`) to the current test run. *** ### Assert Step An **Assert** step tells Docket to verify that a condition holds true at the current state of your application.\ When you write an assertion, Docket takes a **screenshot**, analyzes the page using its **vision model**, and uses prior test history to understand context. The 5 most recent actions include their screenshots, while older actions are passed as text-only context. **Examples:** * Assert that the dashboard shows at least 3 recent orders. * Assert that a success message appears saying "Account created successfully." If the assertion fails, Docket will mark the test as **failed**, capture a screenshot and reasoning log, and continue or stop depending on your test configuration. #### Assertion Screenshots (Lookback) By default, Docket passes the **last 5 screenshots** to the assertion model, giving it context about what happened in preceding steps. You can configure this value between 1 and 10 per step. To adjust this, click the **gear icon** on any assert or AI step. The icon turns blue when the value differs from the default. AI_step_gear.png change_assertion_screenshots.png A higher value gives the assertion model more context about preceding actions — useful for multi-step flows where the assertion depends on earlier state. A lower value is faster and works well for assertions that only need the current page state. *** ### Writing Good Assertions Well-written assertions make your tests reliable and meaningful. Poorly defined ones can make results ambiguous.\ Follow these guidelines for clarity and precision: | Problem | Bad Example | Improved Example | | ----------------------------- | ------------------------------------------ | ------------------------------------------------------------------- | | Missing `assert` keyword | Look for search results on the main body | **Assert** that there are search results displayed on the main body | | Ambiguous goal | Assert that results are correct | Assert that search results are sorted by date | | Unverifiable statement | Assert that the page looks good | Assert that no text in the table overflows its cell | | Too precise for minor details | Assert that the divider color is #ff5733 | Assert that the divider appears red | | Time-based check | Assert that the video plays a 10-second ad | Avoid timing-based assertions | > **Note**\ > Writing words like `verify`, `check`, `ensure`, `assert` or `validate` during an AI step may also result in an assertion action. > but we recommend using explicit `assert` actions for consistency and accuracy. *** ### Early Termination Docket can mark a test as failed without completing the entire flow if, during self heal or AI steps, it detects usability issues that would frustrate a real user. The agent will fail the test early if it encounters: * The feature is not easily findable and requires navigating through multiple menus or sections * The interface uses non-standard or unintuitive patterns * The task takes significantly more steps or retries than expected * There are visible errors, missing features, or unresponsive UI elements * The interface is confusing due to unclear labeling, layout, or navigation * The tester is unsure how to proceed because the next step isn't obvious or discoverable Even without an explicit assertion, encountering any of the above will cause the test to fail—unless specified otherwise. You can craft your prompt accordingly if you'd like to override this behavior. > **Tip**: This behavior ensures Docket catches not just broken functionality, but also poor user experiences that could lead to user frustration or abandonment. *** ### Testing AI Steps in the Remote Screen When working with AI steps during test creation, you can test them in real-time using the [remote screen](/essentials/remote-screen). Simply write an AI step and click the **play button** next to it while the remote screen is running. Docket will execute that step immediately, allowing you to: * Verify the step works as expected * See the agent's reasoning in real-time * Iterate quickly on your test instructions * Observe how the agent interprets your natural language commands This live testing capability helps you refine your AI steps before running the full test, ensuring your instructions are clear and effective. *** ### Combining Cached and AI Steps You can combine [recorded steps](/essentials/recorded-steps) and AI steps to achieve a balance of precision and flexibility. | Use Case | Recommended Step | | ------------------------------------- | ----------------------------------------------- | | Deterministic clicks or scrolls | **[Recorded Step](/essentials/recorded-steps)** | | Dynamic workflows or variable layouts | **AI Step** | | Page validations or checks | **Assert Step** | | File uploads or email actions | **AI Step** | **Example Combined Flow:** * \[Recorded Step] Click "Sign In" * \[AI Step] Login using "[nishant@docketqa.com](mailto:nishant@docketqa.com)" and "password123" * \[Assert Step] Assert that the dashboard loads successfully #### Important: Page State After AI Steps When using AI steps followed by recorded steps, it's **critical** to consider where your AI step will leave the page once complete. Recorded steps rely on specific screen coordinates, so if an AI step ends on an unexpected page state, scroll position, or modal, subsequent recorded actions may fail or become flaky. **Best Practices:** * Be explicit about the final state in your AI step (e.g., "Login and ensure you're on the dashboard") * Verify the page has fully loaded before transitioning to recorded steps * If using modals or overlays, explicitly close them in the AI step if recorded steps follow * Consider adding a brief assertion to confirm the expected page state before recorded steps execute **Example:** ``` ❌ Bad: "Login" (leaves page state ambiguous) ✅ Good: "Login using credentials and wait for the dashboard to fully load" ``` This ensures recorded steps start from a predictable, consistent state and reduces test flakiness. > **Learn more**: See [Recorded Steps](/essentials/recorded-steps) to understand how coordinate-based actions work and when to use them. # Anti-Bot Detection Source: https://docs.docketqa.com/essentials/bot-detection Solutions for bot detection systems including Clerk and IP allowlisting ## Docket IP Allowlist To prevent our automated requests from being blocked, please allow-list the following IP addresses in your security systems. If you have **Proxy** turned on in your Browser Settings, Docket will use a residential proxy from the region you've selected. In this case, you should allow-list the following IP addresses depending on the region: | Region | IPv4 Address | IPv6 Address | | :------------------- | :--------------- | :--------------------------------- | | **US West** | `209.71.96.165` | `2a09:8280:e633::91:90e3:0` | | **US East** | `204.93.227.70` | `2605:4c40:40:e85c:0:3cca:61de:1` | | **Europe (UK)** | `205.234.240.78` | `2605:4c40:94:cbfa:0:d88d:acca:1` | | **Asia (India)** | `204.93.145.73` | `2605:4c40:145:2420:0:f923:aa52:1` | | **Embedded Browser** | `52.33.220.88` | `n/a` | These IPs should be allowlisted in: * Firewalls * Bot detection systems * Rate limiting rules * WAF configurations ## Clerk Bot Detection If you see a Clerk bot detection page in one of your test failures, you have likely enabled Clerk Bot Detection turned on. Docket's AI is running in a headless browser, which is often detected as a bot by Clerk. There are two ways to resolve this: ### 1. Disable Clerk Bot Detection on staging Clerk does not have a granular way to allowlist User-Agent. The best way to resolve this is to disable Clerk Bot Detection on staging. ### 2. Create a simple API to return a session token to Docket Clerk enables services to bypass bot detection by attaching a session token to the request. You can read more about it [here](https://clerk.com/docs/guides/development/testing/overview#testing-tokens). If you want to test on production or keep Clerk bot detection on for staging, you can implement an API that returns a session token. The API is necessary because session tokens are short-lived and require your Clerk tokens to generate, therefore only you can generate it. Here is an example of how you can implement this API: ```javascript theme={null} import { clerkClient } from "@clerk/clerk-express"; const clerk = clerkClient({ secretKey: process.env.CLERK_SECRET_KEY, }); app.post("/session", async (req, res) => { const { clerkToken } = req.body; const session = await clerk.sessions.create({ userId: clerkToken, }); res.json(session); }); ``` Once you have the API, you can add it in advanced settings. Clerk Bot Detection Configuration # Bulk Create Source: https://docs.docketqa.com/essentials/bulk-create Import existing test cases from documents to create multiple tests at once ### Bulk Create Bulk create lets you import existing test cases from a document and create multiple Docket tests in a single operation. This is ideal for migrating test cases from spreadsheets, test management tools, or written documentation. *** ### Getting Started Navigate to the Tests tab and click **Create Multiple Tests**. You'll see two options: 1. **Bulk Create** — Import test cases from an existing document 2. **[Generate Tests](/essentials/generate-tests)** — Use AI to generate test cases from PRDs or screenshots Select **Bulk Create** to proceed. multi_create_options.png *** ### Uploading a Document Drag and drop your file or click to browse. Docket parses the document and extracts individual test cases automatically. **Supported formats:** CSV, Excel (`.xls`, `.xlsx`), Word (`.doc`, `.docx`), PDF, TXT, RTF drop_file_to_bulk_create.png After upload, Docket runs a two-stage process: 1. **Upload** — Your file is uploaded and queued for processing 2. **Format & Parse** — Docket extracts and structures the test cases from your document *** ### Reviewing Parsed Tests Once parsing completes, you'll see a list of extracted test cases. Each test case shows its title and steps, and can be expanded for review. generated_tests.png From here you can: * **Bulk Create All** — Create all parsed tests at once with shared settings (test suite, viewport, browser zoom) * **Create Test** — Create an individual test case and open it in the editor for fine-tuning * **Upload Another File** — Start over with a different document When bulk creating, all tests are created as drafts in the [folder](/essentials/folders) you were viewing when you started the process. *** ### Best Practices * **Structure your source document clearly** — Use consistent formatting with distinct test titles and numbered steps for best parsing results * **Review before creating** — Skim the parsed output to catch any misinterpretations before bulk creating * **Use CSV for structured data** — CSV files with columns for test name, steps, and URL tend to parse most reliably * **Organize first** — Navigate to the desired [folder](/essentials/folders) before starting a bulk create to keep your tests organized # CI Integration Source: https://docs.docketqa.com/essentials/ci-integration Integrating Docket runs with CI/CD pipeline ### Setting up your CI/CD with Docket **Pre-requisites** 🚨 1. Make sure you have a Github account (with admin access to repos you’d like to connect) 2. Make sure you have a Docket account 3. Make sure you have a **Docket API Key** 1. Can’t find one? No worries, e-mail `boris@docketqa.com` for support! **Set-up Process** 🚀 1. Add your **Docket API** key to your Github Org 1. Open the repo you’d like to connect on Github 2. Click on **Settings** > **Security > Secrets and variables > Actions** 3. Create a new **`Repository Secret, name it DOCKET_API_KEY`** 2. Log-in to [app.docketqa.com](http://app.docketqa.com) and click on `CI/CD` Screenshot_2025-05-21_at_7.17.39_PM.png 3. You should see a big **Connect GitHub** button, click it Screenshot_2025-05-21_at_7.20.31_PM.png 4. Follow the installation instructions & select your repo Screenshot_2025-05-21_at_7.30.00_PM.png 5. After you click `Install` , you should be re-directed back to Docket. Click `View Connected Repos` . You should now see the connected repo Screenshot_2025-05-21_at_7.33.05_PM.png ### How the Gated Deployment Process Works 1. **Trigger**: Your deployment workflow is typically triggered by an event like a tag push (e.g., `v1.0.0`). This kicks off a Test Suite run on Docket. 2. **QA Status Check**: The workflow identifies the specific commit associated with the trigger and polls GitHub for a commit status from Docket QA (e.g., a status with the context `ci/docket-qa`). When Docket finishes running your test suite, it notifies Github about the pass/fail status of the commit. 3. **Automated Path (QA Passes)**: * If the Docket QA status for the commit is `success`, the workflow proceeds to deploy your application automatically. 4. **Manual Override Path (QA Fails or Times Out)**: * If the Docket QA status is `failure`, `error`, or if the check times out before a `success` status is received: * The workflow will **not** automatically deploy. * Instead, a **manual approval process** is initiated which involves creating a GitHub Issue detailing the QA failure and asking for a decision. * Designated approvers (specified in the workflow) can review the situation and comment on the issue (e.g., with `/approve` or `/reject`). * If **approved**, the workflow proceeds with the deployment. * If **rejected** or if the approval request times out, the deployment is halted, and the workflow job fails. This ensures quality control via Docket QA while providing the necessary flexibility for authorized manual overrides. Add `.github/workflows/release-pipeline.yml` > This is an example workflow for the release step of your CI/CD pipeline. In short, it assigns a `pending` status to the release commit and kicks off a Docket test run using: your Docket API Key + the `test_blueprint_category_id` of your test group in docket (this id resembles a grouping of all the QA tests you want to run). ```yaml theme={null} name: Release Pipeline with Docket QA on: release: types: [published] workflow_dispatch: inputs: tag_to_qa: description: 'Git tag to run QA against (e.g., v1.0.0). Must exist.' required: true type: string jobs: initiate_docket_qa: name: Initiate Docket QA Tests runs-on: ubuntu-latest permissions: contents: read # To checkout the code/tag statuses: write # To set the initial "pending" commit status steps: - name: Determine Ref and SHA for QA id: qa_commit_details run: | REF_TO_CHECKOUT="" SHA_FOR_STATUS="" # Will be determined after checkout for workflow_dispatch TAG_NAME="" if [[ "${{ github.event_name }}" == "release" ]]; then TAG_NAME="${{ github.ref_name }}" REF_TO_CHECKOUT="refs/tags/$TAG_NAME" SHA_FOR_STATUS="${{ github.sha }}" # For release events, github.sha is the commit SHA of the tag echo "Release event for tag: $TAG_NAME, Ref: $REF_TO_CHECKOUT, SHA: $SHA_FOR_STATUS" elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then TAG_NAME="${{ github.event.inputs.tag_to_qa }}" REF_TO_CHECKOUT="refs/tags/$TAG_NAME" echo "Workflow dispatch for tag: $TAG_NAME, Ref: $REF_TO_CHECKOUT. SHA will be resolved after checkout." # SHA_FOR_STATUS will be set in the next step after checkout else echo "::error::Unsupported event: ${{ github.event_name }}" exit 1 fi echo "ref_to_checkout=${REF_TO_CHECKOUT}" >> $GITHUB_OUTPUT echo "sha_for_status_initial=${SHA_FOR_STATUS}" >> $GITHUB_OUTPUT echo "tag_name=${TAG_NAME}" >> $GITHUB_OUTPUT - name: Checkout Code for QA uses: actions/checkout@v4 with: ref: ${{ steps.qa_commit_details.outputs.ref_to_checkout }} fetch-depth: 0 # Ensure tags are fetched - name: Resolve SHA for Tag (if not already set) id: resolve_sha run: | FINAL_SHA="${{ steps.qa_commit_details.outputs.sha_for_status_initial }}" if [ -z "$FINAL_SHA" ]; then # This path is mainly for workflow_dispatch, where SHA is resolved from the checked-out ref echo "Resolving SHA from checked-out ref: ${{ steps.qa_commit_details.outputs.ref_to_checkout }}" FINAL_SHA=$(git rev-parse HEAD) if [ -z "$FINAL_SHA" ]; then echo "::error::Could not resolve SHA for ref ${{ steps.qa_commit_details.outputs.ref_to_checkout }} after checkout." exit 1 fi echo "Resolved SHA: $FINAL_SHA" fi echo "sha_for_status=${FINAL_SHA}" >> $GITHUB_OUTPUT - name: Set Initial QA Status to Pending uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const releaseTag = "${{ steps.qa_commit_details.outputs.tag_name }}"; const sha = "${{ steps.resolve_sha.outputs.sha_for_status }}"; if (!sha) { core.setFailed("Could not determine commit SHA to set status."); return; } core.info(`Setting 'pending' status for Docket QA on tag: ${releaseTag} (SHA: ${sha})`); await github.rest.repos.createCommitStatus({ owner: context.repo.owner, repo: context.repo.repo, sha: sha, state: 'pending', target_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, // Link to this workflow run description: 'Docket QA tests initiated, awaiting results...', context: 'ci/docket-qa' // Must match the context used by the listener and deploy workflow }); core.info("Pending status set successfully."); - name: Trigger Docket QA Test id: trigger_docket_qa uses: signdocket/docket-action@v2 # Assuming this action uses the GITHUB_SHA of the checked-out commit with: apiKey: ${{ secrets.DOCKET_API_KEY }} repositoryFullName: ${{ github.repository }} # The docket-action should pick up the correct commit SHA after the checkout step. # Ensure the docket_run_completed event payload contains this SHA as 'commitSha'. testParameters: | { "test_blueprint_category_id": "3", "test_suite_url_overrides": { "3": "https://bing.com" }, "test_url_overrides": { "15": "https://staging.docketqa.com" } } - name: QA Process Initiated run: | echo "Docket QA test process has been initiated for release tag: ${{ steps.qa_commit_details.outputs.tag_name }} (SHA: ${{ steps.resolve_sha.outputs.sha_for_status }})." echo "Docket run ID: ${{ steps.trigger_docket_qa.outputs.runId }}" echo "Awaiting webhook from Docket server to update commit status via the 'Docket Run Results' workflow." ``` `.github/workflows/docket-results-qa-listener.yml` When your test run completes, Docket sends a dispatch event to your Github repository. This workflow subscribes to such events and marks the release commit’s status to pass/fail depending on the outcome of the test run. ```yaml theme={null} name: Docket Run Results on: repository_dispatch: types: [docket_run_completed] jobs: handle-docket-run-results: name: Handle Docket Run Results runs-on: ubuntu-latest permissions: statuses: write steps: - name: Log QA Result Payload and Map Status id: qa_data run: | echo "Received Docket QA run completed event!" echo "Client payload: ${{ toJSON(github.event.client_payload) }}" COMMIT_SHA="${{ github.event.client_payload.commitSha }}" DOCKET_SERVER_STATUS="${{ github.event.client_payload.status }}" DETAILS_URL="${{ github.event.client_payload.detailsUrl }}" SUMMARY="${{ github.event.client_payload.summary }}" CONTEXT_LABEL="ci/docket-qa" DOCKET_RUN_ID="${{ github.event.client_payload.runId }}" echo "Commit SHA: $COMMIT_SHA" echo "Docket Server Status: $DOCKET_SERVER_STATUS" echo "Docket Run ID: $DOCKET_RUN_ID" echo "Details URL: $DETAILS_URL" echo "Summary: $SUMMARY" echo "Context Label for Commit Status: $CONTEXT_LABEL" # Map Docket server status to GitHub commit status states GITHUB_COMMIT_STATE="error" if [[ "$DOCKET_SERVER_STATUS" == "passed" ]]; then GITHUB_COMMIT_STATE="success" elif [[ "$DOCKET_SERVER_STATUS" == "failed" ]]; then GITHUB_COMMIT_STATE="failure" elif [[ "$DOCKET_SERVER_STATUS" == "error" ]]; then GITHUB_COMMIT_STATE="error" fi echo "github_commit_state=${GITHUB_COMMIT_STATE}" >> $GITHUB_OUTPUT echo "commit_sha_output=${COMMIT_SHA}" >> $GITHUB_OUTPUT echo "details_url_output=${DETAILS_URL}" >> $GITHUB_OUTPUT echo "summary_output=${SUMMARY}" >> $GITHUB_OUTPUT echo "context_label_output=${CONTEXT_LABEL}" >> $GITHUB_OUTPUT - name: Set Final Commit Status uses: actions/github-script@v7 if: steps.qa_data.outputs.commit_sha_output != '' && steps.qa_data.outputs.commit_sha_output != null with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const commitSha = "${{ steps.qa_data.outputs.commit_sha_output }}"; const state = "${{ steps.qa_data.outputs.github_commit_state }}"; const targetUrl = "${{ steps.qa_data.outputs.details_url_output }}"; let description = "${{ steps.qa_data.outputs.summary_output }}"; if (!description) { description = `Docket QA: ${state}`; } description = description.substring(0, 140); const contextLabel = "${{ steps.qa_data.outputs.context_label_output }}"; core.info(`Setting commit status for SHA: ${commitSha} to '${state}' with context '${contextLabel}'`); try { await github.rest.repos.createCommitStatus({ owner: context.repo.owner, repo: context.repo.repo, sha: commitSha, state: state, target_url: targetUrl, description: description, context: contextLabel }); core.info("Commit status set successfully."); if (state !== 'success') { core.setFailed(`Docket QA tests reported as '${state}'. Summary: ${description}`); } } catch (error) { core.setFailed(`Failed to set commit status: ${error.message}`); core.error(JSON.stringify(error)); } ``` Lastly, take a look at your deploy action, and optionally, add Docket QA runs as a blocking step (with manual unblocking if it does fail)! ```yaml theme={null} - name: Wait for Docket QA Status id: check_qa_status uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const commitSha = "${{ steps.resolve_final_sha.outputs.commit_sha }}"; const owner = context.repo.owner; const repo = context.repo.repo; const expectedContext = "ci/docket-qa"; // Ensure this context name is correct let qaPassed = false; let finalQaState = "pending"; // To store the terminal state if not success core.info(`Waiting for commit status on SHA: ${commitSha}, Context: ${expectedContext}`); // Timeout after X minutes (e.g. 30 * 60 * 1000 ms) const timeoutMs = parseInt("${{ vars.QA_TIMEOUT_MINUTES || 30 }}") * 60 * 1000; const pollIntervalMs = 30 * 1000; const startTime = Date.now(); while (Date.now() - startTime < timeoutMs) { try { const { data: statusesResponse } = await github.rest.repos.getCombinedStatusForRef({ owner, repo, ref: commitSha, }); const docketStatus = statusesResponse.statuses.find(status => status.context === expectedContext); if (docketStatus) { core.info(`Found status for '${expectedContext}': ${docketStatus.state}. Description: ${docketStatus.description}`); finalQaState = docketStatus.state; // Update finalQaState if (docketStatus.state === 'success') { core.info("Docket QA status is 'success'."); qaPassed = true; break; // QA Passed, exit loop } else if (docketStatus.state === 'failure' || docketStatus.state === 'error') { // Do NOT fail the step. Log a warning. qaPassed remains false. core.warning(`Docket QA status is '${docketStatus.state}'. Details: ${docketStatus.target_url || 'N/A'}`); qaPassed = false; break; // Exit loop, QA has reached a terminal non-success state } else if (docketStatus.state === 'pending') { core.info("Docket QA status is 'pending'. Waiting..."); } else { core.info(`Docket QA status is '${docketStatus.state}'. Waiting...`); } } else { core.info(`No status found yet for context '${expectedContext}' on SHA ${commitSha}. Waiting...`); finalQaState = "not_found"; // Update if no status found yet } } catch (error) { finalQaState = "error_fetching"; // Do NOT fail the step. Log a warning. if (error.status === 404) { core.info(`No statuses found for ref ${commitSha} (404). Waiting...`); } else { core.warning(`Error fetching commit statuses: ${error.message}. Retrying...`); } } await new Promise(resolve => setTimeout(resolve, pollIntervalMs)); } // After loop, determine final output based on qaPassed if (qaPassed) { core.info("Docket QA Passed!"); core.setOutput('qa_passed', 'true'); } else { // Log appropriate warning based on why QA didn't pass if (Date.now() - startTime >= timeoutMs && (finalQaState === 'pending' || finalQaState === 'not_found' || finalQaState === 'error_fetching')) { core.warning(`Timed out after ${timeoutMs / 60000} minutes waiting for Docket QA status on SHA ${commitSha} to be 'success'. Last known state: ${finalQaState}. QA is considered FAILED.`); } else if (finalQaState === 'failure' || finalQaState === 'error') { core.warning(`Docket QA for SHA ${commitSha} resulted in '${finalQaState}'. QA is considered FAILED.`); } else { core.warning(`Docket QA for SHA ${commitSha} did not achieve 'success'. Last known state: ${finalQaState}. QA is considered FAILED.`); } core.setOutput('qa_passed', 'false'); } // This script step itself should not fail due to QA outcome. // It has set the 'qa_passed' output which will drive the workflow logic. env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Ensure token is available to the script # <<< NEW STEP: Manual Approval if QA Failed >>> - name: Manual Approval if QA Failed (web-final) id: manual_approval_web # Unique ID for this approval step if: steps.check_qa_status.outputs.qa_passed == 'false' # Only run if QA failed uses: trstringer/manual-approval@v1 with: secret: ${{ secrets.GITHUB_TOKEN }} approvers: boris, nishant # <--- Add your usernames here minimum-approvals: 1 issue-title: "QA Failed: Manual approval for web-final tag ${{ steps.resolve_final_sha.outputs.tag_name }}" issue-body: | Docket QA checks failed for commit `${{ steps.resolve_final_sha.outputs.commit_sha }}` (tag `${{ steps.resolve_final_sha.outputs.tag_name }}`). Deployment to `web-final` requires manual approval. Please review the QA results and **comment with `/approve` or `/reject` on the issue created by this step.** Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} ``` ### URL Overrides Override starting URLs for tests during CI/CD runs to test against different environments. This is particularly useful when generating preview links (like Vercel preview deployments) and you want to test against those specific environments instead of your production URLs. #### Override Types * **Test Suite URL Overrides** (`test_suite_url_overrides`): **All tests in the suite** start from this URL * **Test Suite Login URL Overrides** (`test_suite_account_login_url_overrides`): **Account belonging to this test suite** will use this login URL * **Individual Test URL Overrides** (`test_url_overrides`): Override specific tests (takes precedence) #### Vercel Preview Example When deploying with Vercel, you might want to test your preview deployment before merging. Here's how to override entrypoints for tests, test suites, and account login flows: ```json theme={null} { "test_blueprint_category_id": ["17", "23"], "test_suite_url_overrides": { "17": "https://myapp-git-feature-branch-team.vercel.app", "23": "https://myapp-git-feature-branch-team.vercel.app/dashboard" }, "test_suite_account_login_url_overrides": { "17": "https://myapp-git-feature-branch-team.vercel.app/auth/login", "23": "https://myapp-git-feature-branch-team.vercel.app/admin/login" }, "test_url_overrides": { "167": "https://myapp-git-feature-branch-team.vercel.app/specific-feature", "234": "https://myapp-git-feature-branch-team.vercel.app/new-component" } } ``` In this example: * **Test suite `17`**: All tests start from preview root, login at `/auth/login` * **Test suite `23`**: All tests start from preview `/dashboard`, admin login at `/admin/login` * **Tests `167` and `234`**: Override suite settings with specific feature URLs # Dedicated Mailboxes Source: https://docs.docketqa.com/essentials/dedicated-mailboxes Learn how to use dedicated mailboxes in Docket ### Dedicated Mailboxes Dedicated mailboxes allow our agent to read and extract content from emails sent to an address generated by Docket. Our agent can only access unread emails that were delivered within the past 1 hour. This feature is perfect for OTP codes, magic links, invitation links, password reset links, verification emails, and more. Please note that the agent cannot send emails. If you have a use case that requires sending emails, please contact the Docket team. ### Creating a Dedicated Mailbox To create a dedicated mailbox, navigate to the Email Settings page in your Docket dashboard. Screenshot 2025-07-18 at 3.46.46 PM.png ### Email Filtering and Selection When multiple emails arrive in your dedicated mailbox, you can prompt the agent to filter for specific emails using subject keywords. This ensures the agent interacts with the correct email when multiple messages are present. The agent will search through emails from the past hour and the next minute (in case the email is lagging) and match based on the subject line keywords you specify in your prompt. ### Mailbox State Visibility During test execution, you can view the state of your mailbox at the time of any email-related tool call by clicking the mail button in the test interface. This modal shows: Screenshot 2025-07-18 at 3.46.46 PM.png * **Matching email** is processed by the agent * All emails present in the mailbox at that moment * Email timestamps and subject lines for easy identification This visibility feature helps you understand exactly which emails the agent found and interacted with during your test run. Screenshot 2025-07-18 at 3.46.46 PM.png ### Mailbox Viewer The Mailbox Viewer lets you inspect all emails received by your Docket mailboxes. Access it from the Email Settings page. Filter by plus address or search by subject to find specific emails. Mailbox Viewer ## Plus Addresses Plus addresses let you create custom email aliases (e.g., `yourbase+signuptest@docketsign.com`) for organizing different test scenarios. Create them in the Email Settings page. Plus Addresses Configuration Once created, plus addresses appear in the [email variable dropdown](/essentials/test-creation#-email-variables) when configuring test variables. ### Email Forwarding Each plus address can optionally forward incoming emails to an external address. This is useful for setting up and verifying plus-addressed emails (e.g., confirming account signups) directly in your own mailbox without needing to use the Docket browser. ## Prompting Best Practices * "Look for an email with 'verification' in the subject and click the confirmation link" * "Find the email containing 'password reset' in the subject line and use the reset link" * "Search for an email with 'invoice' in the subject and extract the order number" * "Get the OTP code from the email with 'two-factor' or '2FA' in the subject" # Files Source: https://docs.docketqa.com/essentials/file-upload Uploading files and reading file content into agent context ### Uploading Files You can click the Files tab to upload and manage files for your test. Screenshot 2025-07-18 at 3.46.46 PM.png You can upload multiple files as shown in the Files tab above. Each file appears with its filename and can be individually managed. To use a specific file in your test, reference it by name: `upload "cat.jpeg" to the profile picture` or `upload "ZDummy_PDF.pdf" to the document field`. For single file uploads, simply say `upload file`. *** ### Reading Files into Context Beyond uploading files to your application, Docket can also **read file contents into the agent's context**. This lets the agent reference information from your files when executing steps or making assertions. Supported file types for context reading include: | Category | Extensions | | --------------- | ----------------------------------------------------------------------------------------------------------- | | **Images** | `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.webp` | | **Text & Code** | `.txt`, `.md`, `.json`, `.xml`, `.html`, `.css`, `.js`, `.py`, `.java`, `.c`, `.cpp`, `.ts`, `.tsx`, `.jsx` | | **Config** | `.yml`, `.yaml`, `.toml`, `.ini`, `.cfg`, `.conf` | | **Documents** | `.csv`, `.pdf`, `.docx`, `.doc` | Files with unsupported extensions can still be uploaded to your application during a test, but their contents won't be available to the agent for context. #### Per-Step File Attachments You can attach specific files to individual steps by clicking the **gear icon** on any step. This scopes which files the agent can reference during that step's execution, keeping context focused and relevant. step_settings_file_picker.png This is useful when a step needs to reference data from a specific file — for example, asserting that form values match data in an uploaded CSV, or verifying that a document's content was correctly parsed by your application. # Folders Source: https://docs.docketqa.com/essentials/folders Organize your tests into a hierarchical folder structure ### Folders Folders let you organize tests into a hierarchical structure, similar to a file system. As your test suite grows, folders help you group related tests by feature, team, or workflow. *** ### Creating a Folder To create a folder, navigate to the Tests tab. You can create folders directly from the test list view using the folder creation option. create_folders.png Folder names can contain letters, numbers, hyphens, underscores, and spaces. You can nest folders up to 10 levels deep. *** ### Navigating Folders The breadcrumb bar at the top of the test list shows your current location in the folder hierarchy. Click any segment to jump to that level. folder_breadcrumb.png When the path gets long, intermediate segments are collapsed automatically — the root and last two segments always remain visible. *** ### Moving Tests and Folders You can move tests between folders in two ways: 1. **Drag and drop** — Drag a test or folder row onto another folder or breadcrumb segment 2. **Modify dialog** — Use the three-dot menu on a folder to access Rename, Move, and Expand options move_folders.png The **Expand** option dissolves a folder and moves all its contents up one level — useful for flattening your hierarchy when a folder is no longer needed. *** ### Archiving Folders To archive a folder, click the three-dot menu and select **Archive**. This archives the folder and all tests inside it, including any subfolders. Archived items can be restored by an admin. *** ### Folders and Bulk Create When you [bulk create tests](/essentials/bulk-create) or [generate tests with AI](/essentials/generate-tests), the new tests are placed in the folder you're currently viewing. Navigate to the desired folder before starting a bulk create operation to keep things organized. # Generate Tests Source: https://docs.docketqa.com/essentials/generate-tests Use AI to generate test cases from PRDs, screenshots, and documentation ### Generate Tests with AI Docket can generate test cases from your existing artifacts — PRDs, Figma screenshots, documentation, or any descriptive text. Describe what you want tested, upload supporting materials, and Docket's AI will produce structured test cases ready for review and creation. *** ### Getting Started Navigate to the Tests tab and click **Create Multiple Tests**, then select **Generate Tests**. You can also access this from the [Bulk Create](/essentials/bulk-create) flow by choosing the generation option. *** ### Uploading Artifacts Upload the materials you want Docket to analyze. These serve as context for the AI when generating test cases. **Supported formats:** Images (`.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`), text files (`.txt`, `.md`), documents (`.pdf`, `.doc`, `.docx`) Common artifacts include: * Product requirement documents (PRDs) * Figma screenshots or design mockups * Feature specifications * User flow diagrams gen_with_ai_artifact.png *** ### Writing a Generation Prompt The **Generation Prompt** is required and tells the AI what kind of tests to generate. Be specific about the flows, edge cases, and coverage you need. **Good prompts:** * "Generate 6 tests that verify the checkout path is functional, including adding items, applying a coupon, and completing payment" * "Create tests for the user registration flow covering: successful signup, password validation, duplicate email handling, and email verification" * "Generate tests for the settings page covering profile updates, password changes, and notification preferences" **Weak prompts:** * "Test everything" (too broad) * "Generate some tests" (no direction) You can optionally provide a **Starting URL** — this URL will be used as the default entry point for all generated tests. *** ### Reviewing Generated Tests After generation, you'll see a list of test cases. You can toggle between the **Test Cases** view and the **Raw Output** to inspect what the AI produced. generated_tests.png bulk_raw_output.png Each generated test case includes a title, steps, and a starting URL. You can delete individual test cases you don't need before creating them. *** ### Iterating on Results The AI retains context from previous generations, so you can refine results through follow-up prompts. Use the **Refine Tests** input to iterate: * "Add 2 more tests covering form validation edge cases" * "Make the login tests more explicit about error states" * "Remove the mobile tests and add desktop-only scenarios" Each iteration produces a **fresh set** of tests informed by the prior context — it doesn't modify previously generated tests in place. *** ### Creating Tests from Results Once you're satisfied with the generated test cases, you can: * **Bulk Create All** — Create all tests at once with shared settings (test suite, viewport, browser zoom) * **Create Test** — Create a single test and open it in the editor for further refinement Generated tests are created as drafts in the [folder](/essentials/folders) you were viewing when you started the process. > **Tip**: Generated tests are a starting point. After creation, open individual tests to fine-tune steps, add [recorded steps](/essentials/recorded-steps), or adjust [variables](/essentials/test-creation#test-variables). # Mobile Apps Source: https://docs.docketqa.com/essentials/mobile-apps Testing native iOS and Android applications with Docket ### Overview Docket supports writing dedicated test suites for your native **iOS** and **Android** apps, just like you would for a web app. Each mobile test runs against your app on a dedicated iOS simulator or Android emulator — the mobile counterpart to the web [remote screen](/essentials/remote-screen). ### Supported Devices When configuring a mobile test, you pick a device profile. Docket provisions a fresh simulator/emulator matching that profile for each run.
**iOS simulators** * iPhone 17 Pro * iPhone 16e * iPad Pro 13"
**Android emulators** * Pixel 9 * Pixel 9 Pro XL * Pixel 9 Pro Fold * Pixel Tablet * Galaxy S23
### Apps and Builds A mobile app in Docket is a long-lived container for every build you ship. Tests always run against the app's **active build**, which Docket installs onto the simulator before each run — so you never need to edit your tests after bumping a version. * **Create an app**: choose a name and platform (`ios` or `android`) and upload your first build. * **Add builds over time**: each build has its own name (typically a version or commit SHA) and binary. * **Switch the active build**: promote any build to active to run your existing tests against it — useful for release candidates or reproducing regressions on older versions. Deleting the active build auto-promotes the next most recent one. All of the above can be driven from CI with your API key — see [Upload a Build](/api-reference/endpoint/upload-build) for the upload flow and [Set Active Build](/api-reference/endpoint/set-current-build) for promoting a version after a release. ### Device Settings Mobile tests expose a **Device Settings** tab inside Advanced Settings for configuring the simulator/emulator environment before the run starts. This tab only appears for mobile tests. Device Settings * **Latitude / Longitude** (iOS and Android): override the device's GPS location so location-aware flows resolve to a specific place. * **Timezone** (iOS and Android): set the simulator/emulator's timezone, useful for testing time-of-day, scheduling, and region-specific behavior. * **Orientation** (Android only): switch the emulator between **portrait** and **landscape**. ### App Error Logs For both iOS and Android runs, Docket captures the app's native device logs and surfaces them in the run view under the **App errors** tab whenever a log is available, making it easy to trace a failed step back to a crash or exception inside your app. The log viewer highlights crashes and exceptions, collapses repeated lines, supports search, and offers the full log as a download. ### Build Requirements Docket installs your app onto a **simulator/emulator**, not a physical device. Upload a zipped **simulator `.app` bundle** — **not** an `.ipa`. #### Xcode Open the project, choose the app target and any simulator device in the toolbar, then go to **Product → Scheme → Edit Scheme** and set the **Run** build configuration to **Release**. Then press `Cmd + B`. The `.app` will be at: ``` ~/Library/Developer/Xcode/DerivedData//Build/Products/Release-iphonesimulator/.app ``` #### React Native ```bash theme={null} npx react-native run-ios --mode Release ``` The `.app` will be at `ios/build/Build/Products/Release-iphonesimulator/.app`. #### Flutter ```bash theme={null} flutter build ios --simulator ``` Add `--flavor ` if your project uses flavors. The `.app` will be at `build/ios/iphonesimulator/Runner.app`. Upload a `.apk` (or `.xapk` / `.apks` / `.apkm`) that includes `arm64-v8a` libraries. 32-bit-only APKs are rejected at upload. #### Android Studio Choose **Build → Build Bundle(s) / APK(s) → Build APK(s)**, or from the terminal: ```bash theme={null} ./gradlew assembleRelease ``` The `.apk` will be at `app/build/outputs/apk/release/app-release.apk`. #### React Native ```bash theme={null} cd android && ./gradlew assembleRelease ``` The `.apk` will be at `android/app/build/outputs/apk/release/app-release.apk`. #### Flutter ```bash theme={null} flutter build apk --release ``` Add `--flavor ` if your project uses flavors. The `.apk` will be at `build/app/outputs/flutter-apk/app-release.apk`. # Failure Notifications Source: https://docs.docketqa.com/essentials/notifications Receiving notifications about test failures on Docket ### Configuring notifications To access the notification configuration menu, open the Settings menu which you can access by clicking the user profile menu in the bottom left corner of the Docket dashboard. Screenshot 2025-07-17 at 6.19.24 PM.png ### Slack Failures You can configure to be notified in Slack when a test fails by configuring an incoming webhook. To set up a Slack webhook, head over to [https://api.slack.com/apps](https://api.slack.com/apps): 1. Click "Create New App." 2. Choose "From scratch." 3. Give it a name (e.g., "Docket Notifications") and select your Slack workspace. 4. In the left sidebar, go to "Incoming Webhooks." 5. Toggle the switch "Activate Incoming Webhooks" → ON. 6. Scroll down and click "Add New Webhook to Workspace." 7. Pick a channel to send them to and paste the provided webhook link in Docket. Screenshot 2025-07-17 at 6.21.20 PM.png ### Email Failures You can configure to be notified via email when a test fails by configuring the inbox you want to receive failures in. Screenshot 2025-07-17 at 6.23.14 PM.png ### Webhook Notifications You can configure webhooks to receive real-time notifications about test failures and other test events. Webhooks are ideal for integrating Docket with your own systems, triggering custom workflows, or sending notifications to tools beyond Slack and email. > **Learn more**: See [Webhooks](/essentials/webhooks) for detailed setup instructions, payload schemas, and security verification. # Recorded Steps Source: https://docs.docketqa.com/essentials/recorded-steps Understanding and maintaining recorded steps in Docket ### What Are Recorded Steps? Recorded steps are clicks, hovers, and scrolls that Docket records while you interact with the [remote screen](/essentials/remote-screen) during test creation. Each recorded step stores both **the exact screen coordinates** of your action and a **natural language annotation** that describes what you did. You can identify recorded steps by the **yellow cache icon** next to them.\ To see the coordinate that Docket has captured, simply hover over the icon. > **Tip**: For dynamic workflows or complex logic, consider using [AI Steps](/essentials/ai-steps) instead, which adapt to UI changes automatically. /images/remote_browser_cached_step.png *** ### How Recorded Steps Work Recorded steps execute **sequentially**, one after another. In [recording mode](/essentials/remote-screen#start-recording), they do not waiting for page loads or self heal. Recorded steps will auto wait for page loads or try to self heal during full test runs (see below). If a minor change is made to your UI, Docket will be able to self heal as long as the annotation of the recorded action is correct. However, after major UI changes, it is recommended you ensure your recorded steps are up to date. *** ### Recorded Steps During Full Test Runs When running a full test (manaully, scheduled, or part of CI/CD), Docket performs a **pre-check** before executing each recorded step.\ If the page hasn’t loaded yet or the click coordinate seems inconsistent with the annotation, Docket will trigger its **AI vision model** to attempt a **self-heal**. During self-healing, Docket uses: * The step’s **natural language annotation** (e.g. “login button”) * The current **visual state of the page** to find the correct element before proceeding.\ This combination of **coordinate precision** and **semantic context** gives Docket reliability even as your UI evolves. *** ### Writing Good Annotations The annotations you see under recorded steps (e.g. “click login button”, “scroll to footer”) are critical for Docket’s reasoning and self-healing. Here’s how to make them effective: #### Scroll Actions Describe not only *where* to scroll, but also *what should be revealed*. You should always include elements that will be interacted with post-scroll as part of actions that need to be revealed. ✅ **Good Example:** > Scroll to the footer of the page and reveal the Careers and Terms of Service buttons. ❌ **Bad Example:** > Scroll down. #### Click or Hover Actions Specify the exact element or purpose of the action. ✅ **Good Example:** > Click on the blue “Sign In” button in the top-right corner. ❌ **Bad Example:** > Click on button. *** ### Common Pitfalls | Issue | Description | Example | | -------------------------- | -------------------------------------- | -------------------------------------------------------- | | **Outdated Coordinates** | UX changed, making coordinates invalid | A new banner moves element off the page, can't self heal | | **Vague Annotations** | Unclear what element is being clicked | “Click on link” when multiple exist | | **Missing Scroll Context** | Scrolls recorded but not described | “Scroll down” instead of “Scroll to reveal footer links” | | **Redundant Steps** | Repeated clicks on the same element | Duplicate interactions | *** ### Best Practices * Re-record recorded steps after big UI updates * Review annotations for clarity * Keep English instructions specific and descriptive * Minimize unnecessary actions * Combine recorded steps with [AI steps](/essentials/ai-steps) for resilient flows > **Learn more**: See [AI Steps](/essentials/ai-steps) to understand how to use natural language instructions for dynamic test flows. *** ### Summary Recorded steps are the backbone of Docket's deterministic testing.\ They allow precise replay of user actions while staying flexible through Docket's AI-assisted pre-check and self-healing. Keep your recorded step annotations meaningful and accurate to ensure your tests remain stable, clear, and reliable. **Next Steps:** * Learn about [AI Steps](/essentials/ai-steps) for dynamic test flows * Read the full guide on [Creating a Test](/essentials/test-creation) # Remote Screen Source: https://docs.docketqa.com/essentials/remote-screen Understanding Docket's persistent browser and device instances ### Overview Docket launches a single persistent **remote screen** that stays active as you create and edit tests. For web tests this is a browser; for [mobile tests](/essentials/mobile-apps) it's an iOS simulator or Android emulator. In both cases the screen is embedded in the side panel and automatically stays in sync with your current test configuration. ### Start Screen launcher **Start Screen** is a split button: the main half launches with the displayed device; the caret opens a picker grouped by **Browser** / **iOS** / **Android**, with per-resolution entries and inline app selection on mobile. The default mirrors the test you're viewing, so the typical flow is: open a test → click Start Screen. Start Screen launcher with the iOS tab open, iPhone 17 Pro selected, and iOS Alpha picked as the app **Key behaviors:** * **Single active tab**: one tab at a time. Other tabs see the screen as "busy" and can take it over. * **Persistent session**: the screen survives test switches. Variables, files, rules, and login session auto-sync as you navigate. * **Config changes need a restart**: viewport, zoom, device, app, or entrypoint URL changes trigger the **Screen Out of Sync** flow. ### Controls When the screen is launched and you're viewing a test, you'll see several control options in the bottom bar: Remote Screen Controls #### Status Badge Shows the current state of the instance. The screen cycles through several states: * **Offline**: Not started * **Starting**: Instance is starting up * **Online**: Ready for execution or recording * **Recording**: Ready for interaction. All events are captured and created in the step recorder. Cannot execute steps while recording * **Executing**: Playing back steps. Cannot record during execution * **Stopping**: Instance was stopped and will go offline #### Self Heal Toggle Controls how [recorded steps](/essentials/recorded-steps) replay during test execution. * **Enabled** (default): Before replaying each recorded step, Docket performs a check to see if the element is still available at the saved coordinates. If the check passes, the step executes normally. If the element has moved or is unavailable, the agent self-heals by locating it using the step description and action * **Disabled**: The agent will directly replay from the exact saved coordinates without performing any checks or attempting to adapt #### Run from Step Executes your test starting from the currently selected step (highlighted in blue) and continues through subsequent steps in sequence. The execution respects the Self Heal toggle setting. #### Start Recording Enables recording mode where you can interact with the embedded screen and Docket will automatically capture and cache your actions. This is the primary way to create [recorded steps](/essentials/recorded-steps). #### Resync Opens the resync dialog to re-push the test's configuration to the running screen. For web tests: * **Navigate to URL**: navigate the browser to the test's entrypoint URL. * **Restart browser**: restart the browser to apply viewport, zoom, and tunnel changes. For mobile tests: * **Restart app**: relaunch the [active build](/essentials/mobile-apps#apps-and-builds) on the simulator/emulator. The app is not reinstalled and the device is not restarted. Variables, files, rules, and login session are already auto-synced, so resync is only needed for the items listed above. ### Screen Out of Sync When the running screen drifts from the current test's device, viewport, zoom, orientation, or app, the stream gets an overlay listing the specific drifts and a single **Restart Screen** button to realign. Run, Record, and Run-from-Step are disabled until the worker matches. Modules inherit the running screen's config and never trigger this overlay. #### Stop Terminates the instance. You'll need to launch a new one to continue creating or editing tests. # Running a Test Source: https://docs.docketqa.com/essentials/running-test Different ways to run a test on Docket ### Manual Run You can manually trigger test runs on an individual test level or a [test suite](/essentials/test-suite) level. To trigger a run for an individual test, click the play icon on the test row: Screenshot 2025-07-17 at 5.14.19 PM.png To trigger a run for all tests in a test suite, go to the test suites tab and click play icon on any of the suites: Screenshot 2025-07-17 at 5.15.41 PM.png ### CI/CD Integration You can trigger a test suite to run as part of your CI/CD pipeline. See the [CI Integration](/essentials/ci-integration) page for more details on how to set this up. ### Scheduling a Run To schedule a run, you can click the edit icon on a test suite to expose the scheduling menu. Screenshot 2025-07-17 at 5.17.40 PM.png Screenshot 2025-07-17 at 5.18.25 PM.png This will allow you to schedule test runs on a Daily, Weekly, or Hourly cadence. You can also specify your on custom cron tab schedule. When specifying this schedule, please follow the format of [AWS EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-scheduled-rule-pattern.html#eb-cron-expressions). An easy way to figure out the schedule is to copy that entire page into ChatGPT and describe your desired in plain english, and ask it to output the right result (we will embed this functionality into Docket soon as well!). # Creating a Test Source: https://docs.docketqa.com/essentials/test-creation How to create a test on Docket ### Prerequisites First, go to the [test suites](/essentials/test-suite) page to create a test suite that the test will belong to. ### Creating a Test To get started with writing a test on Docket, you should: 1. Navigate to the tests tab on the left 2. Click "Create New Test" 3. Enter a title, select a test suite, and provide an entrypoint URL (the starting point for your test) 4. Click "Launch Browser" Screenshot 2025-07-17 at 4.03.12 PM.png The URL you provide will be where the Docket Browser agent automatically navigates to begin executing your test. > **Learn more**: For detailed information about the persistent browser/device instance and its controls, see the [Remote Screen](/essentials/remote-screen) documentation. > **Testing a native mobile app?** Instead of an entrypoint URL, mobile tests target a [mobile app](/essentials/mobile-apps) on a simulator or emulator. See the [Mobile Apps](/essentials/mobile-apps) guide for supported devices and build requirements. ### Building Your Test To create tests on Docket, you can simply interact in the [remote screen](/essentials/remote-screen) and Docket will record actions alongside English annotations automatically. There are six types of steps you can write on Docket: 1. **[Recorded Steps](/essentials/recorded-steps)** - Precise coordinate-based actions that replay exactly as recorded and self-heal when the UI changes 2. **[AI Steps](/essentials/ai-steps)** - Natural language instructions that adapt to your UI dynamically 3. **API Steps** - Network requests to endpoints for seeding, setup, and teardown of test resources 4. **Code Steps** - Run sandboxed Python to transform data, manage files, call APIs, or drive the browser 5. **Modules** - Reusable collections of steps that can be shared across multiple tests 6. **Trigger Run** - Trigger another Docket test and pass variables between them Learn more about each step type to understand when to use them. ### API Steps API steps allow you to make network requests to any endpoint during your test execution. They're incredibly powerful for creating dynamic, data-driven tests that can fully manage test resources throughout their lifecycle. **Common use cases:** * **Test Setup**: Creating test data, user accounts, or resources before the main test flow * **Test Seeding**: Populating databases or systems with necessary data * **Dynamic CRUD Operations**: Create resources, store their IDs, then update or delete them later in the test * **Test Teardown**: Cleaning up resources after test completion API steps support all HTTP methods (GET, POST, PUT, DELETE, PATCH, etc.) and pass when they receive a 2xx response status code. ##### Extracting Response Data API steps can extract data from responses and store them in variables using **JSON Path** expressions. This enables powerful workflows where you create resources and use their IDs in subsequent steps. API Step Configuration In the example above, we're extracting a `resource_id` from a nested API response. Notice how the request also uses `@bearer_token` in the Authorization header—this token was likely extracted from a previous authentication API call, demonstrating how you can chain multiple API steps together. **Response structure:** ```json theme={null} { "response": { "data": [ {"resource_id": 123, "other_data": "..."}, {"resource_id": 456, "other_data": "..."} ] } } ``` **JSON Path:** `response.data[0].resource_id`\ **Result:** Extracts `123` and stores it in the `@resource_id` variable ##### Dynamic CRUD Example API steps become extremely powerful when you combine variable extraction with multiple requests: 1. **Create** a product via POST and extract its ID to `@product_id` 2. **Update** the product via PUT to `https://api.example.com/products/@product_id` 3. Use the product in your UI test flow 4. **Delete** the product via DELETE to `https://api.example.com/products/@product_id` for cleanup This pattern allows you to create fully isolated, repeatable tests that manage their own test data dynamically without polluting your database or depending on pre-existing resources. ### Code Steps A **Code Step** runs a snippet of **Python** at a point in your test. Reach for one when a step needs real logic that [AI Steps](/essentials/ai-steps) and [Recorded Steps](/essentials/recorded-steps) aren't meant for: transforming data, reading or creating files, calling an API, or computing a value to reuse later. **Common uses:** * Generate or transform test data (e.g. a unique payload or a signed token) * Read an [uploaded file](/essentials/file-upload) or browser download and extract a value * Call an external API and save part of the response * Drive the browser directly with Playwright ##### How It Works Your code is the body of a function with two values already in scope: | Name | Type | Description | | ----------- | --------------------------- | --------------------------------------------------------------------------- | | `context` | Playwright `BrowserContext` | The live browser the test is driving. `None` on mobile (iOS/Android) tests. | | `variables` | `dict[str, str]` | The test's variables. Read and write them here. | Whatever you store in `variables` is saved back to the test automatically; no `return` is needed. ```python theme={null} import requests resp = requests.get("https://api.ipify.org?format=json") variables["my_ip"] = resp.json()["ip"] ``` Saved values appear in the run results and can be referenced by later steps as `@my_ip`. > **Storing variables:** Values must be strings; wrap others with `str(...)` or `json.dumps(...)`. Use plain literal keys (`variables["token"]`), not dynamically computed ones, so Docket can detect the variable names. The Code Step editor with the AI assistant ##### Browser Access In browser tests, `context` is a synchronous Playwright `BrowserContext` you can drive directly: ```python theme={null} page = context.pages[0] variables["page_title"] = page.title() ``` ##### Files * The working directory holds your [uploaded files](/essentials/file-upload). Open them by name: `open("data.csv")`. * Files your code creates persist for later steps **in the same run**. * Browser-downloaded files live under `/tmp/docket-downloads/`; open them with the full path. ##### Runtime & Limits Code runs in an isolated sandbox: * **Synchronous Python only** (no `async`/`await`). * Default **timeout of 120 s**, configurable per step. * Importable: the full standard library plus `requests`, `PyPDF2`, `numpy`, `PIL` (Pillow), `openpyxl`, `docx`, and `faker`. Nothing is pre-imported, so `import` what you use. * Outbound HTTP(S) to public endpoints works; localhost and private/LAN addresses are blocked unless the run uses a [tunnel](/essentials/tunnel). * No process spawning (`subprocess`, `os.system`, `multiprocessing`). ##### Generate Code with AI Don't want to write Python? Describe the step in plain English and Docket's assistant writes it for you, aware of the available packages, `context`, and `variables`. Review before saving. ##### Results Expand a code step in the run view to see its output, formatted like every other action: * **STDOUT / STDERR**: captured output (STDERR turns red when the step fails) * **Created Variables**: values written to `variables`, shown as `@name = "value"` * **Created Files**: files the step wrote A code step **passes** unless it raises an unhandled error, times out, or exceeds a limit. ### Modules Modules are reusable collections of steps that can be created once and inserted into multiple tests. They're perfect for common workflows like logging in, navigating to a specific page, or performing setup tasks that are repeated across many tests. **Key features:** * **Create and manage** modules in the "Modules" section of Docket * **Compose with any step type**: Modules can contain AI steps, recorded steps, and API steps * **Can nest**: A `step_module` step inside a module references another module (up to 5 levels deep) * **Universal**: One module works across every browser viewport, iOS device, and Android device — modules inherit the running screen's config rather than carrying their own * **CRUD interface**: The module creation interface is similar to test creation, with a [remote screen](/essentials/remote-screen) for recording interactions ##### Variables in Modules Modules have specific rules around variable usage: * **Can reference variables**: Modules can use variables (like `@user_email` or `@auth_token`) that are defined in the tests where the module is used * **Can extract from API calls**: Modules can create new variables by extracting values from API response bodies within the module * **Cannot define variables**: Modules cannot create their own text, email, or random alphanumeric variables * **No file uploads**: Modules do not support file management This design keeps modules focused and portable—they rely on the parent test for variable definitions and file resources while still being able to extract and pass data through API calls. **Common use cases:** * Standard navigation sequences * Common setup or teardown operations * Shared API authentication workflows * Repeated multi-step interactions ### Trigger Run Trigger Run steps execute another Docket test from within your current test. Useful for dependent tests—e.g., a "Create Account" test that triggers a "Login" test, passing the credentials via variable mapping. **Key features:** * **Trigger any test**: Select another test in your workspace to run as a step * **Variable mapping**: Pass variables from the current test to the triggered test, allowing data to flow between tests * **Run skipped tests**: Trigger Run is the programmatic way to execute tests with [Suite Run Behavior](#suite-run-behavior) set to "Skipped" Trigger Run Configuration ### Lifecycle Hooks Lifecycle hooks allow you to attach optional [modules](#modules) that run automatically at specific points in your test execution. Configure these in the "Lifecycle Hooks" tab of your test. **Setup Hook**\ Runs after any account login (if configured) and before the first test instruction. Perfect for creating test resources via [API steps](#api-steps) and storing their IDs in variables. **Teardown Hook**\ Runs after the test completes, regardless of whether it passed or failed. Ideal for cleaning up resources created during the test. The most powerful use of lifecycle hooks is pairing setup and teardown modules with [API steps](#api-steps): 1. **Setup module**: Create resources via API POST requests, extract their IDs to variables (e.g., `@test_user_id`, `@order_id`) 2. **Test**: Use these resources in your UI test flow by referencing the variables 3. **Teardown module**: Delete the resources via API DELETE requests using the stored IDs This pattern ensures each test run starts with a clean environment and doesn't leave behind test data, making your tests fully isolated and repeatable. ## Test Variables Variables can be created in the Variables tab and referenced in test instructions using `@variable_name` syntax. Test-level variables take precedence over [suite-level variables](/essentials/test-suite#variables). Screenshot 2025-07-17 at 4.18.22 PM.png ### Text Variables Static values that remain constant throughout test execution. Ideal for credentials, product names, or configuration values. ### Dynamic Variables Generate pseudorandom strings with configurable length and character sets. Perfect for unique usernames, product IDs, or any data requiring uniqueness. ### Email Variables Choose a [plus address](/essentials/dedicated-mailboxes#plus-addresses) configured in your Email Settings, or generate a unique random address per test run. The agent can monitor these addresses for incoming emails—perfect for verification codes, magic links, and OTPs. ### Extracted Variables Created dynamically by capturing data from API responses using JSON Path (from response body) or directly from response headers. Use these to store auth tokens, resource IDs, or session identifiers. See [API Steps](#api-steps) for examples. ## Advanced Test Configuration Configure additional settings to fine-tune your test execution behavior. Advanced Test Configuration ### Browser Zoom Level Control the browser's zoom level (equivalent to `Ctrl +/-` in Chromium). Useful for testing responsive design and accessibility. **Options:** 50%, 75%, 100% (default), 125%, 150%, 200% ### Test Retries Configure automatic retries when a test fails. Docket will re-run the entire test from the beginning. **Options:** No retries (default), 1-3 retries ### Suite Run Behavior * **Included** (default): Test runs in all scenarios * **Skipped**: When a test suite is triggered to which this test belongs, this test is skipped and not run. The only way to run this test is via a [Trigger Run](#trigger-run) step or manually through the UI ### Persist Self-Healed Actions When enabled, if the AI agent self-heals a recorded step during test execution (e.g., because a button moved), the updated action automatically replaces the original in your test definition. This keeps your tests up to date as your UI evolves without manual re-recording. **Options:** Disabled (default), Enabled ### File Download Behavior Controls how the agent handles files downloaded during a test (e.g., CSV exports, PDF reports). * **Save Only** (default): The file is saved but its contents are not read * **Ingest Content**: The file is saved **and** its contents are extracted and injected into the agent's context, allowing subsequent assert steps to verify file contents This is particularly useful for testing export functionality — for example, asserting that a downloaded CSV contains the expected data. ### Typing Speed Set the delay between keystrokes in milliseconds. Range: 12ms–1000ms (default: 12ms). ### Two-Factor Authentication (2FA) Store TOTP secrets for automated 2FA during testing. Enter the secret key from your authenticator app setup, and Docket will automatically generate codes when prompted. # Test Suites Source: https://docs.docketqa.com/essentials/test-suite Test suites are a grouping of tests on Docket ### Test Suite Test suites are collections of tests on Docket. They are used to organize tests into logical groups that you might want to run together. > **Next Step**: After creating a test suite, you can [create individual tests](/essentials/test-creation) to add to the suite. ### Creating a test suite To create a test suite, navigate to the test suites tab. Screenshot 2025-07-17 at 3.52.48 PM.png From there, click the "New Test Suite" button and give your test suite a suitable name. Screenshot 2025-07-27 at 4.03.55 PM.png ### Accounts Think of accounts as username and password configurations that Docket uses to log in. You can assign accounts to test suites, which will then use that account to authenticate for all tests in the suite. Docket will navigate to the provided URL and log in with the credentials. The browser state (cookies, local storage) that results from this login will be copied as the starting point for all other test runs. Screenshot 2025-07-17 at 3.59.28 PM.png You can then assign this account as the login module for any test suite: Screenshot 2025-07-17 at 3.59.56 PM.png ### Region Select the geographical region where your tests will execute. Choose a region close to your servers for best performance and lower network latency. ### Notifications Configure email, Slack, or webhook [notifications](/essentials/notifications) for test results. ### Variables Define key-value pairs at the suite level and reference them in test steps using `@variable_name` syntax. Mark random or email variables as **fixed** to share the same generated value across all tests in a suite run. ### Agent Rules Add suite-level [agent rules](/essentials/agent-context) that apply to all tests in the suite. These are combined with your company-wide rules. ### Scheduling a Test Suite You can also schedule all tests in a given test suite to run at regular intervals. See the [scheduling section](/essentials/running-test#scheduling-a-run) in the Running a Test guide for instructions on how to set this up. **Related Pages:** * [Creating a Test](/essentials/test-creation) - Learn how to add tests to your suite * [Running a Test](/essentials/running-test) - Different ways to execute your tests # Triggering Tests Source: https://docs.docketqa.com/essentials/triggering-tests Different ways to trigger test runs on Docket ### Overview Beyond [manual runs and scheduling](/essentials/running-test), Docket provides several ways to trigger tests programmatically or chain tests together. *** ### API Trigger You can trigger test runs via the Docket API. This is useful for integrating Docket into custom workflows, deployment scripts, or automation pipelines outside of GitHub Actions. **Trigger a test suite:** ```bash theme={null} curl -X POST https://api.docketqa.com/test_group_run/trigger_run \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"test_blueprint_category_id": "SUITE_ID"}' ``` **Trigger specific tests by ID:** ```bash theme={null} curl -X POST https://api.docketqa.com/test_group_run/trigger_run \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"test_blueprint_ids": [1, 2, 3]}' ``` You can find your API key on the CI/CD page in the Docket dashboard. For GitHub-based CI/CD workflows, see the [CI Integration](/essentials/ci-integration) guide. *** ### Trigger Run Step (Test Chaining) A **Trigger Run** step lets you execute another test as part of the current test flow. This is useful for composing complex end-to-end scenarios from smaller, reusable tests. To add a trigger run step: 1. Click **Add Step** in the test editor 2. Select **Trigger Run** 3. Choose the target test to execute trigger_test_picker.png #### Variable Mappings When triggering another test, you can map variables from the current test to the target test's variables. This lets you pass data between tests — for example, passing a generated user ID from a registration test into a login test. variable_mapping.png Each mapping connects a **source variable** (from the current test) to a **target variable** (in the triggered test). Email variables in the target test require email variable sources. *** ### Suite Run Behavior Individual tests can be configured to require an explicit trigger rather than running as part of a suite. This is configured in the test's [Advanced Settings](/essentials/test-creation#advanced-test-configuration): * **Always Run** (default) — The test runs whenever its parent suite is triggered * **Require Individual Trigger** — The test is skipped during suite runs and must be triggered on its own Tests marked as "Require Individual Trigger" display an orange badge in the test list. They can still be triggered individually via the play button, the API, or as a target of a Trigger Run step. # Docket Tunnel Source: https://docs.docketqa.com/essentials/tunnel Test your local development environment with Docket ### Overview The Docket Tunnel lets you run tests against your local development environment—across **Web, iOS, and Android**—without exposing it to the public internet. Only your authenticated Docket account can access the proxied services. If your laptop can hit it, Docket can test it. ### Install the CLI Download and install the Docket CLI from our official distribution: ```bash theme={null} curl -fsSL https://api.docketqa.com/tunnel/install | bash ``` Add the CLI to your PATH: ```bash theme={null} export PATH="$HOME/.docket/bin:$PATH" ``` > **Tip**: Add the export line to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.) to make it permanent. ### Authenticate Link the CLI to your Docket account. This account will be the only one with access to services exposed over the tunnel: ```bash theme={null} docket auth ``` ### Start the Tunnel Start the tunnel to automatically proxy traffic to your local services: ```bash theme={null} docket start ``` While the tunnel is running: * Your local services are accessible from within your authenticated Docket account * Resources are **not** accessible from the public internet or any other Docket account * Press `Ctrl+C` to stop the tunnel ### Pointing Tests at Your Tunnel * **Web**: set the test's **URL** to your local address (e.g. `http://localhost:3000`). * **iOS / Android**: apps that already talk to a private host just work. To jump to a private web app, use a **Deep Link** step. iOS test using a localhost deep link through the Docket tunnel # Webhooks Source: https://docs.docketqa.com/essentials/webhooks Receive real-time notifications about test events via webhooks Webhooks allow you to receive real-time notifications about test events. Configure your webhook URL, shared secret, and event subscriptions in your company settings. Screenshot 2025-07-18 at 3.46.46 PM.png ## Supported Events * **Test Group Run Passed**: All tests in the group completed successfully * **Test Group Run Failed**: One or more tests failed or encountered errors * **Test Group Run Stopped**: Test group run was manually stopped ## Security & Verification All requests are signed with HMAC-SHA256. The `X-Docket-Signature` header contains: ``` X-Docket-Signature: v1,t=1640995200,s=a2114d57b48eac2b0fc35c4c4b4d5a8c... ``` To verify: 1. Extract timestamp `t` and signature `s` from the header 2. Create signed payload: `{timestamp}.{raw_request_body}` 3. Compute HMAC-SHA256 using the shared webhook secret 4. Compare with provided signature ```python Python theme={null} import hashlib import hmac def verify_webhook_signature(secret_hex: str, signature_header: str, raw_body: bytes) -> bool: try: parts = signature_header.split(',') timestamp = int(parts[1].split('=')[1]) provided_signature = parts[2].split('=')[1] signed_payload = f"{timestamp}.{raw_body.decode()}" key = bytes.fromhex(secret_hex) expected_signature = hmac.new(key, signed_payload.encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(provided_signature, expected_signature) except: return False ``` ```javascript Node.js theme={null} const crypto = require('crypto'); function verifyWebhookSignature(secretHex, signatureHeader, rawBody) { try { const parts = signatureHeader.split(','); const timestamp = parseInt(parts[1].split('=')[1]); const providedSignature = parts[2].split('=')[1]; const signedPayload = `${timestamp}.${rawBody}`; const key = Buffer.from(secretHex, 'hex'); const expectedSignature = crypto .createHmac('sha256', key) .update(signedPayload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(providedSignature, 'hex'), Buffer.from(expectedSignature, 'hex') ); } catch { return false; } } ``` ## Payload Schema ```json theme={null} { "event": "test_group_run_passed", "payload": { "id": 12345, "url": "https://app.docketqa.com/dashboard/grouprun/12345", "name": "API Integration Tests", "status": "passed", "created_at": "2024-01-15T10:00:00Z", "updated_at": "2024-01-15T10:30:00Z", "tests_ran": 15, "tests_passed": 15, "tests_failed": 0, "tests_stopped": 0, "github_context": { "ref": "refs/heads/feature/user-authentication", "commit_sha": "a7b8c9d1e2f3456789abcdef0123456789abcdef", "repository": "acme-corp/web-app" }, "tests": [ { "id": 67890, "url": "https://app.docketqa.com/dashboard/testrun/67890", "name": "User Login Flow", "status": "passed", "created_at": "2024-01-15T10:00:00Z", "updated_at": "2024-01-15T10:05:00Z", "error_message": null } ] } } ``` ### Key Fields * `event`: Event type (`test_group_run_passed`, `test_group_run_failed`, `test_group_run_stopped`) * `payload.status`: Test group status (`passed`, `failed`, `stopped`) * `payload.tests`: Array of individual test results * `payload.tests_*`: Count of tests by status * `payload.github_context`: GitHub context information (only present during CI/CD runs) * `ref`: Git reference (branch/tag) * `commit_sha`: Commit SHA hash * `repository`: Repository name ## Requirements * Respond with HTTP 200-204 within 10 seconds * Use HTTPS endpoints only * Handle duplicate deliveries using `X-Docket-Idempotency-Key` header # Quickstart Source: https://docs.docketqa.com/quickstart Getting started with writing your first test on Docket ### 1. Create a New Test Suite with Tests * Create a new [test suite](/essentials/test-suite). * Create a [new test](/essentials/test-creation) and give Docket a testing prompt for a flow you would like to see tested. * Learn about [AI Steps](/essentials/ai-steps) and [Recorded Steps](/essentials/recorded-steps) to understand how to build effective tests. * Testing a native iOS or Android app? See the [Mobile Apps](/essentials/mobile-apps) guide for how to upload your first build and point a test at it. ### 2. Add Agent Rules (Optional) * Help the agent understand app-specific behavior via [agent rules](/essentials/agent-context). ### 3. Run the Test * [Run the test](/essentials/running-test) manually, schedule it, or build a [CI/CD integration](/essentials/ci-integration). ### 4. Review the Results * Tests return a clear pass/fail outcome * If failed, Docket gives a concise reason why—based on real usability criteria *** 💡 **Note**: Docket fails fast. If a real user would be confused, blocked, or slowed down, the test fails by design. **Next Steps:** * [Creating a Test](/essentials/test-creation) — Deep dive into test creation * [AI Steps](/essentials/ai-steps) — Learn about natural language test instructions * [Recorded Steps](/essentials/recorded-steps) — Understand coordinate-based actions * [Bulk Create](/essentials/bulk-create) — Import existing test cases from documents * [Generate Tests](/essentials/generate-tests) — Use AI to generate tests from PRDs and screenshots Need help? Reach out to our team at [founders@docketqa.com](mailto:founders@docketqa.com). # Welcome to Docket Source: https://docs.docketqa.com/welcome AI agent for testing your web, iOS, and Android apps Welcome to **Docket**, your AI-powered QA testing agent. Docket simulates real user behavior to identify broken flows, confusing UX, and unresponsive elements—so you can catch issues before your users do. With Docket, you can: * Run end-to-end tests using intelligent agents * Test across **web**, native **[iOS, and Android](/essentials/mobile-apps)** — on real browsers, iOS simulators, and Android emulators * Automatically catch poor UX, not just broken buttons * Create flows by clicking through your app—no coding needed * Add app-specific guidance through agent rules * Get structured bug reports with failure reasons Docket doesn't just ask "does it work?" It asks, "would a real user succeed?" *** ### Getting Started Ready to start testing? Check out these guides: * **[Quickstart](/quickstart)** — Get up and running in minutes * **[Creating a Test](/essentials/test-creation)** — Build your first test * **[AI Steps](/essentials/ai-steps)** — Write natural language test instructions * **[Recorded Steps](/essentials/recorded-steps)** — Use precise coordinate-based actions * **[Test Suites](/essentials/test-suite)** — Organize and manage your tests * **[Mobile Apps](/essentials/mobile-apps)** — Test native iOS and Android apps on dedicated simulators ### Scaling Up * **[Bulk Create](/essentials/bulk-create)** — Import test cases from documents * **[Generate Tests](/essentials/generate-tests)** — Use AI to generate tests from PRDs and screenshots * **[Folders](/essentials/folders)** — Organize tests into a hierarchy * **[Triggering Tests](/essentials/triggering-tests)** — API triggers, test chaining, and automation