curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/branches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"branch_name": "add-contact-form",
"prompt": "Add a contact form to the home page",
"from_message_id": "7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/branches"
payload = {
"branch_name": "add-contact-form",
"prompt": "Add a contact form to the home page",
"from_message_id": "7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19"
}
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({
branch_name: 'add-contact-form',
prompt: 'Add a contact form to the home page',
from_message_id: '7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/branches', 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}/branches",
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([
'branch_name' => 'add-contact-form',
'prompt' => 'Add a contact form to the home page',
'from_message_id' => '7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19'
]),
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}/branches"
payload := strings.NewReader("{\n \"branch_name\": \"add-contact-form\",\n \"prompt\": \"Add a contact form to the home page\",\n \"from_message_id\": \"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19\"\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}/branches")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"branch_name\": \"add-contact-form\",\n \"prompt\": \"Add a contact form to the home page\",\n \"from_message_id\": \"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/branches")
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 \"branch_name\": \"add-contact-form\",\n \"prompt\": \"Add a contact form to the home page\",\n \"from_message_id\": \"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19\"\n}"
response = http.request(request)
puts response.read_body{
"id": "68f1a2b3c4d5e6f708192a3b",
"app_id": "6820f3a4e7b91d003c45a1f2",
"branch_name": "add-contact-form",
"status": "active",
"run_state": {
"state": "ready",
"details": "Restoring checkpoint",
"last_updated_date": "2026-09-28T10:18:40"
},
"code_state": "changed",
"base_checkpoint_id": "6886b8d390dc7e2f4a2c91b3",
"created_by_id": "68a0c1d2e3f4a5b6c7d8e9f0",
"created_by_name": "Jane Doe",
"created_date": "2026-09-28T10:15:00",
"merged_at": "2026-09-29T08:02:11",
"merged_by_id": "68a0c1d2e3f4a5b6c7d8e9f0",
"static_preview_url": "https://preview--6820f3a4e7b91d003c45a1f2--b-d8c647b.base44.app"
}Create branch
Creates a branch of the app from its main branch. The branch has its own copy of the app’s code, so its changes don’t reach main until you merge the branch.
Set branch_name to name the branch, or send prompt and Base44 generates a short name from it. prompt only names the branch. It isn’t sent to the AI. When a generated name is taken, Base44 adds a number to it. A branch_name you choose must not belong to another active or merged branch.
The branch starts from main’s latest saved state. If the AI is working on main at the time, the branch starts from main as it was before that change. Set from_message_id to start from an earlier point instead. Send at least one of branch_name, prompt, and from_message_id.
In this response, created_by_name is always null. Get branch returns it.
This endpoint is limited to 30 requests per minute, shared with Create branch, Delete branch and Merge branch.
curl --request POST \
--url https://app.base44.com/api/apps/{app_id}/branches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"branch_name": "add-contact-form",
"prompt": "Add a contact form to the home page",
"from_message_id": "7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19"
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/branches"
payload = {
"branch_name": "add-contact-form",
"prompt": "Add a contact form to the home page",
"from_message_id": "7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19"
}
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({
branch_name: 'add-contact-form',
prompt: 'Add a contact form to the home page',
from_message_id: '7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19'
})
};
fetch('https://app.base44.com/api/apps/{app_id}/branches', 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}/branches",
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([
'branch_name' => 'add-contact-form',
'prompt' => 'Add a contact form to the home page',
'from_message_id' => '7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19'
]),
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}/branches"
payload := strings.NewReader("{\n \"branch_name\": \"add-contact-form\",\n \"prompt\": \"Add a contact form to the home page\",\n \"from_message_id\": \"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19\"\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}/branches")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"branch_name\": \"add-contact-form\",\n \"prompt\": \"Add a contact form to the home page\",\n \"from_message_id\": \"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/branches")
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 \"branch_name\": \"add-contact-form\",\n \"prompt\": \"Add a contact form to the home page\",\n \"from_message_id\": \"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19\"\n}"
response = http.request(request)
puts response.read_body{
"id": "68f1a2b3c4d5e6f708192a3b",
"app_id": "6820f3a4e7b91d003c45a1f2",
"branch_name": "add-contact-form",
"status": "active",
"run_state": {
"state": "ready",
"details": "Restoring checkpoint",
"last_updated_date": "2026-09-28T10:18:40"
},
"code_state": "changed",
"base_checkpoint_id": "6886b8d390dc7e2f4a2c91b3",
"created_by_id": "68a0c1d2e3f4a5b6c7d8e9f0",
"created_by_name": "Jane Doe",
"created_date": "2026-09-28T10:15:00",
"merged_at": "2026-09-29T08:02:11",
"merged_by_id": "68a0c1d2e3f4a5b6c7d8e9f0",
"static_preview_url": "https://preview--6820f3a4e7b91d003c45a1f2--b-d8c647b.base44.app"
}Authorizations
Personal access token, sent as Authorization: Bearer <token>.
Path Parameters
ID of the app to create the branch in.
Body
The new branch's name, or text to name it from.
Name of the branch. It starts with a letter or digit and contains only letters, digits, ., _, / and -. It can't contain .. or //, end with / or ., start with b44/, or be main, and no part between slashes can start with . or end with .lock. Leave it out to have Base44 name the branch from prompt.
1 - 100"add-contact-form"
Text to name the branch from when you leave out branch_name. Base44 generates a short name from it. An empty string names the branch after your first name and today's date.
"Add a contact form to the home page"
ID of a message in main's conversation, from Read conversation messages. The branch starts from the app as it was when that message was sent, instead of from main's latest state. Without branch_name, the branch is named after the last user message before that one, and prompt is ignored.
64"7f3a1c88-52d4-4a0e-9b31-2c6f0d8e4a19"
Response
The new branch.
A branch of an app.
ID of the branch.
"68f1a2b3c4d5e6f708192a3b"
ID of the app the branch belongs to.
"6820f3a4e7b91d003c45a1f2"
Name of the branch.
"add-contact-form"
active while the branch can still be worked on, merged once it was merged into main, and deleted once it was deleted.
active, merged, deleted "active"
State of the AI's work on the branch, or null if no turn has run on it yet.
Show child attributes
Show child attributes
unchanged when the branch has no code changes of its own to merge into main. changed otherwise, including when Base44 can't tell yet.
unchanged, changed "changed"
ID of the main checkpoint the branch started from, or null if the app had no checkpoint yet.
"6886b8d390dc7e2f4a2c91b3"
ID of the user who created the branch.
"68a0c1d2e3f4a5b6c7d8e9f0"
Display name of the user who created the branch, or the part of their email before the @ when they have no name. null when Base44 can't name them, for example when their account no longer exists.
"Jane Doe"
When the branch was created, as a UTC timestamp in ISO 8601 format.
"2026-09-28T10:15:00"
When the branch was merged into main, as a UTC timestamp in ISO 8601 format, or null if it wasn't.
"2026-09-29T08:02:11"
ID of the user who merged the branch, or null if it wasn't merged or Base44 doesn't know who did, as for a branch whose pull request was merged on GitHub.
"68a0c1d2e3f4a5b6c7d8e9f0"
URL of the branch's preview. It shows the branch only while it's active and once it has been built.
"https://preview--6820f3a4e7b91d003c45a1f2--b-d8c647b.base44.app"
Was this page helpful?