# What BitAssure is BitAssure checks that your website, Android app, iPhone app or API still does what it should. You walk through it once in a real browser or phone, and on each screen you say what should be true: the total reads $64.97, the Pay button is enabled, the welcome message is visible. BitAssure then walks the same path again whenever you ask, on a schedule, or from your CI pipeline, and tells you in your own words which of those things stopped being true. There is no test code to write. A run gives you a pass or fail for every check, a video with each check marked at the moment it was judged, a PDF report anyone can read, and JUnit XML for your pipeline. ## The words BitAssure uses | Word | What it means | |---|---| | **Project** | One product of yours, such as "Storefront" or "Retail Bank". | | **Platform** | One place that product runs: its website, its Android app, its iPhone app or its API. A project has at most one of each. Older screens call this a *target*. | | **Journey** | One flow through a platform that you record in one go, such as "Sign in" or "Send money". On an API it is called a *flow*. | | **Scenario** | One stop along a journey: the screen you reached and what should be true on it. A journey is a series of scenarios. | | **Step** | One thing done on the way: a click, typing into a field, a scroll. Steps are recorded, never written by hand. | | **Check** | One thing that should be true, said about one element: "Confirm is enabled". A check either holds or it does not. | | **Run** | One walk through a journey (or every journey on a platform) with every check judged. A run ends as passed, failed or error. | | **Credit** | What everything is paid in. A website or API run is 1 credit. A phone is charged by the minute. | ## How it fits together ``` Project: Storefront ├── Platform: Website (https://shop.example.com) │ ├── Journey: Sign in │ │ └── Scenario: Verify Accounts ← checks: "Balance is visible", … │ └── Journey: Checkout (starts where Sign in ends) │ ├── Scenario: Verify Basket │ └── Scenario: Verify Payment └── Platform: Android app (shop.apk) └── Journey: Sign in ``` A journey can start where another one ends. Record "Sign in" once, and "Checkout" begins already signed in, without you recording the sign-in again. ## Where to start - [Your first journey](/docs/getting-started) takes you from signing up to a first passing run. - [Recording a journey](/docs/recording) and [Checks](/docs/checks) cover the recorder in full. - [Running from CI](/docs/ci) and [The REST API](/docs/api) are for automating runs. ## For AI assistants BitAssure has an MCP server, so Claude Code, Cursor and other assistants can record, write and run journeys for you: see [AI assistants (MCP)](/docs/mcp). Every page here is also plain Markdown at `/docs/.md`, an index is at [/llms.txt](/llms.txt), and every page at once is at [/llms-full.txt](/llms-full.txt). --- # Your first journey This takes about ten minutes and uses a website. Phones and APIs work the same way once their platform is set up (see [Android and iPhone apps](/docs/mobile-apps) and [APIs and load testing](/docs/api-testing)). ## 1. Sign up Create an account at [bitassure.app](/signup) with Google, GitHub, or an email address and a password. Every new account starts with 50 free credits, which last 30 days. A website run costs 1 credit, so that is plenty to try everything here. No card is needed. If you signed up with an email address, BitAssure asks you to confirm it the first time you buy credits: it sends you a link, and once you have opened it you carry on where you were. To see a run before setting anything up, press **Try it on our demo shop** on the dashboard. It adds a sample project with a journey already recorded against a small shop of ours, runs it, and opens the result with its video and report. Demo runs are free (up to 20 a day) and stay off your dashboard. The demo is a website only and its address is fixed, so no phone app, API or other website can be added to it. You can practise recording on it, up to 3 journeys of 5 scenarios, but it cannot be scheduled. Your own app goes in a project of its own. You can also skip recording by hand: **Record with AI** on a journey shows how to connect Claude or another AI assistant, which then records the journey from your description (see [AI assistants](/docs/mcp)). ## 2. Create a project and a platform 1. On **Projects**, press **New project** and name it after your product. 2. Inside the project, press **New platform** and choose **Web** as the platform. 3. In **Base URL**, enter the website's address, for example `https://shop.example.com`, and press **Create**. Every recording starts here. ## 3. Record a journey 1. On the platform, press **New journey** and name it after what it does, for example "Sign in". 2. Press **Create and open**. The recorder opens a real Chrome on our side and shows you the page. 3. Click anything highlighted on the screen to choose it. The panel beside it shows what you can do with it: - **Events** move you through the app: **Click it**, **Type a value**, **Choose an option** and so on. Each one you use becomes a step. - **This should be…** adds a check: **Is visible**, **Is enabled**, **Reads exactly…**, **Contains…** and more (see [Checks](/docs/checks)). 4. Walk to the screen you care about and add a check or two there. For example, after signing in, choose the account name and press **Is visible**. ## 4. Save the scenario The **Scenario name** box, above the save buttons, already holds a suggestion such as "Verify Accounts", taken from the screen. Keep it or type your own. It is the heading this part of the report will have. - **Save and continue** saves this scenario and lets you carry on to the next screen in the same journey. - **Save and end** saves it and closes the recorder. Nothing is written until you save. Ending without saving leaves the journey as it was. ## 5. Run it On the journey's page, press **Run journey**. BitAssure opens a fresh browser, walks your steps, judges each check where you added it, and records a video. A short journey takes well under a minute. The run page shows every check as a sentence that held or did not, with the video beside it. Press **Download report** for the PDF. ## 6. Make it run by itself - On the journey's **Schedule** tab, add a schedule: hourly, daily, on weekdays or weekly, at a time in your own time zone. If a scheduled run starts failing, everyone who has asked for it gets an email, and another when it passes again. See [Running and scheduling](/docs/running). - To run it from your pipeline after every release, create an API key and follow [Running from CI](/docs/ci). --- # Recording a journey A journey is recorded, never written. You use your app in the recorder the way a customer would, and BitAssure writes down each step and each check exactly as you made it. ## Opening the recorder - **A new journey:** on a platform, press **New journey**, name it, and press **Create and open**. - **Adding to a journey:** on the journey's page, press **Add more checks**. The recorder carries on from where the journey's last scenario ends. - **Editing one scenario:** on the journey's **Checks** tab, press **Edit** beside the scenario. See [Changing a journey](/docs/changing-a-journey). The recorder opens a real browser or phone on our side and shows it to you. A website opens at the platform's address. A phone opens your uploaded app. ## The recorder's parts - **The screen.** Everything you can act on is highlighted. Click one to choose it. **Look again** takes a fresh picture if the screen changed after the last one, for example after an animation finished. - **Selected element.** What you chose, and two groups of buttons: - **This should be…** adds a check about it (see [Checks](/docs/checks)). - **Events** act on it: **Click it**, **Type a value**, **Empty it**, **Choose an option**, **Set a date**, **Double-click**, **Press and hold**, **Wait for it**, drag, scroll inside it, and more. Rarer ones are under **Everything else you can do**. - **Move the screen.** Actions that need no element: **Back**, **Scroll down**, **Scroll up**, **Scroll until you see…**, **Press Enter**, **Press Tab**, **Press Escape**, and the pop-up answers **Accept the pop-up**, **Dismiss the pop-up** and **Type into the pop-up**. Phones add swipes, **Turn sideways** and **Put the keyboard away**. Websites add **Leave the frame** and **Go to the new window**. - **Steps.** The scenario's steps with its checks written in between, in the order you made them. Steps that got you here from earlier scenarios are folded away at the top. Remove a step with its **×** and the recorder walks the app again without it. - **Scenario name** and the save buttons, at the bottom. ## Values you type When an action needs a value, such as text to type, an option to choose or a date, the recorder asks for it in a small window. Dates are stored as a date (for example 15 October 2026), never as typed, so the same step means the same date on every machine and phone. Do not record real passwords or personal data you would not want in a report. Use a test account. ## Scenarios: where to stop A scenario ends when you say so, never when the app moves. Stop at each screen where something should be checked: 1. Walk to the screen. 2. Add the checks that should hold there. 3. Check the **Scenario name**. It starts as "Verify" followed by the screen's own name, for example "Verify Checkout", and follows the screen until you type over it. 4. Press **Save and continue** to carry on to the next screen, or **Save and end** to finish. Nothing is written until you save. **End** at the top asks whether to save or discard anything unsaved. Discarding leaves the journey exactly as it was. ## A check is judged where you added it Each check is judged at its place in the walk, not at the end of the scenario. "Confirm is enabled" added before you typed an amount and the same check added after it are two different claims, and a run judges each one at the point you made it. ## Journeys that start where another ends On the journey's page, under **Runs first**, press **Add a prerequisite** and choose another journey, such as "Sign in". From then on: - the recorder walks the prerequisite first and starts you where it ends, already signed in - a run walks the prerequisite first too, and a failure there is reported as a failure there The prerequisite is recorded once and shared by every journey that needs it, so a change to the sign-in page is fixed in one place. ## Several scenarios on a phone Before a run walks a scenario from its first step, it starts over: on Android it clears the app's data, on an iPhone it closes and reopens the app, and on a website the browser forgets its cookies and anything the site saved, so a scenario recorded signed out is never walked by a browser that is still signed in. A run of a whole platform does this before every scenario after the first, because each one starts from the beginning. The run page says when it did this, so the video showing a fresh start is never a surprise. ## What recording costs The browser or phone is ours while the recorder is open, so recording is charged by the clock: | Platform | While the recorder is open | |---|---| | Website | 1 credit per 10 minutes | | Android or iPhone | 1 credit per minute | Charging starts only once the browser or phone is ready, so one that never comes up costs nothing. If you stop using it, the recorder asks "Still using it?" after two minutes and switches the browser or phone off if nobody answers. Closing the tab does the same a few minutes later. Your unsaved draft is kept for 24 hours: open the recorder again and **Carry on** opens a new device and walks your draft's steps again. Running out of credits switches it off the same way, keeping the draft. An account can have two recorders open at once. --- # Checks A check is one thing that should be true about one element on a screen. It is written as a sentence, and a run reports it as holding or not, in the same words. ## Kinds of check Choose an element in the recorder, then press one of these under **This should be…**: | Button | The sentence it makes | Holds when | |---|---|---| | **Is visible** | Pay should be visible | The element is on the screen and can be seen. | | **Is enabled** | Pay should be enabled | The element can be used, not greyed out. | | **Reads exactly…** | Total should read "$64.97" | Its text is exactly this. | | **Contains…** | Message should contain "Thank you" | Its text includes this, anywhere. | | **Attribute is…** | Email's placeholder should be "you@example.com" | A named attribute of the element has this value. | | **Is on** | Remember me should be on | A switch or checkbox is on. | | **Is off** | Newsletter should be off | A switch or checkbox is off. | **Is on** and **Is off** read the switch the way each platform keeps it: Android's checked state, an iPhone switch's value, a website checkbox or anything marked `aria-checked`. Used on something that is not a switch, the check fails and says so. APIs have their own kinds of check, about status codes, response bodies and response times. See [APIs and load testing](/docs/api-testing). ## Where a check is judged A check is judged at the point in the walk where you added it, after the screen has settled. If you removed steps after adding it, it is judged at the nearest point that still exists. ## When a check does not hold The run reports the check's sentence with the reason it did not hold, such as: > Total should read “$64.97”. Found “$64.98” instead. or, when the element was not there at all: > Pay should be visible. Couldn't find this on the screen. A check that does not hold fails the run, but the run carries on to the screens after it, so one failure never hides another. A step that cannot be done, such as a click on a button that no longer exists, is different: the walk cannot continue past it, so the screens after it are reported as not reached. ## Writing good checks - **Check outcomes, not decoration.** "Order confirmed is visible" and "Total reads $64.97" say the app worked. A check on a logo mostly tells you about the logo. - **Check text with Contains when it varies.** "Contains 'Welcome'" survives "Welcome back, Thabo" and "Welcome back, Neo". - **Avoid values that change every run,** such as today's date or an order number. Check that the element is visible instead. - **Use a test account whose data stays put,** so a balance or a basket total reads the same every time. --- # Changing a journey Apps change. When a check fails because the app moved on rather than broke, the check is what needs changing, and BitAssure lets you change it without recording the journey again. ## The Checks tab A journey's **Checks** tab lists its scenarios in order, each with its steps and its checks between them. Beside each scenario: - **Fix this** appears beside a check that failed in the last run. It opens that check so you can point it at the right element or correct what it expects. - **Change** opens a check that passed, or has not run yet, for the same edits. - **Edit** opens the recorder at that scenario, to re-record its steps or add checks. ## Pointing a check at the right element When a developer renames or moves something, a check can end up pointing at nothing. **Point it at the right element** lets you choose the element again. The check keeps its wording and its history, and so does every other check on that element. ## Changing what a check expects Open the check and change its value, for example when a price changed on purpose. Where the check sits in the walk is not changed here, because "Confirm is enabled" before typing and after typing are two different claims. To move a check, edit the scenario in the recorder. ## Screens after a failed step If the last run stopped at a step it could not do, the screens after it never ran. They are shown as locked, with the reason, because there is nothing known about them to fix. Fix the scenario where the run stopped, run the journey again, and the rest opens up. ## Editing a scenario in the recorder Press **Edit** beside a scenario. The recorder walks you to it and opens it as a draft: - saving updates that scenario in place, keeping its checks and its run history - the scenarios after it are kept and carry on from your new version - ending without saving leaves it as it was ## Archiving and deleting From the journey's **⋯** menu: - **Archive this journey** puts it away. It stops running, leaves the journey lists and the dashboard, and its schedules record why they stopped. Its runs and reports stay readable, and it can be restored. - **Delete permanently** removes the journey, its scenarios, its checks and every run of it with its reports. This cannot be undone. Credits already spent are not affected. If a platform's address changes, for example from staging to production, change it with **Change address** on the platform. Recorded steps that start with the old address move to the new one, and BitAssure tells you how many it moved. --- # Running and scheduling ## Ways to start a run | From | Press | Runs | |---|---|---| | A journey's page | **Run journey** | That journey, after any journeys it needs first. | | A platform's page | **Run all** | Every journey on the platform, each as its own run. You can also tick some journeys and run just those. | | A project's page | **Run everything** | Every journey on every platform of the project. | | Your pipeline or a script | the [REST API](/docs/api) | Any journey or platform, with an API key. See [Running from CI](/docs/ci). | | A schedule | nothing, it starts itself | What the schedule points at. | A run walks the journey in a fresh browser or phone, judges each check where it was added, and records a video. Archived journeys are never run. ## How a run ends | Result | Means | Charged | |---|---|---| | **Passed** | Every check held. | Yes | | **Failed** | At least one check did not hold, or the run stopped before the end (see below). | Yes | | **Error** | The run measured nothing: the browser or phone never came up, or something on our side broke. | No. The credits come back automatically. | A failed run is a result, and usually the one you most needed, so it is charged like a pass. An error is our problem, not your app's, so it is never charged. ## Run limits A run may take up to **10 minutes on a website or API** and **15 minutes on a phone**. A run that is still going then has almost always met an app that stopped answering. It stops before its next screen, keeps everything it measured and its video, and is reported as **failed**, with the screen it stopped at named on the run page and in the PDF. A phone run also stops when the account's credits run out, in the same way. Each account runs **two runs at once** (four on Monthly credits). More wait their turn, and nobody else's runs wait for yours. ## What a run costs | Platform | Cost | |---|---| | Website | 1 credit a run | | API | 1 credit a run | | Android or iPhone | 1 credit per minute of phone time, at most 15 | | Load test | 1 credit per 50 virtual-user-minutes | The credits are taken when the run starts, so a queue of runs cannot spend more than you have. A phone run first holds what it expects to need, based on the last run of the same journey (10 minutes when there is no history), and gives back what it did not use when it finishes. Phone time is counted from when the phone is ready with your app installed, not while one is being found. The journey page shows what a run will cost before you press Run. See [Credits and billing](/docs/credits). ## Schedules A schedule runs a journey, a whole platform, or an API flow under a load profile, by itself. Add one on the **Schedule** tab of a journey, or the **Schedules** tab of a platform. **How often** is one of: - **Hourly**, at a chosen number of minutes past the hour - **Daily**, at a chosen time - **Weekdays**, Monday to Friday at a chosen time - **Weekly**, on a chosen day at a chosen time Times are in the schedule's own time zone and stay right when the clocks change. Every plan can schedule. A scheduled run costs the same as one started by hand. A schedule that comes due and cannot run says why on the schedule and on the dashboard, rather than quietly skipping: - the previous run is still going, so this one is skipped to keep the two from measuring each other - the account is out of credits - BitAssure was down at that moment and the time passed more than an hour ago (missed runs are not piled up and run late) **Schedules** in the sidebar lists every schedule in the account. ## Being told A scheduled run emails the account's members when a journey **starts failing** and again when it **passes again**, never every night it stays the same. A schedule that could not run emails once. Each person can switch these emails off under **Settings → Your account → Mail me about scheduled runs**. Runs started by hand or from CI do not email; your pipeline already tells you. --- # Reading a run ## The run page Every run has its own page, reached from **Runs** in the sidebar, from a journey's **Runs** tab, or from the link in a CI job or an email. It shows: - **The verdict:** passed, failed or error, how long it took, who or what started it. - **Each scenario as a section,** headed by its name, with every check as a sentence that held or did not. A check that did not hold says why. A button above the list narrows it to the scenarios that failed. - **The video,** with each check marked at the moment it was judged. Click a check to jump to that moment. - **Where it stopped,** if it did not reach the end, naming the screen and the reason. A run on a phone in our device lab gets its video a minute or two after it ends. Until then the page says the recording is being prepared. ## The PDF report **Download report** gives a PDF anyone can read without an account: a run, a whole platform's latest results, or a whole project's. It names every journey and scenario, including ones that have not run yet, so "all checks passed" never quietly means "half of it was never checked". ## Since when A journey's page and the dashboard show its last 14 runs as a strip of marks, oldest to newest. A one-off blip, a flaky check that comes and goes, and a break that has been red since Tuesday each look different, and the dashboard says it in words: "Checkout has been failing for 8 days". ## The dashboard The dashboard leads with what is true now: how many journeys are passing as of their latest run. Below it: - **What did not hold:** every failing check in the words it was written in - **Since when:** each journey's recent runs - **What the green does not cover:** journeys with no checks, journeys that have never run, and schedules that came due and did not produce a run ## In words A journey's **In words** tab reads it as Given, When and Then, generated from what you recorded: the steps that lead to each scenario, the steps within it, and its checks. It is a readable summary for people who will never open the recorder. ## For pipelines Every run is also available as JUnit XML, the results file every CI system reads, with each check as a test case named by its sentence. See [Running from CI](/docs/ci). ## How long reports are kept | Plan | Videos and screenshots kept | |---|---| | Pay as you go | 90 days | | Monthly credits | 1 year | The run itself, its results and its PDF are kept for as long as the journey exists. Only the video and screenshots age out. --- # Running from CI Check your app from a pipeline after every build or release. Every check shows up by name in the pipeline's own test tab, and the PDF report is kept with the build. Any CI that can run `curl` and `jq` works. ## 1. Create an API key 1. Go to **Settings → API keys** and press **Create key**. 2. Name it after where it runs, for example "GitHub Actions". 3. Copy the key. It starts with `ba_` and is shown once. An API key can start runs and read results, and nothing more: it cannot add members, delete anything or create more keys. Store it as a secret in your CI, never in the repository. See [The REST API](/docs/api). ## 2. Copy the step from BitAssure Under **Settings → API keys**, **Run from your pipeline** writes the step for you: 1. Choose the app. 2. Choose what to run: - **Everything in the app**: every journey on every platform. - **One platform**: every journey on it. - **Chosen journeys**: only the ones you tick. 3. Leave **Email the team when the result changes** ticked if you want to be told by email. 4. Choose your CI: GitHub Actions, GitLab CI, Azure Pipelines, Jenkins, or any shell. 5. Press **Copy** and paste the step into your pipeline. 6. Store the key as the secret the page names (`BITASSURE_KEY`, or the credential `bitassure-key` in Jenkins). Every id is already filled in. With **Everything** or **One platform**, BitAssure decides which journeys to run each time the step runs. A journey you record next week is included, and one you archive is left out, with no change to the CI file. ## What the step does 1. **Starts a pipeline run.** `POST /api/pipeline-runs` starts one run for each journey and answers at once. If nothing can start, the step fails and prints BitAssure's reason. For example: "This pipeline run costs 3 credits and this account has 1. Top up to run it." 2. **Waits for it.** It asks `GET /api/pipeline-runs/{id}` every 15 seconds until `finished` is true, for up to 90 minutes. 3. **Fetches the results.** `GET /api/pipeline-runs/{id}/junit.xml` is one results file with a test suite per journey. Your CI's test tab reads it. 4. **Keeps the report.** `GET /api/pipeline-runs/{id}/report.pdf` is one PDF. It opens with a page saying what ran and how each journey did, followed by each run's own report. The step saves it with the build: as an artifact in GitHub Actions and GitLab, and in the published artifacts in Azure and Jenkins. 5. **Passes or fails the build.** The step fails unless every journey passed. It also prints each journey's result with a link to its run. ## Being told by email When **Email the team when the result changes** is on, BitAssure mails the account's members: - once when the pipeline starts failing, saying which checks did not hold - once when it passes again Each email has the PDF report attached. Nothing is sent while the result stays the same, so a broken build does not mean an email on every push. The comparison is with the previous pipeline run of the same thing (the same app, platform or set of journeys). Anyone can switch these emails off under **Settings → Your account**. ## The request, for writing your own ```bash curl -X POST https://api.bitassure.app/api/pipeline-runs \ -H "Authorization: Bearer $BITASSURE_KEY" -H 'Content-Type: application/json' \ -d '{"projectId":"…","notifyOnChange":true,"triggeredBy":"CI"}' ``` Name exactly one of `projectId`, `platformId` or `journeyIds` (a list, at most 100). The answer, and `GET /api/pipeline-runs/{id}` afterwards, carries: - `status`: `PENDING`, `RUNNING`, `PASSED`, `FAILED` or `ERROR` - `finished` - `runs`: each with its journey, status and a link to its page - `skipped`: journeys that could not be started and why, for example one with nothing recorded yet - where to fetch `junitUrl` and `reportUrl` The results file and the PDF answer 409 until every run has finished. ## The results file - Each journey's run is a test suite, named after the app, journey and platform. - Each check is a test case. Its class is the scenario name, and its name is the check's sentence, such as "Total should read “$64.97”". - A failed check carries its reason as the failure message. - A run that stopped before the end adds one failing case saying where, because the checks after it never ran. - An errored run is a single error, not a list of passes. - A `run` property links to the run's page, with its video and PDF. ## One run at a time The older single-run calls still work: `POST /api/journeys/{id}/runs` for one journey, then `GET /api/runs/{id}` and `GET /api/runs/{id}/junit.xml`. A journey's id is the last part of its address in BitAssure. ## Costs and limits A pipeline's runs cost the same as any other run, and come out of the same prepaid credits, so a pipeline can never spend more than the account holds. BitAssure checks that the account can pay for every journey before starting any, so you never get a half-run pipeline that looks green. Runs count towards the account's runs at once (two, or four on Monthly credits). A pipeline with more journeys than that runs them in turn. --- # The REST API Everything the BitAssure portal does goes through a REST API at `https://api.bitassure.app`. With an API key, a script, a pipeline or an AI assistant can start runs and read their results. ## Authentication Create a key under **Settings → API keys** (it starts with `ba_` and is shown once), and send it as a bearer token: ``` Authorization: Bearer ba_your_key ``` An API key acts as a **tester**: it can read everything in the account and start runs, but cannot add or remove members, create keys, delete apps or close the account. Revoke a key on the same page; it stops working at once. ## Finding ids Every project, platform, journey and run has an id, which is the last part of its address in the portal: | Page | Address | |---|---| | Project | `https://bitassure.app/projects/{projectId}` | | Platform | `https://bitassure.app/targets/{platformId}` | | Journey | `https://bitassure.app/journeys/{journeyId}` | | Run | `https://bitassure.app/runs/{runId}` | Or list them through the API: ``` GET /api/projects/{projectId}/targets the project's platforms GET /api/targets/{platformId}/journeys a platform's journeys GET /api/targets/{platformId}/runs?size=25 a platform's runs, newest first (paged) ``` ## Starting a run ``` POST /api/journeys/{journeyId}/runs one journey POST /api/targets/{platformId}/runs every journey on a platform, as one run Content-Type: application/json {"triggeredBy": "CI"} ``` `triggeredBy` is optional and is shown on the run as who started it. The answer is `201 Created` with the run, at once, while it waits its turn: ```json { "id": "4f3d927e-30fb-4d84-b02a-098c330948a7", "status": "PENDING", "kind": "FUNCTIONAL", "triggeredBy": "CI", "journeyId": "2abff37d-7c00-4a17-a5bd-9a9556c2a67e", "targetId": "647edf85-8fe2-48cf-a4b9-1ffe69a48a26", "createdAt": "2026-10-15T12:22:25.898914Z", "startedAt": null, "finishedAt": null, "stoppedBecause": null } ``` The credits are taken when the run is accepted. A run that errors gives them back. ### Several journeys as one ``` POST /api/pipeline-runs {"projectId": "…"}, {"platformId": "…"} or {"journeyIds": ["…"]} GET /api/pipeline-runs/{id} its status, and each run in it GET /api/pipeline-runs/{id}/junit.xml every run as one JUnit file GET /api/pipeline-runs/{id}/report.pdf a cover page, then each run's report ``` A whole app or platform means the journeys that are there when it is started. Add `"notifyOnChange": true` to email the team when the result turns. This is what the CI step uses; see [Running from CI](/docs/ci). ## Following a run ``` GET /api/runs/{runId} ``` `status` moves from `PENDING` to `RUNNING` and ends as one of: | Status | Means | |---|---| | `PASSED` | Every check held. | | `FAILED` | A check did not hold, or the run stopped before the end. `stoppedBecause` then says where and why. | | `ERROR` | Nothing was measured, for example a browser or phone that never came up. Not charged. | Poll every 10 seconds or so. A run takes at most 10 minutes on a website or API and 15 on a phone. `GET /api/runs/{runId}/progress` says what it is doing right now, such as which screen it is checking. ## Reading the results ``` GET /api/runs/{runId}/results every check, as JSON GET /api/runs/{runId}/junit.xml the same as JUnit XML, for CI GET /api/runs/{runId}/report.pdf the PDF report GET /api/runs/{runId}/video the run's recording, as MP4 ``` Each result in `/results` reads: ```json { "passed": false, "scenario": "Verify Basket", "elementName": "Total", "ruleType": "TEXT_EQUALS", "expectedValue": "$64.97", "actualValue": "$64.98", "sentence": "Total should read “$64.97”", "reason": "Found “$64.98” instead", "evaluatedAt": "2026-10-15T12:22:33.068717Z" } ``` `sentence` and `reason` are the words a person reads on the run page and in the PDF. For an AI assistant reporting a failure, they are usually all that is needed. ## Reading a journey ``` GET /api/journeys/{journeyId} its name and settings GET /api/journeys/{journeyId}/feature the journey as Given, When and Then: its scenarios, their steps and their checks ``` ## Errors Every error answer is JSON with one sentence in `message`: ```json {"message": "Run on WEB costs 1 credit and this account has 0. Top up to run it."} ``` | Status | Means | |---|---| | `400` | The request was malformed, for example a missing field. | | `401` | No key, or a key that is wrong or revoked. | | `402` | Not enough credits. The message says how many are needed and how many are left. | | `403` | The key is valid but may not do this, for example deleting something. | | `404` | There is no such thing in this account. | | `409` | It cannot be done right now, for example the JUnit file of a run still in progress. | | `5xx` | Something went wrong on our side. Try again shortly. | ## Limits - The account's runs at once (two, four on Monthly credits) apply to API runs too. Extra runs wait their turn. - A key belongs to the account, not to a person, so runs it starts say "API key" followed by its name as who started them. ## Using BitAssure from an AI assistant The easiest way is the MCP server, which gives an assistant tools to run, record and write journeys directly: see [AI assistants (MCP)](/docs/mcp). An assistant with only a shell or HTTP tool can use this API instead: give it an API key and point it at this page, or at [/llms.txt](/llms.txt) for all the docs. --- # AI assistants (MCP) BitAssure has an MCP server, so an AI assistant such as Claude Code, Cursor or VS Code's Copilot can use it while you work. You can ask it to: - "Record a BitAssure journey on our staging site: sign in as the test user, add the blue T-shirt to the basket, and check the total is $24.99." - "I changed the checkout code. Run the Checkout journey and tell me what broke." - "What's failing this morning? Show me the screen where it failed." - "The total is $24.99 now, on purpose. Update the check." - "Write a BitAssure flow for our orders API from the routes in this repository, then run it." The assistant records, writes and runs journeys the same way you would in the portal. Everything it makes is an ordinary journey you can open, edit, schedule and report on. ## Connecting The server is: ``` https://api.bitassure.app/mcp ``` There are two ways in. A chat app such as claude.ai or ChatGPT **signs you in** with your BitAssure account, the way any "Sign in with" button works. A developer tool such as Claude Code, Cursor or VS Code can sign in the same way, or use an **API key**. ### claude.ai and the Claude apps 1. In Claude, open **Settings → Connectors** and choose **Add custom connector**. 2. Name it **BitAssure** and paste the server address above. Leave the advanced settings empty. 3. Press **Connect**. A BitAssure sign-in page opens: sign in, then press **Yes** to let Claude use BitAssure. Claude then works as you, in your account and with your role. The connection lasts 30 days, then Claude asks you to sign in again. Custom connectors are available on Claude's paid plans; on a Team or Enterprise plan an owner may need to add it first. ### ChatGPT In ChatGPT, turn on **developer mode** (**Settings → Apps & Connectors → Advanced settings**), then create a connector with the server address above and **OAuth** as its authentication. Sign in and allow it as above. ### With an API key Create a key under **Settings → API keys**, named after the assistant, for example "Claude Code". A key acts as a tester and belongs to the account rather than to a person, which suits a shared machine or a pipeline. ### Claude Code ``` claude mcp add --transport http bitassure https://api.bitassure.app/mcp \ --header "Authorization: Bearer ba_your_key" ``` ### Cursor In `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project): ```json { "mcpServers": { "bitassure": { "url": "https://api.bitassure.app/mcp", "headers": { "Authorization": "Bearer ba_your_key" } } } } ``` ### VS Code In `.vscode/mcp.json`: ```json { "servers": { "bitassure": { "type": "http", "url": "https://api.bitassure.app/mcp", "headers": { "Authorization": "Bearer ba_your_key" } } } } ``` Claude Code can also sign in instead: leave out `--header`, then type `/mcp` in Claude Code and choose **Authenticate**. ### Other assistants Any assistant that supports remote MCP servers over HTTP works: with an `Authorization: Bearer` header holding a key, or by signing in (MCP's OAuth sign-in) where the assistant offers it. Keep the key out of files you commit. Most assistants can read it from an environment variable instead. ## What the assistant can do ### Set up an app | Tool | Does | |---|---| | `create_project` | Creates a project, one product of yours such as "Storefront" | | `add_platform` | Adds a website or an API to a project, at its address. Phone apps need their build uploaded in the portal. | Both need an admin or owner, as in the portal, so they work when the assistant is signed in as one. A key acts as a tester and is refused. ### Run and read | Tool | Does | |---|---| | `list_journeys` | Every project, platform and journey, with ids and each journey's latest result | | `describe_journey` | A journey in words: its scenarios, steps and checks | | `run_journey` | Starts a run of a journey or a whole platform. **Spends credits.** | | `wait_for_run` | Waits up to 50 seconds for a run to finish; the assistant calls it again until it has | | `get_run` | A run's result: what did not hold and why, where it stopped, and its link | | `recent_runs` | A journey's latest runs, to answer "since when has this been failing?" | | `failing_now` | Across the account: what is failing and since when, every check that did not hold, and what nothing covers | | `failure_picture` | The screen at the moment a check failed, taken from the run's video | ### Look after journeys | Tool | Does | |---|---| | `change_check` | Changes what a saved check expects, keeping its history: for when the app changed on purpose | | `repoint_check` | In a recording, points a check at the element as it is now, when it moved or was renamed | | `set_runs_first` | Makes a journey start where others end, such as after "Sign in", so no password is typed again | `describe_journey` lists each scenario's and check's id, which these take. ### Record a website or phone journey | Tool | Does | |---|---| | `start_recording` | Opens the recorder on a real browser or phone: a new journey, more of an existing one, or one saved scenario to edit. `starts_after` makes it begin where another journey ends. | | `look` | The screen now: its address, a numbered list of what is on it, and a picture | | `act` | One step: click, type, choose, scroll, swipe, answer a pop-up and so on, on element N | | `add_check` | Something that should be true about element N: visible, enabled, reads, contains, attribute, on, off | | `remove_step`, `remove_check` | Undo a step or a check | | `save_scenario` | Saves what was recorded since the last save as a scenario, such as "Verify Basket" | | `finish` | Saves or throws away anything unsaved and frees the browser or phone | The assistant picks elements by their number on the screen. BitAssure still decides how to find each element again on the next run, so a journey recorded this way is as sturdy as one you record yourself. ### Write an API flow | Tool | Does | |---|---| | `create_flow`, `show_flow` | Start a flow on an API platform, or show one with its ids | | `add_call`, `change_call`, `remove_call` | The calls, in order, with headers, body and `{{values}}` | | `try_call` | Sends one call and shows the answer. Free. | | `add_check_on_answer`, `remove_check_on_answer` | What each answer should be: status, time, body, a JSON value, a header | | `carry_value`, `remove_carried_value` | Take a value from one answer for later calls, such as a token | See [APIs and load testing](/docs/api-testing) for what each check and placeholder means. ## Watching it record When the assistant starts a recording, it gives a link to the recorder in the portal. Open it and you see the same browser or phone, with each step and check appearing as the assistant makes it. You can take over at any point: what you do and what the assistant does go into the same recording. ## What it costs The same as anything else: a website or API run is 1 credit, a phone run 1 credit a minute, and the recorder is charged by the clock while it is open (1 credit per 10 minutes on a website, 1 a minute on a phone). An assistant is slower than a person, so recording a phone through one costs more than recording it yourself. `run_journey` is marked as spending, so most assistants ask you before using it. ## Safety - **The assistant can do what the tools offer, and no more.** It can set up an app, record, write, run and read, but cannot delete journeys, change members, create keys or touch billing: none of those are tools. Signed in, it acts with your role (a viewer cannot use it, since every tool call counts as a change); with a key, as a tester. - **A sign-in given to an assistant opens the MCP server only.** It cannot be used against the rest of BitAssure's API, and you can end it by removing the connector in the assistant. To end every sign-in at once, change your password under **Settings → Your account** and tick **Sign out from other devices**. - **Sign in once, then never again.** Record signing in as its own journey (by hand, or with a test account), then have the assistant start other journeys after it with `starts_after` or `set_runs_first`. It records them already signed in and never needs the password. - **Use test accounts.** Whatever the assistant types, it also sends to its AI provider, and what is typed into a journey is stored with it. Never give an assistant a real customer's password. - **Credentials for API platforms are set by a person** under the platform in the portal. The assistant writes calls that use them but never sees them. - **Everything is reviewable.** An assistant's journey is an ordinary journey: read it on its **In words** tab, fix it with **Change**, or delete it. ## Limits - Recording on an iPhone through an assistant has not been tried yet. Websites and Android have. - "Scroll until you see…" is not offered. The assistant scrolls and then acts on what came into view. - A phone can take a minute or two to open. `start_recording` then answers that it is still opening, and the assistant asks again. --- # Websites A website platform is checked in Chrome, both while you record and when it runs. Each run gets a fresh browser with no cookies or stored data from earlier runs. ## Setting it up Create a **Web** platform with the website's **Base URL**. Every recording and every run starts by going to that address. To test a staging site or an internal tool that is not on the internet, see [Testing inside your network](/docs/connector). ## What the recorder can do on a page - **Click, type, clear, double-click, hover, press keys.** - **Dropdowns:** **Choose an option** works on a real `