curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/testing-agent/flows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Create a project",
"goal": "Sign up, create a project called Launch, and check that it appears on the dashboard.",
"role": "admin"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/testing-agent/flows"
payload = {
"name": "Create a project",
"goal": "Sign up, create a project called Launch, and check that it appears on the dashboard.",
"role": "admin"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Create a project',
goal: 'Sign up, create a project called Launch, and check that it appears on the dashboard.',
role: 'admin'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/testing-agent/flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/testing-agent/flows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Create a project',
'goal' => 'Sign up, create a project called Launch, and check that it appears on the dashboard.',
'role' => 'admin'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/testing-agent/flows"
payload := strings.NewReader("{\n \"name\": \"Create a project\",\n \"goal\": \"Sign up, create a project called Launch, and check that it appears on the dashboard.\",\n \"role\": \"admin\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.base44.com/api/apps/{app_id}/testing-agent/flows")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Create a project\",\n \"goal\": \"Sign up, create a project called Launch, and check that it appears on the dashboard.\",\n \"role\": \"admin\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/testing-agent/flows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Create a project\",\n \"goal\": \"Sign up, create a project called Launch, and check that it appears on the dashboard.\",\n \"role\": \"admin\"\n}"
response = http.request(request)
puts response.read_body{
"id": "68a1c2e4f0b3d9001a7e5c21",
"app_id": "6820f3a4e7b91d003c45a1f2",
"name": "Create a project",
"goal": "Sign up, create a project called Launch, and check that it appears on the dashboard.",
"source": "manual",
"revision": 1,
"created_date": "2026-09-28T10:15:00+00:00",
"updated_date": "2026-09-28T10:15:00+00:00",
"role": "admin"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Create test
Adds a test to the app. A test is a goal written in plain language that the testing agent tries to accomplish in a real browser when you run it.
Set role to run the test as a user with that role. Leave it out and Base44 picks a role named in the test’s name or goal, such as “as an admin”, or runs as a regular user when neither names one.
An app can have up to 250 tests. Creating a test is free. Running it costs credits.
This is limited to 300 requests per minute per caller for each app. Some workspaces have a different limit.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/testing-agent/flows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Create a project",
"goal": "Sign up, create a project called Launch, and check that it appears on the dashboard.",
"role": "admin"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/testing-agent/flows"
payload = {
"name": "Create a project",
"goal": "Sign up, create a project called Launch, and check that it appears on the dashboard.",
"role": "admin"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Create a project',
goal: 'Sign up, create a project called Launch, and check that it appears on the dashboard.',
role: 'admin'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/testing-agent/flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/testing-agent/flows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Create a project',
'goal' => 'Sign up, create a project called Launch, and check that it appears on the dashboard.',
'role' => 'admin'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/testing-agent/flows"
payload := strings.NewReader("{\n \"name\": \"Create a project\",\n \"goal\": \"Sign up, create a project called Launch, and check that it appears on the dashboard.\",\n \"role\": \"admin\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.base44.com/api/apps/{app_id}/testing-agent/flows")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Create a project\",\n \"goal\": \"Sign up, create a project called Launch, and check that it appears on the dashboard.\",\n \"role\": \"admin\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/testing-agent/flows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Create a project\",\n \"goal\": \"Sign up, create a project called Launch, and check that it appears on the dashboard.\",\n \"role\": \"admin\"\n}"
response = http.request(request)
puts response.read_body{
"id": "68a1c2e4f0b3d9001a7e5c21",
"app_id": "6820f3a4e7b91d003c45a1f2",
"name": "Create a project",
"goal": "Sign up, create a project called Launch, and check that it appears on the dashboard.",
"source": "manual",
"revision": 1,
"created_date": "2026-09-28T10:15:00+00:00",
"updated_date": "2026-09-28T10:15:00+00:00",
"role": "admin"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
Personal access token, sent as Authorization: Bearer <token>.
Path Parameters
ID of the app.
Body
Short name for the test.
1 - 100"Create a project"
What the testing agent should try to do, in plain language.
1 - 500"Sign up, create a project called Launch, and check that it appears on the dashboard."
Role to run the test as, such as admin. Leave it out to let Base44 pick one from the name or goal.
100"admin"
Response
The created test.
Fields the FE actually reads, plus the metadata the runtime slice
needs (role for per-flow role-aware runs, revision for
optimistic-concurrency, source so AI-generated rows can be styled
differently, etc.).
ID of the test.
"68a1c2e4f0b3d9001a7e5c21"
ID of the app the test belongs to.
"6820f3a4e7b91d003c45a1f2"
Short name of the test.
"Create a project"
What the testing agent tries to do, in plain language.
"Sign up, create a project called Launch, and check that it appears on the dashboard."
manual for a test you created, app_context for one Base44 generated from the app.
"manual"
Starts at 1 and goes up each time the test is edited.
1
When the test was created, as an ISO 8601 UTC timestamp.
"2026-09-28T10:15:00+00:00"
When the test last changed, as an ISO 8601 UTC timestamp.
"2026-09-28T10:15:00+00:00"
Role set on the test, or null when none is set. A test without one can still run as a role its name or goal names. The run's flow_role shows the role actually used.
"admin"
Was this page helpful?